From f857f6bec9aa480569ec48c2ae3e3a4929ab5a3f Mon Sep 17 00:00:00 2001 From: Piotr Sarna Date: Mon, 24 Jun 2019 16:20:26 +0200 Subject: [PATCH] Release 1.5.0 --- .gitignore | 157 +- Podfile | 35 +- Podfile.lock | 68 +- Pods/ActionSheetPicker-3.0/LICENSE | 24 + .../Pickers/AbstractActionSheetPicker.h | 126 + .../Pickers/AbstractActionSheetPicker.m | 804 +++ .../Pickers/ActionSheetCustomPicker.h | 37 + .../Pickers/ActionSheetCustomPicker.m | 125 + .../Pickers/ActionSheetCustomPickerDelegate.h | 39 + .../Pickers/ActionSheetDatePicker.h | 95 + .../Pickers/ActionSheetDatePicker.m | 272 ++ .../Pickers/ActionSheetDistancePicker.h | 39 + .../Pickers/ActionSheetDistancePicker.m | 207 + .../Pickers/ActionSheetLocalePicker.h | 63 + .../Pickers/ActionSheetLocalePicker.m | 408 ++ .../Pickers/ActionSheetMultipleStringPicker.h | 65 + .../Pickers/ActionSheetMultipleStringPicker.m | 225 + .../Pickers/ActionSheetPicker.h | 35 + .../Pickers/ActionSheetStringPicker.h | 62 + .../Pickers/ActionSheetStringPicker.m | 195 + .../Pickers/DistancePickerView.h | 21 + .../Pickers/DistancePickerView.m | 208 + .../Pickers/SWActionSheet.h | 19 + .../Pickers/SWActionSheet.m | 223 + Pods/ActionSheetPicker-3.0/README.md | 230 + Pods/ChameleonFramework/LICENSE.md | 21 + .../Pod/Classes/Objective-C/Chameleon.h | 31 + .../Classes/Objective-C/ChameleonConstants.h | 21 + .../Classes/Objective-C/ChameleonConstants.m | 15 + .../Pod/Classes/Objective-C/ChameleonEnums.h | 39 + .../Pod/Classes/Objective-C/ChameleonMacros.h | 125 + .../Pod/Classes/Objective-C/Chameleon_.h | 66 + .../Pod/Classes/Objective-C/Chameleon_.m | 793 +++ .../Classes/Objective-C/NSArray+Chameleon.h | 112 + .../Classes/Objective-C/NSArray+Chameleon.m | 736 +++ .../Classes/Objective-C/UIAppearance+Swift.h | 17 + .../Classes/Objective-C/UIAppearance+Swift.m | 32 + .../Classes/Objective-C/UIButton+Chameleon.h | 15 + .../Classes/Objective-C/UIButton+Chameleon.m | 23 + .../Classes/Objective-C/UIColor+Chameleon.h | 685 +++ .../Classes/Objective-C/UIColor+Chameleon.m | 1027 ++++ .../Objective-C/UIColor+ChameleonPrivate.h | 36 + .../Objective-C/UIColor+ChameleonPrivate.m | 251 + .../Objective-C/UIImage+ChameleonPrivate.h | 21 + .../Objective-C/UIImage+ChameleonPrivate.m | 74 + .../Classes/Objective-C/UILabel+Chameleon.h | 15 + .../Classes/Objective-C/UILabel+Chameleon.m | 18 + .../UINavigationController+Chameleon.h | 32 + .../UINavigationController+Chameleon.m | 214 + .../Objective-C/UIView+ChameleonPrivate.h | 16 + .../Objective-C/UIView+ChameleonPrivate.m | 46 + .../Objective-C/UIViewController+Chameleon.h | 64 + .../Objective-C/UIViewController+Chameleon.m | 900 ++++ Pods/ChameleonFramework/README.md | 768 +++ Pods/Charts/LICENSE | 202 + Pods/Charts/README.md | 213 + .../Source/Charts/Animation/Animator.swift | 280 ++ .../Animation/ChartAnimationEasing.swift | 394 ++ .../Source/Charts/Charts/BarChartView.swift | 186 + .../Charts/Charts/BarLineChartViewBase.swift | 1958 ++++++++ .../Charts/Charts/BubbleChartView.swift | 27 + .../Charts/Charts/CandleStickChartView.swift | 34 + .../Source/Charts/Charts/ChartViewBase.swift | 1034 ++++ .../Charts/Charts/CombinedChartView.swift | 246 + .../Charts/HorizontalBarChartView.swift | 270 ++ .../Source/Charts/Charts/LineChartView.swift | 28 + .../Source/Charts/Charts/PieChartView.swift | 599 +++ .../Charts/Charts/PieRadarChartViewBase.swift | 837 ++++ .../Source/Charts/Charts/RadarChartView.swift | 220 + .../Charts/Charts/ScatterChartView.swift | 31 + .../Source/Charts/Components/AxisBase.swift | 359 ++ .../Charts/Components/ChartLimitLine.swift | 74 + .../Charts/Components/ComponentBase.swift | 37 + .../Charts/Components/Description.swift | 46 + .../Source/Charts/Components/IMarker.swift | 39 + .../Source/Charts/Components/Legend.swift | 420 ++ .../Charts/Components/LegendEntry.swift | 88 + .../Charts/Components/MarkerImage.swift | 106 + .../Source/Charts/Components/MarkerView.swift | 95 + .../Source/Charts/Components/XAxis.swift | 75 + .../Source/Charts/Components/YAxis.swift | 198 + .../Implementations/ChartBaseDataSet.swift | 435 ++ .../Standard/BarChartData.swift | 107 + .../Standard/BarChartDataEntry.swift | 230 + .../Standard/BarChartDataSet.swift | 167 + .../BarLineScatterCandleBubbleChartData.swift | 25 + ...rLineScatterCandleBubbleChartDataSet.swift | 38 + .../Standard/BubbleChartData.swift | 32 + .../Standard/BubbleChartDataEntry.swift | 79 + .../Standard/BubbleChartDataSet.swift | 58 + .../Standard/CandleChartData.swift | 25 + .../Standard/CandleChartDataEntry.swift | 98 + .../Standard/CandleChartDataSet.swift | 136 + .../Implementations/Standard/ChartData.swift | 612 +++ .../Standard/ChartDataEntry.swift | 110 + .../Standard/ChartDataEntryBase.swift | 96 + .../Standard/ChartDataSet.swift | 576 +++ .../Standard/CombinedChartData.swift | 301 ++ .../Standard/LineChartData.swift | 26 + .../Standard/LineChartDataSet.swift | 173 + .../Standard/LineRadarChartDataSet.swift | 85 + .../LineScatterCandleRadarChartDataSet.swift | 51 + .../Standard/PieChartData.swift | 124 + .../Standard/PieChartDataEntry.swift | 119 + .../Standard/PieChartDataSet.swift | 135 + .../Standard/RadarChartData.swift | 46 + .../Standard/RadarChartDataEntry.swift | 54 + .../Standard/RadarChartDataSet.swift | 59 + .../Standard/ScatterChartData.swift | 34 + .../Standard/ScatterChartDataSet.swift | 78 + .../Data/Interfaces/IBarChartDataSet.swift | 42 + ...rLineScatterCandleBubbleChartDataSet.swift | 26 + .../Data/Interfaces/IBubbleChartDataSet.swift | 27 + .../Data/Interfaces/ICandleChartDataSet.swift | 66 + .../Data/Interfaces/IChartDataSet.swift | 270 ++ .../Data/Interfaces/ILineChartDataSet.swift | 80 + .../Interfaces/ILineRadarChartDataSet.swift | 45 + .../ILineScatterCandleRadarChartDataSet.swift | 36 + .../Data/Interfaces/IPieChartDataSet.swift | 64 + .../Data/Interfaces/IRadarChartDataSet.swift | 40 + .../Interfaces/IScatterChartDataSet.swift | 36 + .../Charts/Filters/DataApproximator+N.swift | 152 + .../Charts/Filters/DataApproximator.swift | 115 + .../DefaultAxisValueFormatter.swift | 100 + .../Formatters/DefaultFillFormatter.swift | 58 + .../Formatters/DefaultValueFormatter.swift | 103 + .../Formatters/IAxisValueFormatter.swift | 30 + .../Charts/Formatters/IFillFormatter.swift | 21 + .../Charts/Formatters/IValueFormatter.swift | 36 + .../Formatters/IndexAxisValueFormatter.swift | 59 + .../Charts/Highlight/BarHighlighter.swift | 108 + .../Charts/Highlight/ChartHighlighter.swift | 180 + .../Highlight/CombinedHighlighter.swift | 70 + .../Source/Charts/Highlight/Highlight.swift | 203 + .../Highlight/HorizontalBarHighlighter.swift | 63 + .../Charts/Highlight/IHighlighter.swift | 23 + .../Charts/Highlight/PieHighlighter.swift | 27 + .../Highlight/PieRadarHighlighter.swift | 61 + .../Charts/Highlight/RadarHighlighter.swift | 78 + .../Source/Charts/Highlight/Range.swift | 52 + .../Interfaces/BarChartDataProvider.swift | 23 + ...ScatterCandleBubbleChartDataProvider.swift | 23 + .../Interfaces/BubbleChartDataProvider.swift | 19 + .../Interfaces/CandleChartDataProvider.swift | 19 + .../Charts/Interfaces/ChartDataProvider.swift | 39 + .../CombinedChartDataProvider.swift | 19 + .../Interfaces/LineChartDataProvider.swift | 21 + .../Interfaces/ScatterChartDataProvider.swift | 19 + .../Charts/Jobs/AnimatedMoveViewJob.swift | 33 + .../Charts/Jobs/AnimatedViewPortJob.swift | 126 + .../Charts/Jobs/AnimatedZoomViewJob.swift | 96 + .../Source/Charts/Jobs/MoveViewJob.swift | 34 + .../Source/Charts/Jobs/ViewPortJob.swift | 46 + .../Source/Charts/Jobs/ZoomViewJob.swift | 71 + .../Charts/Renderers/AxisRendererBase.swift | 218 + .../Charts/Renderers/BarChartRenderer.swift | 893 ++++ .../BarLineScatterCandleBubbleRenderer.swift | 119 + .../Renderers/BubbleChartRenderer.swift | 359 ++ .../Renderers/CandleStickChartRenderer.swift | 420 ++ .../Renderers/ChartDataRendererBase.swift | 94 + .../Renderers/CombinedChartRenderer.swift | 209 + .../HorizontalBarChartRenderer.swift | 624 +++ .../Charts/Renderers/LegendRenderer.swift | 575 +++ .../Charts/Renderers/LineChartRenderer.swift | 781 +++ .../Charts/Renderers/LineRadarRenderer.swift | 54 + .../LineScatterCandleRadarRenderer.swift | 49 + .../Charts/Renderers/PieChartRenderer.swift | 929 ++++ .../Charts/Renderers/RadarChartRenderer.swift | 475 ++ .../Source/Charts/Renderers/Renderer.swift | 26 + .../Scatter/ChevronDownShapeRenderer.swift | 36 + .../Scatter/ChevronUpShapeRenderer.swift | 36 + .../Scatter/CircleShapeRenderer.swift | 63 + .../Scatter/CrossShapeRenderer.swift | 36 + .../Renderers/Scatter/IShapeRenderer.swift | 32 + .../Scatter/SquareShapeRenderer.swift | 63 + .../Scatter/TriangleShapeRenderer.swift | 66 + .../Renderers/Scatter/XShapeRenderer.swift | 36 + .../Renderers/ScatterChartRenderer.swift | 249 + .../Charts/Renderers/XAxisRenderer.swift | 440 ++ .../XAxisRendererHorizontalBarChart.swift | 356 ++ .../Renderers/XAxisRendererRadarChart.swift | 91 + .../Charts/Renderers/YAxisRenderer.swift | 386 ++ .../YAxisRendererHorizontalBarChart.swift | 363 ++ .../Renderers/YAxisRendererRadarChart.swift | 273 ++ .../Charts/Utils/ChartColorTemplates.swift | 198 + .../Source/Charts/Utils/ChartUtils.swift | 296 ++ Pods/Charts/Source/Charts/Utils/Fill.swift | 323 ++ .../Charts/Utils/Platform+Accessibility.swift | 197 + .../Charts/Source/Charts/Utils/Platform.swift | 629 +++ .../Source/Charts/Utils/Transformer.swift | 170 + .../Utils/TransformerHorizontalBarChart.swift | 32 + .../Source/Charts/Utils/ViewPortHandler.swift | 553 +++ Pods/Eddystone/LICENSE | 19 + Pods/Eddystone/Pod/Classes/Beacon.swift | 206 + .../Pod/Classes/CoreBluetoothExtensions.swift | 53 + .../Pod/Classes/DoubleExtensions.swift | 45 + Pods/Eddystone/Pod/Classes/Frame.swift | 14 + Pods/Eddystone/Pod/Classes/Generic.swift | 41 + Pods/Eddystone/Pod/Classes/Global.swift | 21 + .../Eddystone/Pod/Classes/IntExtensions.swift | 22 + .../Classes/NSTimeIntervalExtensions.swift | 48 + Pods/Eddystone/Pod/Classes/Object.swift | 57 + Pods/Eddystone/Pod/Classes/Scanner.swift | 173 + Pods/Eddystone/Pod/Classes/TlmFrame.swift | 75 + Pods/Eddystone/Pod/Classes/Uid.swift | 20 + Pods/Eddystone/Pod/Classes/UidFrame.swift | 58 + Pods/Eddystone/Pod/Classes/Url.swift | 13 + Pods/Eddystone/Pod/Classes/UrlFrame.swift | 80 + Pods/Eddystone/README.md | 161 + Pods/IP-UIKit-Wisdom/LICENSE | 9 + .../CAGradientLayer+IPGradients.h | 23 + .../CAGradientLayer+IPGradients.m | 24 + .../src/UIButton/UIButton+IPUtils.h | 19 + .../src/UIButton/UIButton+IPUtils.m | 20 + .../src/UIColor/UIColor+IPRandomColor.h | 7 + .../src/UIColor/UIColor+IPRandomColor.m | 12 + .../src/UIImage/UIImage+ColorMaskedImage.h | 14 + .../src/UIImage/UIImage+ColorMaskedImage.m | 16 + .../src/UITableView/UITableView+Utils.h | 32 + .../src/UITableView/UITableView+Utils.m | 48 + .../src/UIView/UIView+Constraints.h | 329 ++ .../src/UIView/UIView+Constraints.m | 274 ++ .../src/UIView/UIView+IPAncestry.h | 20 + .../src/UIView/UIView+IPAncestry.m | 42 + .../src/UIView/UIView+IPFrameUtils.h | 63 + .../src/UIView/UIView+IPFrameUtils.m | 115 + .../src/UIView/UIView+NibInitable.h | 14 + .../src/UIView/UIView+NibInitable.m | 28 + .../UIViewController+Containment.h | 33 + .../UIViewController+Containment.m | 30 + .../FBKVOController/FBKVOController.h | 200 + .../FBKVOController/FBKVOController.m | 676 +++ .../FBKVOController/KVOController.h | 11 + .../NSObject+FBKVOController.h | 42 + .../NSObject+FBKVOController.m | 65 + Pods/KVOController/LICENSE | 30 + Pods/KVOController/README.md | 84 + Pods/Local Podspecs/Eddystone.podspec.json | 27 + Pods/MZTimerLabel/LICENSE | 20 + Pods/MZTimerLabel/MZTimerLabel/MZTimerLabel.h | 132 + Pods/MZTimerLabel/MZTimerLabel/MZTimerLabel.m | 406 ++ Pods/MZTimerLabel/README.md | 172 + Pods/Manifest.lock | 73 + Pods/Pods.xcodeproj/project.pbxproj | 4296 +++++++++++++++++ .../xcschemes/ActionSheetPicker-3.0.xcscheme | 80 + .../xcschemes/ChameleonFramework.xcscheme | 80 + .../xcshareddata/xcschemes/Charts.xcscheme | 80 + .../xcschemes/Eddystone-Eddystone.xcscheme | 80 + .../xcshareddata/xcschemes/Eddystone.xcscheme | 80 + .../xcschemes/IP-UIKit-Wisdom.xcscheme | 80 + .../xcschemes/KVOController.xcscheme | 80 + .../xcschemes/MZTimerLabel.xcscheme | 80 + .../xcschemes/Pods-BlueGecko.xcscheme | 80 + .../Pods-BlueGeckoWithHomeKit.xcscheme | 80 + .../xcschemes/Pods-WirelessGecko.xcscheme | 80 + .../xcschemes/PureLayout.xcscheme | 80 + .../xcschemes/SVProgressHUD.xcscheme | 80 + .../xcschemes/UICircularProgressRing.xcscheme | 80 + .../xcschemes/WYPopoverController.xcscheme | 80 + .../xcschemes/XMLDictionary.xcscheme | 80 + Pods/PureLayout/LICENSE | 9 + .../PureLayout/PureLayout/ALView+PureLayout.h | 242 + .../PureLayout/PureLayout/ALView+PureLayout.m | 1146 +++++ .../PureLayout/NSArray+PureLayout.h | 115 + .../PureLayout/NSArray+PureLayout.m | 505 ++ .../NSLayoutConstraint+PureLayout.h | 84 + .../NSLayoutConstraint+PureLayout.m | 552 +++ .../PureLayout/PureLayout+Internal.h | 87 + .../PureLayout/PureLayout/PureLayout.h | 43 + .../PureLayout/PureLayout/PureLayoutDefines.h | 228 + Pods/PureLayout/README.md | 239 + Pods/SVProgressHUD/LICENSE | 21 + Pods/SVProgressHUD/README.md | 218 + .../SVProgressHUD/SVIndefiniteAnimatedView.h | 17 + .../SVProgressHUD/SVIndefiniteAnimatedView.m | 137 + .../SVProgressHUD/SVProgressAnimatedView.h | 17 + .../SVProgressHUD/SVProgressAnimatedView.m | 96 + .../SVProgressHUD.bundle/angle-mask.png | Bin 0 -> 1845 bytes .../SVProgressHUD.bundle/angle-mask@2x.png | Bin 0 -> 4893 bytes .../SVProgressHUD.bundle/angle-mask@3x.png | Bin 0 -> 8319 bytes .../SVProgressHUD.bundle/error.png | Bin 0 -> 184 bytes .../SVProgressHUD.bundle/error@2x.png | Bin 0 -> 306 bytes .../SVProgressHUD.bundle/error@3x.png | Bin 0 -> 398 bytes .../SVProgressHUD.bundle/info.png | Bin 0 -> 365 bytes .../SVProgressHUD.bundle/info@2x.png | Bin 0 -> 816 bytes .../SVProgressHUD.bundle/info@3x.png | Bin 0 -> 1200 bytes .../SVProgressHUD.bundle/success.png | Bin 0 -> 262 bytes .../SVProgressHUD.bundle/success@2x.png | Bin 0 -> 462 bytes .../SVProgressHUD.bundle/success@3x.png | Bin 0 -> 714 bytes .../SVProgressHUD/SVProgressHUD.h | 147 + .../SVProgressHUD/SVProgressHUD.m | 1509 ++++++ .../SVProgressHUD/SVRadialGradientLayer.h | 14 + .../SVProgressHUD/SVRadialGradientLayer.m | 25 + .../ActionSheetPicker-3.0-dummy.m | 5 + .../ActionSheetPicker-3.0-prefix.pch | 12 + .../ActionSheetPicker-3.0-umbrella.h | 27 + .../ActionSheetPicker-3.0.modulemap | 6 + .../ActionSheetPicker-3.0.xcconfig | 9 + .../ActionSheetPicker-3.0/Info.plist | 26 + .../ChameleonFramework-dummy.m | 5 + .../ChameleonFramework-prefix.pch | 12 + .../ChameleonFramework-umbrella.h | 46 + .../ChameleonFramework.modulemap | 6 + .../ChameleonFramework.xcconfig | 9 + .../ChameleonFramework/Info.plist | 26 + .../Charts/Charts-dummy.m | 5 + .../Charts/Charts-prefix.pch | 12 + .../Charts/Charts-umbrella.h | 16 + .../Charts/Charts.modulemap | 6 + .../Charts/Charts.xcconfig | 9 + Pods/Target Support Files/Charts/Info.plist | 26 + .../Eddystone/Eddystone-dummy.m | 5 + .../Eddystone/Eddystone-prefix.pch | 12 + .../Eddystone/Eddystone-umbrella.h | 16 + .../Eddystone/Eddystone.modulemap | 6 + .../Eddystone/Eddystone.xcconfig | 10 + .../Target Support Files/Eddystone/Info.plist | 26 + .../ResourceBundle-Eddystone-Info.plist | 24 + .../IP-UIKit-Wisdom/IP-UIKit-Wisdom-dummy.m | 5 + .../IP-UIKit-Wisdom-prefix.pch | 12 + .../IP-UIKit-Wisdom-umbrella.h | 26 + .../IP-UIKit-Wisdom/IP-UIKit-Wisdom.modulemap | 6 + .../IP-UIKit-Wisdom/IP-UIKit-Wisdom.xcconfig | 9 + .../IP-UIKit-Wisdom/Info.plist | 26 + .../KVOController/Info.plist | 26 + .../KVOController/KVOController-dummy.m | 5 + .../KVOController/KVOController-prefix.pch | 12 + .../KVOController/KVOController-umbrella.h | 19 + .../KVOController/KVOController.modulemap | 6 + .../KVOController/KVOController.xcconfig | 8 + .../MZTimerLabel/Info.plist | 26 + .../MZTimerLabel/MZTimerLabel-dummy.m | 5 + .../MZTimerLabel/MZTimerLabel-prefix.pch | 12 + .../MZTimerLabel/MZTimerLabel-umbrella.h | 17 + .../MZTimerLabel/MZTimerLabel.modulemap | 6 + .../MZTimerLabel/MZTimerLabel.xcconfig | 8 + .../Pods-BlueGecko/Info.plist | 26 + .../Pods-BlueGecko-acknowledgements.markdown | 440 ++ .../Pods-BlueGecko-acknowledgements.plist | 538 +++ .../Pods-BlueGecko/Pods-BlueGecko-dummy.m | 5 + .../Pods-BlueGecko-frameworks.sh | 175 + .../Pods-BlueGecko-resources.sh | 118 + .../Pods-BlueGecko/Pods-BlueGecko-umbrella.h | 16 + .../Pods-BlueGecko.debug.xcconfig | 11 + .../Pods-BlueGecko/Pods-BlueGecko.modulemap | 6 + .../Pods-BlueGecko.release.xcconfig | 11 + .../Pods-BlueGeckoWithHomeKit/Info.plist | 26 + ...GeckoWithHomeKit-acknowledgements.markdown | 440 ++ ...lueGeckoWithHomeKit-acknowledgements.plist | 538 +++ .../Pods-BlueGeckoWithHomeKit-dummy.m | 5 + .../Pods-BlueGeckoWithHomeKit-frameworks.sh | 175 + .../Pods-BlueGeckoWithHomeKit-resources.sh | 118 + .../Pods-BlueGeckoWithHomeKit-umbrella.h | 16 + .../Pods-BlueGeckoWithHomeKit.debug.xcconfig | 11 + .../Pods-BlueGeckoWithHomeKit.modulemap | 6 + ...Pods-BlueGeckoWithHomeKit.release.xcconfig | 11 + .../Pods-WirelessGecko/Info.plist | 26 + ...ds-WirelessGecko-acknowledgements.markdown | 440 ++ .../Pods-WirelessGecko-acknowledgements.plist | 538 +++ .../Pods-WirelessGecko-dummy.m | 5 + .../Pods-WirelessGecko-frameworks.sh | 175 + .../Pods-WirelessGecko-resources.sh | 118 + .../Pods-WirelessGecko-umbrella.h | 16 + .../Pods-WirelessGecko.debug.xcconfig | 11 + .../Pods-WirelessGecko.modulemap | 6 + .../Pods-WirelessGecko.release.xcconfig | 11 + .../PureLayout/Info.plist | 26 + .../PureLayout/PureLayout-dummy.m | 5 + .../PureLayout/PureLayout-prefix.pch | 12 + .../PureLayout/PureLayout-umbrella.h | 22 + .../PureLayout/PureLayout.modulemap | 6 + .../PureLayout/PureLayout.xcconfig | 8 + .../SVProgressHUD/Info.plist | 26 + .../SVProgressHUD/SVProgressHUD-dummy.m | 5 + .../SVProgressHUD/SVProgressHUD-prefix.pch | 12 + .../SVProgressHUD/SVProgressHUD-umbrella.h | 20 + .../SVProgressHUD/SVProgressHUD.modulemap | 6 + .../SVProgressHUD/SVProgressHUD.xcconfig | 9 + .../UICircularProgressRing/Info.plist | 26 + .../UICircularProgressRing-dummy.m | 5 + .../UICircularProgressRing-prefix.pch | 12 + .../UICircularProgressRing-umbrella.h | 17 + .../UICircularProgressRing.modulemap | 6 + .../UICircularProgressRing.xcconfig | 9 + .../WYPopoverController/Info.plist | 26 + .../WYPopoverController-dummy.m | 5 + .../WYPopoverController-prefix.pch | 12 + .../WYPopoverController-umbrella.h | 18 + .../WYPopoverController.modulemap | 6 + .../WYPopoverController.xcconfig | 9 + .../XMLDictionary/Info.plist | 26 + .../XMLDictionary/XMLDictionary-dummy.m | 5 + .../XMLDictionary/XMLDictionary-prefix.pch | 12 + .../XMLDictionary/XMLDictionary-umbrella.h | 17 + .../XMLDictionary/XMLDictionary.modulemap | 6 + .../XMLDictionary/XMLDictionary.xcconfig | 8 + Pods/UICircularProgressRing/LICENSE | 7 + Pods/UICircularProgressRing/README.md | 126 + .../UICircularProgressRing.h | 18 + .../UICircularProgressRing.swift | 1268 +++++ .../UICircularProgressRingDelegate.swift | 92 + ...CircularProgressRingGradientPosition.swift | 82 + .../UICircularProgressRingLayer.swift | 432 ++ .../UICircularProgressRingStyle.swift | 49 + Pods/WYPopoverController/LICENSE | 9 + Pods/WYPopoverController/README.md | 347 ++ .../WYPopoverController/WYPopoverController.h | 254 + .../WYPopoverController/WYPopoverController.m | 3171 ++++++++++++ .../WYStoryboardPopoverSegue.h | 40 + .../WYStoryboardPopoverSegue.m | 97 + Pods/XMLDictionary/LICENCE.md | 19 + Pods/XMLDictionary/README.md | 239 + .../XMLDictionary/XMLDictionary.h | 118 + .../XMLDictionary/XMLDictionary.m | 564 +++ SiliconLabsApp-Bridging-Header.h | 2 + SiliconLabsApp.pch | 14 - SiliconLabsApp.xcodeproj/project.pbxproj | 1246 +++-- ...outHomeKit.xcscheme => BlueGecko.xcscheme} | 20 +- ...xcscheme => BlueGeckoWithHomeKit.xcscheme} | 20 +- ...sGecko.xcscheme => WirelessGecko.xcscheme} | 57 +- .../contents.xcworkspacedata | 10 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../SILAppSelectionHelpViewController.xib | 51 +- .../SILAppSelectionViewController.xib | 96 +- .../Debug/Popover/SILTextFieldEntryCell.xib | 43 +- ...LDebugCharacteristicTableViewCell~ipad.xib | 160 +- ...ebugCharacteristicTableViewCell~iphone.xib | 210 +- .../RangeTest/RangeTestStoryboard.storyboard | 848 ++++ ...ILRangeTestModeSelectionViewController.xib | 372 ++ .../SILRetailBeaconAppViewController.xib | 109 +- .../SILDeviceSelectionViewController.xib | 61 +- .../BluetoothControllers/SILCentralManager.h | 2 +- .../SILCentralManagerBuilder.m | 6 +- .../BluetoothControllers/SILConstants.h | 5 +- .../BluetoothControllers/SILConstants.m | 5 +- .../SILDiscoveredPeripheral.h | 16 +- .../SILDiscoveredPeripheral.m | 31 +- SiliconLabsApp/Categories/UIImage+SILImages.h | 1 + SiliconLabsApp/Categories/UIImage+SILImages.m | 1 + SiliconLabsApp/Helpers/SILAppearance.m | 4 +- .../SILCharacteristicFieldValueResolver.m | 2 - .../SILCharacteristicTableModel.m | 14 +- .../SILServiceTableModel.m | 8 +- .../Models/DebugDeviceFilterViewModel.swift | 4 +- SiliconLabsApp/Models/EddystoneBeacon.swift | 1 + SiliconLabsApp/Models/EddystoneScanner.swift | 1 + .../SILHomeKitCharacteristicTableModel.m | 4 - SiliconLabsApp/Models/SILApp.h | 3 +- SiliconLabsApp/Models/SILApp.m | 31 +- .../Models/SILOTAFirmwareUpdateManager.m | 81 +- SiliconLabsApp/Models/TLMData.swift | 1 + SiliconLabsApp/SILAppDelegate.m | 4 - .../SupportingFiles/BlueGecko/BlueGecko.pch | 14 + .../BlueGecko/Entitlements.entitlements} | 0 .../Info.plist} | 10 +- .../BlueGeckoWithHomeKit.pch | 14 + .../Entitlements.entitlements} | 0 .../{ => BlueGeckoWithHomeKit}/Info.plist | 14 +- .../SupportingFiles/ExportOptions.plist | 2 + .../AltBeacon.imageset/Contents.json | 0 .../AltBeacon.imageset/beacon_alt-ipad.png | Bin .../AltBeacon.imageset/beacon_alt-ipad@2x.png | Bin .../AltBeacon.imageset/beacon_alt-iphone.png | Bin .../beacon_alt-iphone@2x.png | Bin .../beacon_alt-iphone@3x.png | Bin .../Contents.json | 0 .../Icon-60@2x.png | Bin .../Icon-60@3x.png | Bin .../AppIconBlueGecko.appiconset}/Icon-76.png | Bin .../Icon-76@2x.png | Bin .../Icon-83.5@2x.png | Bin .../Icon-Small-40.png | Bin .../Icon-Small-40@2x-1.png | Bin .../Icon-Small-40@2x.png | Bin .../Icon-Small-40@3x.png | Bin .../Icon-Small.png | Bin .../Icon-Small@2x-1.png | Bin .../Icon-Small@2x.png | Bin .../Icon-Small@3x.png | Bin .../Icon_1024x1024.png | Bin .../Contents.json | 0 .../multiprotocol-60@2x.png | Bin .../multiprotocol-60@3x.png | Bin .../multiprotocol-76.png | Bin .../multiprotocol-76@2x.png | Bin .../multiprotocol-83.5@2x.png | Bin .../multiprotocol-Small-40.png | Bin .../multiprotocol-Small-40@2x-1.png | Bin .../multiprotocol-Small-40@2x.png | Bin .../multiprotocol-Small-40@3x.png | Bin .../multiprotocol-Small.png | Bin .../multiprotocol-Small@2x-1.png | Bin .../multiprotocol-Small@2x.png | Bin .../multiprotocol-Small@3x.png | Bin .../multiprotocol@2x.png | Bin .../BGBeacon.imageset/Contents.json | 0 .../BGBeacon.imageset/beacon_gecko-ipad.png | Bin .../beacon_gecko-ipad@2x.png | Bin .../BGBeacon.imageset/beacon_gecko-iphone.png | Bin .../beacon_gecko-iphone@2x.png | Bin .../beacon_gecko-iphone@3x.png | Bin .../BTMedium.imageset/BT_Medium~ipad.png | Bin .../BTMedium.imageset/BT_Medium~ipad@2x.png | Bin .../BTMedium.imageset/BT_Medium~iphone.png | Bin .../BTMedium.imageset/BT_Medium~iphone@2x.png | Bin .../BTMedium.imageset/BT_Medium~iphone@3x.png | Bin .../BTMedium.imageset/Contents.json | 0 .../BTStrong.imageset/BT_Strong~ipad.png | Bin .../BTStrong.imageset/BT_Strong~ipad@2x.png | Bin .../BTStrong.imageset/BT_Strong~iphone.png | Bin .../BTStrong.imageset/BT_Strong~iphone@2x.png | Bin .../BTStrong.imageset/BT_Strong~iphone@3x.png | Bin .../BTStrong.imageset/Contents.json | 0 .../BTWeak.imageset/BT_Weak~ipad.png | Bin .../BTWeak.imageset/BT_Weak~ipad@2x.png | Bin .../BTWeak.imageset/BT_Weak~iphone.png | Bin .../BTWeak.imageset/BT_Weak~iphone@2x.png | Bin .../BTWeak.imageset/BT_Weak~iphone@3x.png | Bin .../BTWeak.imageset/Contents.json | 0 .../BackIcon.imageset/BackIcon.png | Bin .../BackIcon.imageset/BackIcon@2x.png | Bin .../BackIcon.imageset/BackIcon@3x.png | Bin .../BackIcon.imageset/Contents.json | 0 .../BeaconFar.imageset/Contents.json | 0 .../BeaconFar.imageset/beacon_far-ipad.png | Bin .../BeaconFar.imageset/beacon_far-ipad@2x.png | Bin .../BeaconFar.imageset/beacon_far-iphone.png | Bin .../beacon_far-iphone@2x.png | Bin .../beacon_far-iphone@3x.png | Bin .../BeaconImmediate.imageset/Contents.json | 0 .../beacon_immediate-ipad.png | Bin .../beacon_immediate-ipad@2x.png | Bin .../beacon_immediate-iphone.png | Bin .../beacon_immediate-iphone@2x.png | Bin .../beacon_immediate-iphone@3x.png | Bin .../BeaconNear.imageset/Contents.json | 0 .../BeaconNear.imageset/beacon_near-ipad.png | Bin .../beacon_near-ipad@2x.png | Bin .../beacon_near-iphone.png | Bin .../beacon_near-iphone@2x.png | Bin .../beacon_near-iphone@3x.png | Bin .../Images.xcassets/Contents.json | 0 .../EddystoneBeacon.imageset/Contents.json | 0 .../beacon_eddystone-ipad.png | Bin .../beacon_eddystone-ipad@2x.png | Bin .../beacon_eddystone-iphone.png | Bin .../beacon_eddystone-iphone@2x.png | Bin .../beacon_eddystone-iphone@3x.png | Bin .../Contents.json | 0 .../iconLightBulb-1.png | Bin .../iconLightBulb.png | Bin .../iconLightBulb@2x-1.png | Bin .../iconLightBulb@2x.png | Bin .../iconLightBulb@3x.png | Bin .../HomeDebug.imageset/Contents.json | 0 .../HomeDebug.imageset/home_debug-ipad.png | Bin .../HomeDebug.imageset/home_debug-ipad@2x.png | Bin .../HomeDebug.imageset/home_debug-iphone.png | Bin .../home_debug-iphone@2x.png | Bin .../home_debug-iphone@3x.png | Bin .../HomeHelp.imageset/Contents.json | 0 .../HomeHelp.imageset/Home_Help~ipad.png | Bin .../HomeHelp.imageset/Home_Help~ipad@2x.png | Bin .../HomeHelp.imageset/Home_Help~iphone.png | Bin .../HomeHelp.imageset/Home_Help~iphone@2x.png | Bin .../HomeHelp.imageset/Home_Help~iphone@3x.png | Bin .../HomeKeyFOB.imageset/Contents.json | 0 .../HomeKeyFOB.imageset/Home_Key_FOB~ipad.png | Bin .../Home_Key_FOB~ipad@2x.png | Bin .../Home_Key_FOB~iphone.png | Bin .../Home_Key_FOB~iphone@2x.png | Bin .../Home_Key_FOB~iphone@3x.png | Bin .../HomeKitDebug.imageset/Contents.json | 0 .../homekit_debug-ipad.png | Bin .../homekit_debug-ipad@2x.png | Bin .../homekit_debug-iphone.png | Bin .../homekit_debug-iphone@2x.png | Bin .../homekit_debug-iphone@3x.png | Bin .../Contents.json | 0 .../debug_prop_broadcast.png | Bin .../debug_prop_broadcast@2x.png | Bin .../debug_prop_broadcast@3x.png | Bin .../Contents.json | 0 .../debug_prop_broadcast@3x.png | Bin .../debug_prop_ext.png | Bin .../debug_prop_ext@2x.png | Bin .../Contents.json | 0 .../debug_prop_indicate.png | Bin .../debug_prop_indicate@2x.png | Bin .../debug_prop_indicate@3x.png | Bin .../HomePropertyNotify.imageset/Contents.json | 0 .../debug_prop_notify.png | Bin .../debug_prop_notify@2x.png | Bin .../debug_prop_notify@3x.png | Bin .../HomePropertyRead.imageset/Contents.json | 0 .../debug_prop_read.png | Bin .../debug_prop_read@2x.png | Bin .../debug_prop_read@3x.png | Bin .../Contents.json | 0 .../debug_prop_signed_write.png | Bin .../debug_prop_signed_write@2x.png | Bin .../debug_prop_signed_write@3x.png | Bin .../HomePropertyWrite.imageset/Contents.json | 0 .../debug_prop_write.png | Bin .../debug_prop_write@2x.png | Bin .../debug_prop_write@3x.png | Bin .../Contents.json | 0 .../debug_prop_write_no_resp.png | Bin .../debug_prop_write_no_resp@2x.png | Bin .../debug_prop_write_no_resp@3x.png | Bin .../HomeRangeTestDemo.imageset/Contents.json | 33 + .../Range_Icon~ipad.png | Bin 0 -> 5360 bytes .../Range_Icon~ipad@2x.png | Bin 0 -> 8949 bytes .../Range_Icon~iphone.png | Bin 0 -> 4324 bytes .../Range_Icon~iphone@2x.png | Bin 0 -> 6939 bytes .../Range_Icon~iphone@3x.png | Bin 0 -> 9514 bytes .../HomeRemoteKeyboard.imageset/Contents.json | 0 .../Home_Remote_Keyboard.png | Bin .../Home_Remote_Keyboard@2x.png | Bin .../HomeRetailBeacon.imageset/Contents.json | 0 .../Home_Retail_Beacon~ipad.png | Bin .../Home_Retail_Beacon~ipad@2x.png | Bin .../Home_Retail_Beacon~iphone.png | Bin .../Home_Retail_Beacon~iphone@2x.png | Bin .../Home_Retail_Beacon~iphone@3x.png | Bin .../HomeSmartWatch.imageset/Contents.json | 0 .../Home_Smart_Watch.png | Bin .../Home_Smart_Watch@2x.png | Bin .../HomeThermometer.imageset/Contents.json | 0 .../Home_Thermometer~ipad.png | Bin .../Home_Thermometer~ipad@2x.png | Bin .../Home_Thermometer~iphone.png | Bin .../Home_Thermometer~iphone@2x.png | Bin .../Home_Thermometer~iphone@3x.png | Bin .../IBeacon.imageset/Contents.json | 0 .../IBeacon.imageset/beacon_ibeacon-ipad.png | Bin .../beacon_ibeacon-ipad@2x.png | Bin .../beacon_ibeacon-iphone.png | Bin .../beacon_ibeacon-iphone@2x.png | Bin .../beacon_ibeacon-iphone@3x.png | Bin .../KeyFOBAverage.imageset/Contents.json | 0 .../Key_FOB_Average~ipad.png | Bin .../Key_FOB_Average~ipad@2x.png | Bin .../Key_FOB_Average~iphone.png | Bin .../Key_FOB_Average~iphone@2x.png | Bin .../Key_FOB_Average~iphone@3x.png | Bin .../KeyFOBGood.imageset/Contents.json | 0 .../KeyFOBGood.imageset/Key_FOB_Good~ipad.png | Bin .../Key_FOB_Good~ipad@2x.png | Bin .../Key_FOB_Good~iphone.png | Bin .../Key_FOB_Good~iphone@2x.png | Bin .../Key_FOB_Good~iphone@3x.png | Bin .../KeyFOBLED.imageset/Contents.json | 0 .../KeyFOBLED.imageset/Key_FOB_LED~ipad.png | Bin .../Key_FOB_LED~ipad@2x.png | Bin .../KeyFOBLED.imageset/Key_FOB_LED~iphone.png | Bin .../Key_FOB_LED~iphone@2x.png | Bin .../Key_FOB_LED~iphone@3x.png | Bin .../KeyFOBLEDLight.imageset/Contents.json | 0 .../Key_FOB_LED_Light~ipad.png | Bin .../Key_FOB_LED_Light~ipad@2x.png | Bin .../Key_FOB_LED_Light~iphone.png | Bin .../Key_FOB_LED_Light~iphone@2x.png | Bin .../Key_FOB_LED_Light~iphone@3x.png | Bin .../KeyFOBWeak.imageset/Contents.json | 0 .../KeyFOBWeak.imageset/Key_FOB_Weak~ipad.png | Bin .../Key_FOB_Weak~ipad@2x.png | Bin .../Key_FOB_Weak~iphone.png | Bin .../Key_FOB_Weak~iphone@2x.png | Bin .../Key_FOB_Weak~iphone@3x.png | Bin .../Keyboard.imageset/Contents.json | 0 .../Keyboard.imageset/Keyboard.png | Bin .../Keyboard.imageset/Keyboard@2x.png | Bin .../KeyboardCheckmark.imageset/Contents.json | 0 .../Keyboard_Checkmark.png | Bin .../Keyboard_Checkmark@2x.png | Bin .../LaunchImage.launchimage/Contents.json | 0 .../launch_screen-568@2x.png | Bin .../launch_screen-iphone@2x.png | Bin .../LaunchImage.launchimage/launch_screen.png | Bin .../launch_screen@2x.png | Bin .../Contents.json | 0 .../debug_prop_indicate_disabled.png | Bin .../Contents.json | 0 .../debug_prop_indicate.png | Bin .../Contents.json | 0 .../debug_prop_notify_disabled.png | Bin .../Contents.json | 0 .../debug_prop_notify.png | Bin .../Contents.json | 0 .../debug_prop_read_disabled.png | Bin .../Contents.json | 0 .../debug_prop_read.png | Bin .../Contents.json | 0 .../debug_prop_write_disabled.png | Bin .../Contents.json | 0 .../debug_prop_write.png | Bin .../Contents.json | 0 .../no_response_grey.png | Bin .../Contents.json | 0 .../no_response_red.png | Bin .../RetailBigRadar.imageset/Contents.json | 0 .../Retail_Big_Radar~ipad.png | Bin .../Retail_Big_Radar~ipad@2x.png | Bin .../Retail_Big_Radar~iphone.png | Bin .../Retail_Big_Radar~iphone@2x.png | Bin .../Retail_Big_Radar~iphone@3x.png | Bin .../RetailMessage.imageset/Contents.json | 0 .../Retail_Message~ipad.png | Bin .../Retail_Message~ipad@2x.png | Bin .../Retail_Message~iphone.png | Bin .../Retail_Message~iphone@2x.png | Bin .../Retail_Message~iphone@3x.png | Bin .../RetailSmallRadar.imageset/Contents.json | 0 .../retail_small_radar-ipad.png | Bin .../retail_small_radar-ipad@2x.png | Bin .../retail_small_radar-iphone.png | Bin .../retail_small_radar-iphone@2x.png | Bin .../retail_small_radar-iphone@3x.png | Bin .../SiliconLabsLogo.imageset/Contents.json | 0 .../Silicon_Labs_Logo~ipad.png | Bin .../Silicon_Labs_Logo~ipad@2x.png | Bin .../Silicon_Labs_Logo~iphone.png | Bin .../Silicon_Labs_Logo~iphone@2x.png | Bin .../Silicon_Labs_Logo~iphone@3x.png | Bin .../ThermometerAdd.imageset/Contents.json | 0 .../Thermometer_Add.png | Bin .../Thermometer_Add@2x.png | Bin .../Thermometer_Add@3x.png | Bin .../ThermometerClear.imageset/Contents.json | 0 .../Thermometer_Clear.png | Bin .../Thermometer_Clear@2x.png | Bin .../Thermometer_Clear@3x.png | Bin .../WatchCalendar.imageset/Contents.json | 0 .../WatchCalendar.imageset/Watch_Calendar.png | Bin .../Watch_Calendar@2x.png | Bin .../WatchPairMode.imageset/Contents.json | 0 .../Watch_Pair_Mode.png | Bin .../Watch_Pair_Mode@2x.png | Bin .../WatchPhoneCall.imageset/Contents.json | 0 .../Watch_Phone_Call.png | Bin .../Watch_Phone_Call@2x.png | Bin .../WatchSuccess.imageset/Contents.json | 0 .../WatchSuccess.imageset/Watch_Success.png | Bin .../Watch_Success@2x.png | Bin .../ad_info.imageset/Contents.json | 0 .../ad_info.imageset/ad_info.png | Bin .../ad_info.imageset/ad_info@2x.png | Bin .../ad_info.imageset/ad_info@3x.png | Bin .../blue_arrow.imageset/Contents.json | 33 + .../blue_arrow.imageset/blue_arrow~ipad.png | Bin 0 -> 2203 bytes .../blue_arrow~ipad@2x.png | Bin 0 -> 3127 bytes .../blue_arrow.imageset/blue_arrow~iphone.png | Bin 0 -> 1937 bytes .../blue_arrow~iphone@2x.png | Bin 0 -> 2617 bytes .../blue_arrow~iphone@3x.png | Bin 0 -> 3630 bytes .../cancelScanning.imageset/Contents.json | 21 + .../cancelScanning.png | Bin 0 -> 15828 bytes .../checkmark.imageset/Contents.json | 0 .../checkmark.imageset/checkmark-ipad.png | Bin .../checkmark.imageset/checkmark-ipad@2x.png | Bin .../checkmark.imageset/checkmark-iphone.png | Bin .../checkmark-iphone@2x.png | Bin .../checkmark-iphone@3x.png | Bin .../chevron_collapsed.imageset/Contents.json | 0 .../chevron_collapsed.imageset/view_more.png | Bin .../view_more@2x.png | Bin .../view_more@3x.png | Bin .../chevron_expanded.imageset/Contents.json | 0 .../view_more_up.png | Bin .../view_more_up_2x.png | Bin .../view_more_up_3x.png | Bin .../clearText.imageset/Contents.json | 0 .../clearText.imageset/clearText.png | Bin .../clearText.imageset/clearText@2x.png | Bin .../clearText.imageset/clearText@3x.png | Bin .../debug_error.imageset/Contents.json | 0 .../debug_error.imageset/debug_error.png | Bin .../debug_error.imageset/debug_error@2x.png | Bin .../debug_error.imageset/debug_error@3x.png | Bin .../Contents.json | 0 .../debug_loading_spinner.png | Bin .../debug_loading_spinner@2x.png | Bin .../debug_loading_spinner@3x.png | Bin .../debug_not_found.imageset/Contents.json | 0 .../debug_not_found-ipad.png | Bin .../debug_not_found-ipad@2x.png | Bin .../debug_not_found-iphone.png | Bin .../debug_not_found-iphone@2x.png | Bin .../debug_not_found-iphone@3x.png | Bin .../debug_refresh.imageset/Contents.json | 0 .../debug_refresh.imageset/debug_refresh.png | Bin .../debug_refresh@2x.png | Bin .../debug_refresh@3x.png | Bin .../debug_scanning.imageset/Contents.json | 0 .../debug_scanning-ipad.png | Bin .../debug_scanning-ipad@2x.png | Bin .../debug_scanning-iphone.png | Bin .../debug_scanning-iphone@2x.png | Bin .../debug_scanning-iphone@3x.png | Bin .../Contents.json | 0 .../debug_scanning_indicator-iphone.png | Bin .../debug_scanning_indicator-iphone@2x.png | Bin .../debug_scanning_indicator-iphone@3x.png | Bin .../Contents.json | 0 .../homekit_debug_scanning-ipad.png | Bin .../homekit_debug_scanning-ipad@2x.png | Bin .../homekit_debug_scanning-iphone.png | Bin .../homekit_debug_scanning-iphone@2x.png | Bin .../homekit_debug_scanning-iphone@3x.png | Bin .../icFilter.imageset/Contents.json | 0 .../icFilter.imageset/icFilter.png | Bin .../icFilter.imageset/icFilter@2x.png | Bin .../icFilter.imageset/icFilter@3x.png | Bin .../icRssi.imageset/Contents.json | 0 .../icRssi.imageset/icRssi.png | Bin .../icRssi.imageset/icRssi@2x.png | Bin .../icRssi.imageset/icRssi@3x.png | Bin .../icSearchName.imageset/Contents.json | 0 .../icSearchName.imageset/icSearchName.png | Bin .../icSearchName.imageset/icSearchName@2x.png | Bin .../icSearchName.imageset/icSearchName@3x.png | Bin .../iconBleConnect.imageset/Contents.json | 23 + .../iconBleConnect.imageset/svgexport-15.png | Bin 0 -> 14464 bytes .../iconBleConnect.imageset/svgexport-16.png | Bin 0 -> 9611 bytes .../iconBleConnect.imageset/svgexport-17.png | Bin 0 -> 3944 bytes .../iconBluetooth.imageset/Contents.json | 0 .../iconBluetooth.imageset/iconBluetooth.png | Bin .../iconBluetooth@2x.png | Bin .../iconBluetooth@3x.png | Bin .../iconProprietary.imageset/Contents.json | 0 .../iconProprietary.png | Bin .../iconThread.imageset/Contents.json | 23 + .../Thread_logomark_rgb@1x.png | Bin 0 -> 3087 bytes .../Thread_logomark_rgb@2x.png | Bin 0 -> 6184 bytes .../Thread_logomark_rgb@3x.png | Bin 0 -> 8839 bytes .../iconZigbee.imageset/Contents.json | 0 .../iconZigbee.imageset/iconZigbee.png | Bin .../iconZigbee.imageset/iconZigbee@2x.png | Bin .../iconZigbee.imageset/iconZigbee@3x.png | Bin .../lightOff.imageset/Contents.json | 0 .../lightOff.imageset/lightOff.png | Bin .../lightOff.imageset/lightOff@2x.png | Bin .../lightOff.imageset/lightOff@3x.png | Bin .../lightOn.imageset/Contents.json | 0 .../lightOn.imageset/lightOn.png | Bin .../lightOn.imageset/lightOn@2x.png | Bin .../lightOn.imageset/lightOn@3x.png | Bin .../radio_off.imageset/Contents.json | 0 .../radio_off.imageset/radio_off.png | Bin .../radio_off.imageset/radio_off@2x.png | Bin .../radio_off.imageset/radio_off@3x.png | Bin .../radio_on.imageset/Contents.json | 0 .../radio_on.imageset/radio_on.png | Bin .../radio_on.imageset/radio_on@2x.png | Bin .../radio_on.imageset/radio_on@3x.png | Bin .../red_arrow.imageset/Contents.json | 33 + .../red_arrow.imageset/red_arrow~ipad.png | Bin 0 -> 855 bytes .../red_arrow.imageset/red_arrow~ipad@2x.png | Bin 0 -> 1760 bytes .../red_arrow.imageset/red_arrow~iphone.png | Bin 0 -> 580 bytes .../red_arrow~iphone@2x.png | Bin 0 -> 1256 bytes .../red_arrow~iphone@3x.png | Bin 0 -> 2168 bytes .../right_chevron.imageset/Contents.json | 0 .../right_chevron.imageset/right_chevron.png | Bin .../right_chevron@2x.png | Bin .../right_chevron@3x.png | Bin .../startScanning.imageset/Contents.json | 21 + .../startScanning.imageset/startScanning.png | Bin 0 -> 3903 bytes .../updateCheckmark.imageset/Contents.json | 0 .../updateCheckmark.png | Bin .../updateCheckmark@2x.png | Bin .../updateCheckmark@3x.png | Bin .../WirelessGecko/Entitlements.entitlements | 18 + .../SupportingFiles/WirelessGecko/Info.plist | 134 + .../WirelessGecko/WirelessGecko.pch | 14 + .../SILAppSelectionViewController.m | 54 +- .../SILAppSelectionHelpViewController.m | 15 +- .../SILConnectedLightingViewController.m | 47 +- .../SILConnectedLightingViewController.xib | 25 +- .../DebugDeviceFilterViewController.swift | 3 +- .../DebugApp/SILActivityBarViewController.m | 55 +- .../DebugApp/SILOTAProgressViewController.m | 2 +- .../DebugApp/SILOTAProgressViewController.xib | 9 +- .../DebugApp/SILOTASetupViewController.m | 109 +- .../DebugApp/SILOTAUICoordinator.m | 140 +- .../SILDebugCharacteristicTableViewCell.m | 91 +- .../SILDebugServicesViewController.m | 35 +- .../SILDeviceSelectionViewController.m | 17 +- .../SILHomeKitDebugServicesViewController.m | 2 - .../Board/SILRangeTestBoardFeatures.swift | 39 + .../Board/SILRangeTestBoardInfo.swift | 21 + .../SILRangeTestCharacteristic.swift | 201 + .../SILRangeTestManufacturerData.swift | 60 + .../Peripheral/SILRangeTestPeripheral.swift | 695 +++ .../SILRangeTestAppViewController.swift | 756 +++ .../SILRangeTestAppViewModel.swift | 460 ++ ...RangeTestModeSelectionViewController.swift | 178 + .../SILRangeTestMovingAverageCalculator.swift | 63 + .../SILRangeTestSettingValue.swift | 71 + .../SILRangeTestTXValueUpdater.swift | 54 + .../RetailBeaconApp/SILBeaconRegistry.m | 3 - .../SILRetailBeaconAppViewController.m | 49 +- .../ViewModels/DebugDeviceViewModel.swift | 1 + .../ViewModels/SILDeviceSelectionViewModel.m | 53 +- .../SILOTAFirmwareUpdateViewModel.m | 24 +- .../Views/RSSISliderTableViewCell.swift | 6 +- SiliconLabsApp/Views/SILAlertBarView.m | 16 +- .../Views/TextFieldTableViewCell.swift | 8 +- SiliconLabsAppWithoutHomeKit.pch | 14 - 908 files changed, 69158 insertions(+), 1176 deletions(-) create mode 100644 Pods/ActionSheetPicker-3.0/LICENSE create mode 100755 Pods/ActionSheetPicker-3.0/Pickers/AbstractActionSheetPicker.h create mode 100755 Pods/ActionSheetPicker-3.0/Pickers/AbstractActionSheetPicker.m create mode 100644 Pods/ActionSheetPicker-3.0/Pickers/ActionSheetCustomPicker.h create mode 100644 Pods/ActionSheetPicker-3.0/Pickers/ActionSheetCustomPicker.m create mode 100644 Pods/ActionSheetPicker-3.0/Pickers/ActionSheetCustomPickerDelegate.h create mode 100755 Pods/ActionSheetPicker-3.0/Pickers/ActionSheetDatePicker.h create mode 100755 Pods/ActionSheetPicker-3.0/Pickers/ActionSheetDatePicker.m create mode 100644 Pods/ActionSheetPicker-3.0/Pickers/ActionSheetDistancePicker.h create mode 100644 Pods/ActionSheetPicker-3.0/Pickers/ActionSheetDistancePicker.m create mode 100644 Pods/ActionSheetPicker-3.0/Pickers/ActionSheetLocalePicker.h create mode 100644 Pods/ActionSheetPicker-3.0/Pickers/ActionSheetLocalePicker.m create mode 100644 Pods/ActionSheetPicker-3.0/Pickers/ActionSheetMultipleStringPicker.h create mode 100644 Pods/ActionSheetPicker-3.0/Pickers/ActionSheetMultipleStringPicker.m create mode 100644 Pods/ActionSheetPicker-3.0/Pickers/ActionSheetPicker.h create mode 100644 Pods/ActionSheetPicker-3.0/Pickers/ActionSheetStringPicker.h create mode 100644 Pods/ActionSheetPicker-3.0/Pickers/ActionSheetStringPicker.m create mode 100644 Pods/ActionSheetPicker-3.0/Pickers/DistancePickerView.h create mode 100644 Pods/ActionSheetPicker-3.0/Pickers/DistancePickerView.m create mode 100644 Pods/ActionSheetPicker-3.0/Pickers/SWActionSheet.h create mode 100644 Pods/ActionSheetPicker-3.0/Pickers/SWActionSheet.m create mode 100644 Pods/ActionSheetPicker-3.0/README.md create mode 100755 Pods/ChameleonFramework/LICENSE.md create mode 100755 Pods/ChameleonFramework/Pod/Classes/Objective-C/Chameleon.h create mode 100755 Pods/ChameleonFramework/Pod/Classes/Objective-C/ChameleonConstants.h create mode 100755 Pods/ChameleonFramework/Pod/Classes/Objective-C/ChameleonConstants.m create mode 100755 Pods/ChameleonFramework/Pod/Classes/Objective-C/ChameleonEnums.h create mode 100755 Pods/ChameleonFramework/Pod/Classes/Objective-C/ChameleonMacros.h create mode 100755 Pods/ChameleonFramework/Pod/Classes/Objective-C/Chameleon_.h create mode 100755 Pods/ChameleonFramework/Pod/Classes/Objective-C/Chameleon_.m create mode 100755 Pods/ChameleonFramework/Pod/Classes/Objective-C/NSArray+Chameleon.h create mode 100755 Pods/ChameleonFramework/Pod/Classes/Objective-C/NSArray+Chameleon.m create mode 100755 Pods/ChameleonFramework/Pod/Classes/Objective-C/UIAppearance+Swift.h create mode 100755 Pods/ChameleonFramework/Pod/Classes/Objective-C/UIAppearance+Swift.m create mode 100755 Pods/ChameleonFramework/Pod/Classes/Objective-C/UIButton+Chameleon.h create mode 100755 Pods/ChameleonFramework/Pod/Classes/Objective-C/UIButton+Chameleon.m create mode 100755 Pods/ChameleonFramework/Pod/Classes/Objective-C/UIColor+Chameleon.h create mode 100755 Pods/ChameleonFramework/Pod/Classes/Objective-C/UIColor+Chameleon.m create mode 100755 Pods/ChameleonFramework/Pod/Classes/Objective-C/UIColor+ChameleonPrivate.h create mode 100755 Pods/ChameleonFramework/Pod/Classes/Objective-C/UIColor+ChameleonPrivate.m create mode 100755 Pods/ChameleonFramework/Pod/Classes/Objective-C/UIImage+ChameleonPrivate.h create mode 100755 Pods/ChameleonFramework/Pod/Classes/Objective-C/UIImage+ChameleonPrivate.m create mode 100755 Pods/ChameleonFramework/Pod/Classes/Objective-C/UILabel+Chameleon.h create mode 100755 Pods/ChameleonFramework/Pod/Classes/Objective-C/UILabel+Chameleon.m create mode 100755 Pods/ChameleonFramework/Pod/Classes/Objective-C/UINavigationController+Chameleon.h create mode 100755 Pods/ChameleonFramework/Pod/Classes/Objective-C/UINavigationController+Chameleon.m create mode 100755 Pods/ChameleonFramework/Pod/Classes/Objective-C/UIView+ChameleonPrivate.h create mode 100755 Pods/ChameleonFramework/Pod/Classes/Objective-C/UIView+ChameleonPrivate.m create mode 100755 Pods/ChameleonFramework/Pod/Classes/Objective-C/UIViewController+Chameleon.h create mode 100755 Pods/ChameleonFramework/Pod/Classes/Objective-C/UIViewController+Chameleon.m create mode 100644 Pods/ChameleonFramework/README.md create mode 100644 Pods/Charts/LICENSE create mode 100644 Pods/Charts/README.md create mode 100644 Pods/Charts/Source/Charts/Animation/Animator.swift create mode 100644 Pods/Charts/Source/Charts/Animation/ChartAnimationEasing.swift create mode 100644 Pods/Charts/Source/Charts/Charts/BarChartView.swift create mode 100644 Pods/Charts/Source/Charts/Charts/BarLineChartViewBase.swift create mode 100644 Pods/Charts/Source/Charts/Charts/BubbleChartView.swift create mode 100644 Pods/Charts/Source/Charts/Charts/CandleStickChartView.swift create mode 100644 Pods/Charts/Source/Charts/Charts/ChartViewBase.swift create mode 100644 Pods/Charts/Source/Charts/Charts/CombinedChartView.swift create mode 100644 Pods/Charts/Source/Charts/Charts/HorizontalBarChartView.swift create mode 100644 Pods/Charts/Source/Charts/Charts/LineChartView.swift create mode 100644 Pods/Charts/Source/Charts/Charts/PieChartView.swift create mode 100644 Pods/Charts/Source/Charts/Charts/PieRadarChartViewBase.swift create mode 100644 Pods/Charts/Source/Charts/Charts/RadarChartView.swift create mode 100644 Pods/Charts/Source/Charts/Charts/ScatterChartView.swift create mode 100644 Pods/Charts/Source/Charts/Components/AxisBase.swift create mode 100644 Pods/Charts/Source/Charts/Components/ChartLimitLine.swift create mode 100644 Pods/Charts/Source/Charts/Components/ComponentBase.swift create mode 100644 Pods/Charts/Source/Charts/Components/Description.swift create mode 100644 Pods/Charts/Source/Charts/Components/IMarker.swift create mode 100644 Pods/Charts/Source/Charts/Components/Legend.swift create mode 100644 Pods/Charts/Source/Charts/Components/LegendEntry.swift create mode 100644 Pods/Charts/Source/Charts/Components/MarkerImage.swift create mode 100644 Pods/Charts/Source/Charts/Components/MarkerView.swift create mode 100644 Pods/Charts/Source/Charts/Components/XAxis.swift create mode 100644 Pods/Charts/Source/Charts/Components/YAxis.swift create mode 100644 Pods/Charts/Source/Charts/Data/Implementations/ChartBaseDataSet.swift create mode 100644 Pods/Charts/Source/Charts/Data/Implementations/Standard/BarChartData.swift create mode 100644 Pods/Charts/Source/Charts/Data/Implementations/Standard/BarChartDataEntry.swift create mode 100644 Pods/Charts/Source/Charts/Data/Implementations/Standard/BarChartDataSet.swift create mode 100644 Pods/Charts/Source/Charts/Data/Implementations/Standard/BarLineScatterCandleBubbleChartData.swift create mode 100644 Pods/Charts/Source/Charts/Data/Implementations/Standard/BarLineScatterCandleBubbleChartDataSet.swift create mode 100644 Pods/Charts/Source/Charts/Data/Implementations/Standard/BubbleChartData.swift create mode 100644 Pods/Charts/Source/Charts/Data/Implementations/Standard/BubbleChartDataEntry.swift create mode 100644 Pods/Charts/Source/Charts/Data/Implementations/Standard/BubbleChartDataSet.swift create mode 100644 Pods/Charts/Source/Charts/Data/Implementations/Standard/CandleChartData.swift create mode 100644 Pods/Charts/Source/Charts/Data/Implementations/Standard/CandleChartDataEntry.swift create mode 100644 Pods/Charts/Source/Charts/Data/Implementations/Standard/CandleChartDataSet.swift create mode 100644 Pods/Charts/Source/Charts/Data/Implementations/Standard/ChartData.swift create mode 100644 Pods/Charts/Source/Charts/Data/Implementations/Standard/ChartDataEntry.swift create mode 100644 Pods/Charts/Source/Charts/Data/Implementations/Standard/ChartDataEntryBase.swift create mode 100644 Pods/Charts/Source/Charts/Data/Implementations/Standard/ChartDataSet.swift create mode 100644 Pods/Charts/Source/Charts/Data/Implementations/Standard/CombinedChartData.swift create mode 100644 Pods/Charts/Source/Charts/Data/Implementations/Standard/LineChartData.swift create mode 100644 Pods/Charts/Source/Charts/Data/Implementations/Standard/LineChartDataSet.swift create mode 100644 Pods/Charts/Source/Charts/Data/Implementations/Standard/LineRadarChartDataSet.swift create mode 100644 Pods/Charts/Source/Charts/Data/Implementations/Standard/LineScatterCandleRadarChartDataSet.swift create mode 100644 Pods/Charts/Source/Charts/Data/Implementations/Standard/PieChartData.swift create mode 100644 Pods/Charts/Source/Charts/Data/Implementations/Standard/PieChartDataEntry.swift create mode 100644 Pods/Charts/Source/Charts/Data/Implementations/Standard/PieChartDataSet.swift create mode 100644 Pods/Charts/Source/Charts/Data/Implementations/Standard/RadarChartData.swift create mode 100644 Pods/Charts/Source/Charts/Data/Implementations/Standard/RadarChartDataEntry.swift create mode 100644 Pods/Charts/Source/Charts/Data/Implementations/Standard/RadarChartDataSet.swift create mode 100644 Pods/Charts/Source/Charts/Data/Implementations/Standard/ScatterChartData.swift create mode 100644 Pods/Charts/Source/Charts/Data/Implementations/Standard/ScatterChartDataSet.swift create mode 100644 Pods/Charts/Source/Charts/Data/Interfaces/IBarChartDataSet.swift create mode 100644 Pods/Charts/Source/Charts/Data/Interfaces/IBarLineScatterCandleBubbleChartDataSet.swift create mode 100644 Pods/Charts/Source/Charts/Data/Interfaces/IBubbleChartDataSet.swift create mode 100644 Pods/Charts/Source/Charts/Data/Interfaces/ICandleChartDataSet.swift create mode 100644 Pods/Charts/Source/Charts/Data/Interfaces/IChartDataSet.swift create mode 100644 Pods/Charts/Source/Charts/Data/Interfaces/ILineChartDataSet.swift create mode 100644 Pods/Charts/Source/Charts/Data/Interfaces/ILineRadarChartDataSet.swift create mode 100644 Pods/Charts/Source/Charts/Data/Interfaces/ILineScatterCandleRadarChartDataSet.swift create mode 100644 Pods/Charts/Source/Charts/Data/Interfaces/IPieChartDataSet.swift create mode 100644 Pods/Charts/Source/Charts/Data/Interfaces/IRadarChartDataSet.swift create mode 100644 Pods/Charts/Source/Charts/Data/Interfaces/IScatterChartDataSet.swift create mode 100644 Pods/Charts/Source/Charts/Filters/DataApproximator+N.swift create mode 100644 Pods/Charts/Source/Charts/Filters/DataApproximator.swift create mode 100644 Pods/Charts/Source/Charts/Formatters/DefaultAxisValueFormatter.swift create mode 100644 Pods/Charts/Source/Charts/Formatters/DefaultFillFormatter.swift create mode 100644 Pods/Charts/Source/Charts/Formatters/DefaultValueFormatter.swift create mode 100644 Pods/Charts/Source/Charts/Formatters/IAxisValueFormatter.swift create mode 100644 Pods/Charts/Source/Charts/Formatters/IFillFormatter.swift create mode 100644 Pods/Charts/Source/Charts/Formatters/IValueFormatter.swift create mode 100644 Pods/Charts/Source/Charts/Formatters/IndexAxisValueFormatter.swift create mode 100644 Pods/Charts/Source/Charts/Highlight/BarHighlighter.swift create mode 100644 Pods/Charts/Source/Charts/Highlight/ChartHighlighter.swift create mode 100644 Pods/Charts/Source/Charts/Highlight/CombinedHighlighter.swift create mode 100644 Pods/Charts/Source/Charts/Highlight/Highlight.swift create mode 100644 Pods/Charts/Source/Charts/Highlight/HorizontalBarHighlighter.swift create mode 100644 Pods/Charts/Source/Charts/Highlight/IHighlighter.swift create mode 100644 Pods/Charts/Source/Charts/Highlight/PieHighlighter.swift create mode 100644 Pods/Charts/Source/Charts/Highlight/PieRadarHighlighter.swift create mode 100644 Pods/Charts/Source/Charts/Highlight/RadarHighlighter.swift create mode 100644 Pods/Charts/Source/Charts/Highlight/Range.swift create mode 100644 Pods/Charts/Source/Charts/Interfaces/BarChartDataProvider.swift create mode 100644 Pods/Charts/Source/Charts/Interfaces/BarLineScatterCandleBubbleChartDataProvider.swift create mode 100644 Pods/Charts/Source/Charts/Interfaces/BubbleChartDataProvider.swift create mode 100644 Pods/Charts/Source/Charts/Interfaces/CandleChartDataProvider.swift create mode 100644 Pods/Charts/Source/Charts/Interfaces/ChartDataProvider.swift create mode 100644 Pods/Charts/Source/Charts/Interfaces/CombinedChartDataProvider.swift create mode 100644 Pods/Charts/Source/Charts/Interfaces/LineChartDataProvider.swift create mode 100644 Pods/Charts/Source/Charts/Interfaces/ScatterChartDataProvider.swift create mode 100644 Pods/Charts/Source/Charts/Jobs/AnimatedMoveViewJob.swift create mode 100644 Pods/Charts/Source/Charts/Jobs/AnimatedViewPortJob.swift create mode 100644 Pods/Charts/Source/Charts/Jobs/AnimatedZoomViewJob.swift create mode 100644 Pods/Charts/Source/Charts/Jobs/MoveViewJob.swift create mode 100644 Pods/Charts/Source/Charts/Jobs/ViewPortJob.swift create mode 100644 Pods/Charts/Source/Charts/Jobs/ZoomViewJob.swift create mode 100644 Pods/Charts/Source/Charts/Renderers/AxisRendererBase.swift create mode 100644 Pods/Charts/Source/Charts/Renderers/BarChartRenderer.swift create mode 100644 Pods/Charts/Source/Charts/Renderers/BarLineScatterCandleBubbleRenderer.swift create mode 100644 Pods/Charts/Source/Charts/Renderers/BubbleChartRenderer.swift create mode 100644 Pods/Charts/Source/Charts/Renderers/CandleStickChartRenderer.swift create mode 100644 Pods/Charts/Source/Charts/Renderers/ChartDataRendererBase.swift create mode 100644 Pods/Charts/Source/Charts/Renderers/CombinedChartRenderer.swift create mode 100644 Pods/Charts/Source/Charts/Renderers/HorizontalBarChartRenderer.swift create mode 100755 Pods/Charts/Source/Charts/Renderers/LegendRenderer.swift create mode 100644 Pods/Charts/Source/Charts/Renderers/LineChartRenderer.swift create mode 100644 Pods/Charts/Source/Charts/Renderers/LineRadarRenderer.swift create mode 100644 Pods/Charts/Source/Charts/Renderers/LineScatterCandleRadarRenderer.swift create mode 100644 Pods/Charts/Source/Charts/Renderers/PieChartRenderer.swift create mode 100644 Pods/Charts/Source/Charts/Renderers/RadarChartRenderer.swift create mode 100644 Pods/Charts/Source/Charts/Renderers/Renderer.swift create mode 100644 Pods/Charts/Source/Charts/Renderers/Scatter/ChevronDownShapeRenderer.swift create mode 100644 Pods/Charts/Source/Charts/Renderers/Scatter/ChevronUpShapeRenderer.swift create mode 100644 Pods/Charts/Source/Charts/Renderers/Scatter/CircleShapeRenderer.swift create mode 100644 Pods/Charts/Source/Charts/Renderers/Scatter/CrossShapeRenderer.swift create mode 100644 Pods/Charts/Source/Charts/Renderers/Scatter/IShapeRenderer.swift create mode 100644 Pods/Charts/Source/Charts/Renderers/Scatter/SquareShapeRenderer.swift create mode 100644 Pods/Charts/Source/Charts/Renderers/Scatter/TriangleShapeRenderer.swift create mode 100644 Pods/Charts/Source/Charts/Renderers/Scatter/XShapeRenderer.swift create mode 100644 Pods/Charts/Source/Charts/Renderers/ScatterChartRenderer.swift create mode 100644 Pods/Charts/Source/Charts/Renderers/XAxisRenderer.swift create mode 100644 Pods/Charts/Source/Charts/Renderers/XAxisRendererHorizontalBarChart.swift create mode 100644 Pods/Charts/Source/Charts/Renderers/XAxisRendererRadarChart.swift create mode 100644 Pods/Charts/Source/Charts/Renderers/YAxisRenderer.swift create mode 100644 Pods/Charts/Source/Charts/Renderers/YAxisRendererHorizontalBarChart.swift create mode 100644 Pods/Charts/Source/Charts/Renderers/YAxisRendererRadarChart.swift create mode 100644 Pods/Charts/Source/Charts/Utils/ChartColorTemplates.swift create mode 100644 Pods/Charts/Source/Charts/Utils/ChartUtils.swift create mode 100644 Pods/Charts/Source/Charts/Utils/Fill.swift create mode 100644 Pods/Charts/Source/Charts/Utils/Platform+Accessibility.swift create mode 100644 Pods/Charts/Source/Charts/Utils/Platform.swift create mode 100644 Pods/Charts/Source/Charts/Utils/Transformer.swift create mode 100644 Pods/Charts/Source/Charts/Utils/TransformerHorizontalBarChart.swift create mode 100755 Pods/Charts/Source/Charts/Utils/ViewPortHandler.swift create mode 100644 Pods/Eddystone/LICENSE create mode 100644 Pods/Eddystone/Pod/Classes/Beacon.swift create mode 100755 Pods/Eddystone/Pod/Classes/CoreBluetoothExtensions.swift create mode 100755 Pods/Eddystone/Pod/Classes/DoubleExtensions.swift create mode 100644 Pods/Eddystone/Pod/Classes/Frame.swift create mode 100644 Pods/Eddystone/Pod/Classes/Generic.swift create mode 100644 Pods/Eddystone/Pod/Classes/Global.swift create mode 100644 Pods/Eddystone/Pod/Classes/IntExtensions.swift create mode 100644 Pods/Eddystone/Pod/Classes/NSTimeIntervalExtensions.swift create mode 100644 Pods/Eddystone/Pod/Classes/Object.swift create mode 100644 Pods/Eddystone/Pod/Classes/Scanner.swift create mode 100644 Pods/Eddystone/Pod/Classes/TlmFrame.swift create mode 100644 Pods/Eddystone/Pod/Classes/Uid.swift create mode 100644 Pods/Eddystone/Pod/Classes/UidFrame.swift create mode 100644 Pods/Eddystone/Pod/Classes/Url.swift create mode 100644 Pods/Eddystone/Pod/Classes/UrlFrame.swift create mode 100644 Pods/Eddystone/README.md create mode 100644 Pods/IP-UIKit-Wisdom/LICENSE create mode 100644 Pods/IP-UIKit-Wisdom/src/CAGradientLayer/CAGradientLayer+IPGradients.h create mode 100644 Pods/IP-UIKit-Wisdom/src/CAGradientLayer/CAGradientLayer+IPGradients.m create mode 100644 Pods/IP-UIKit-Wisdom/src/UIButton/UIButton+IPUtils.h create mode 100644 Pods/IP-UIKit-Wisdom/src/UIButton/UIButton+IPUtils.m create mode 100644 Pods/IP-UIKit-Wisdom/src/UIColor/UIColor+IPRandomColor.h create mode 100644 Pods/IP-UIKit-Wisdom/src/UIColor/UIColor+IPRandomColor.m create mode 100644 Pods/IP-UIKit-Wisdom/src/UIImage/UIImage+ColorMaskedImage.h create mode 100644 Pods/IP-UIKit-Wisdom/src/UIImage/UIImage+ColorMaskedImage.m create mode 100644 Pods/IP-UIKit-Wisdom/src/UITableView/UITableView+Utils.h create mode 100644 Pods/IP-UIKit-Wisdom/src/UITableView/UITableView+Utils.m create mode 100644 Pods/IP-UIKit-Wisdom/src/UIView/UIView+Constraints.h create mode 100644 Pods/IP-UIKit-Wisdom/src/UIView/UIView+Constraints.m create mode 100644 Pods/IP-UIKit-Wisdom/src/UIView/UIView+IPAncestry.h create mode 100644 Pods/IP-UIKit-Wisdom/src/UIView/UIView+IPAncestry.m create mode 100644 Pods/IP-UIKit-Wisdom/src/UIView/UIView+IPFrameUtils.h create mode 100644 Pods/IP-UIKit-Wisdom/src/UIView/UIView+IPFrameUtils.m create mode 100644 Pods/IP-UIKit-Wisdom/src/UIView/UIView+NibInitable.h create mode 100644 Pods/IP-UIKit-Wisdom/src/UIView/UIView+NibInitable.m create mode 100644 Pods/IP-UIKit-Wisdom/src/UIViewController/UIViewController+Containment.h create mode 100644 Pods/IP-UIKit-Wisdom/src/UIViewController/UIViewController+Containment.m create mode 100644 Pods/KVOController/FBKVOController/FBKVOController.h create mode 100644 Pods/KVOController/FBKVOController/FBKVOController.m create mode 100644 Pods/KVOController/FBKVOController/KVOController.h create mode 100644 Pods/KVOController/FBKVOController/NSObject+FBKVOController.h create mode 100644 Pods/KVOController/FBKVOController/NSObject+FBKVOController.m create mode 100644 Pods/KVOController/LICENSE create mode 100644 Pods/KVOController/README.md create mode 100644 Pods/Local Podspecs/Eddystone.podspec.json create mode 100644 Pods/MZTimerLabel/LICENSE create mode 100644 Pods/MZTimerLabel/MZTimerLabel/MZTimerLabel.h create mode 100644 Pods/MZTimerLabel/MZTimerLabel/MZTimerLabel.m create mode 100644 Pods/MZTimerLabel/README.md create mode 100644 Pods/Manifest.lock create mode 100644 Pods/Pods.xcodeproj/project.pbxproj create mode 100644 Pods/Pods.xcodeproj/xcshareddata/xcschemes/ActionSheetPicker-3.0.xcscheme create mode 100644 Pods/Pods.xcodeproj/xcshareddata/xcschemes/ChameleonFramework.xcscheme create mode 100644 Pods/Pods.xcodeproj/xcshareddata/xcschemes/Charts.xcscheme create mode 100644 Pods/Pods.xcodeproj/xcshareddata/xcschemes/Eddystone-Eddystone.xcscheme create mode 100644 Pods/Pods.xcodeproj/xcshareddata/xcschemes/Eddystone.xcscheme create mode 100644 Pods/Pods.xcodeproj/xcshareddata/xcschemes/IP-UIKit-Wisdom.xcscheme create mode 100644 Pods/Pods.xcodeproj/xcshareddata/xcschemes/KVOController.xcscheme create mode 100644 Pods/Pods.xcodeproj/xcshareddata/xcschemes/MZTimerLabel.xcscheme create mode 100644 Pods/Pods.xcodeproj/xcshareddata/xcschemes/Pods-BlueGecko.xcscheme create mode 100644 Pods/Pods.xcodeproj/xcshareddata/xcschemes/Pods-BlueGeckoWithHomeKit.xcscheme create mode 100644 Pods/Pods.xcodeproj/xcshareddata/xcschemes/Pods-WirelessGecko.xcscheme create mode 100644 Pods/Pods.xcodeproj/xcshareddata/xcschemes/PureLayout.xcscheme create mode 100644 Pods/Pods.xcodeproj/xcshareddata/xcschemes/SVProgressHUD.xcscheme create mode 100644 Pods/Pods.xcodeproj/xcshareddata/xcschemes/UICircularProgressRing.xcscheme create mode 100644 Pods/Pods.xcodeproj/xcshareddata/xcschemes/WYPopoverController.xcscheme create mode 100644 Pods/Pods.xcodeproj/xcshareddata/xcschemes/XMLDictionary.xcscheme create mode 100755 Pods/PureLayout/LICENSE create mode 100755 Pods/PureLayout/PureLayout/PureLayout/ALView+PureLayout.h create mode 100755 Pods/PureLayout/PureLayout/PureLayout/ALView+PureLayout.m create mode 100755 Pods/PureLayout/PureLayout/PureLayout/NSArray+PureLayout.h create mode 100755 Pods/PureLayout/PureLayout/PureLayout/NSArray+PureLayout.m create mode 100755 Pods/PureLayout/PureLayout/PureLayout/NSLayoutConstraint+PureLayout.h create mode 100755 Pods/PureLayout/PureLayout/PureLayout/NSLayoutConstraint+PureLayout.m create mode 100644 Pods/PureLayout/PureLayout/PureLayout/PureLayout+Internal.h create mode 100755 Pods/PureLayout/PureLayout/PureLayout/PureLayout.h create mode 100755 Pods/PureLayout/PureLayout/PureLayout/PureLayoutDefines.h create mode 100644 Pods/PureLayout/README.md create mode 100644 Pods/SVProgressHUD/LICENSE create mode 100644 Pods/SVProgressHUD/README.md create mode 100644 Pods/SVProgressHUD/SVProgressHUD/SVIndefiniteAnimatedView.h create mode 100644 Pods/SVProgressHUD/SVProgressHUD/SVIndefiniteAnimatedView.m create mode 100644 Pods/SVProgressHUD/SVProgressHUD/SVProgressAnimatedView.h create mode 100644 Pods/SVProgressHUD/SVProgressHUD/SVProgressAnimatedView.m create mode 100644 Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.bundle/angle-mask.png create mode 100644 Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.bundle/angle-mask@2x.png create mode 100644 Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.bundle/angle-mask@3x.png create mode 100644 Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.bundle/error.png create mode 100644 Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.bundle/error@2x.png create mode 100644 Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.bundle/error@3x.png create mode 100644 Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.bundle/info.png create mode 100644 Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.bundle/info@2x.png create mode 100644 Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.bundle/info@3x.png create mode 100644 Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.bundle/success.png create mode 100644 Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.bundle/success@2x.png create mode 100644 Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.bundle/success@3x.png create mode 100644 Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.h create mode 100644 Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.m create mode 100644 Pods/SVProgressHUD/SVProgressHUD/SVRadialGradientLayer.h create mode 100644 Pods/SVProgressHUD/SVProgressHUD/SVRadialGradientLayer.m create mode 100644 Pods/Target Support Files/ActionSheetPicker-3.0/ActionSheetPicker-3.0-dummy.m create mode 100644 Pods/Target Support Files/ActionSheetPicker-3.0/ActionSheetPicker-3.0-prefix.pch create mode 100644 Pods/Target Support Files/ActionSheetPicker-3.0/ActionSheetPicker-3.0-umbrella.h create mode 100644 Pods/Target Support Files/ActionSheetPicker-3.0/ActionSheetPicker-3.0.modulemap create mode 100644 Pods/Target Support Files/ActionSheetPicker-3.0/ActionSheetPicker-3.0.xcconfig create mode 100644 Pods/Target Support Files/ActionSheetPicker-3.0/Info.plist create mode 100644 Pods/Target Support Files/ChameleonFramework/ChameleonFramework-dummy.m create mode 100644 Pods/Target Support Files/ChameleonFramework/ChameleonFramework-prefix.pch create mode 100644 Pods/Target Support Files/ChameleonFramework/ChameleonFramework-umbrella.h create mode 100644 Pods/Target Support Files/ChameleonFramework/ChameleonFramework.modulemap create mode 100644 Pods/Target Support Files/ChameleonFramework/ChameleonFramework.xcconfig create mode 100644 Pods/Target Support Files/ChameleonFramework/Info.plist create mode 100644 Pods/Target Support Files/Charts/Charts-dummy.m create mode 100644 Pods/Target Support Files/Charts/Charts-prefix.pch create mode 100644 Pods/Target Support Files/Charts/Charts-umbrella.h create mode 100644 Pods/Target Support Files/Charts/Charts.modulemap create mode 100644 Pods/Target Support Files/Charts/Charts.xcconfig create mode 100644 Pods/Target Support Files/Charts/Info.plist create mode 100644 Pods/Target Support Files/Eddystone/Eddystone-dummy.m create mode 100644 Pods/Target Support Files/Eddystone/Eddystone-prefix.pch create mode 100644 Pods/Target Support Files/Eddystone/Eddystone-umbrella.h create mode 100644 Pods/Target Support Files/Eddystone/Eddystone.modulemap create mode 100644 Pods/Target Support Files/Eddystone/Eddystone.xcconfig create mode 100644 Pods/Target Support Files/Eddystone/Info.plist create mode 100644 Pods/Target Support Files/Eddystone/ResourceBundle-Eddystone-Info.plist create mode 100644 Pods/Target Support Files/IP-UIKit-Wisdom/IP-UIKit-Wisdom-dummy.m create mode 100644 Pods/Target Support Files/IP-UIKit-Wisdom/IP-UIKit-Wisdom-prefix.pch create mode 100644 Pods/Target Support Files/IP-UIKit-Wisdom/IP-UIKit-Wisdom-umbrella.h create mode 100644 Pods/Target Support Files/IP-UIKit-Wisdom/IP-UIKit-Wisdom.modulemap create mode 100644 Pods/Target Support Files/IP-UIKit-Wisdom/IP-UIKit-Wisdom.xcconfig create mode 100644 Pods/Target Support Files/IP-UIKit-Wisdom/Info.plist create mode 100644 Pods/Target Support Files/KVOController/Info.plist create mode 100644 Pods/Target Support Files/KVOController/KVOController-dummy.m create mode 100644 Pods/Target Support Files/KVOController/KVOController-prefix.pch create mode 100644 Pods/Target Support Files/KVOController/KVOController-umbrella.h create mode 100644 Pods/Target Support Files/KVOController/KVOController.modulemap create mode 100644 Pods/Target Support Files/KVOController/KVOController.xcconfig create mode 100644 Pods/Target Support Files/MZTimerLabel/Info.plist create mode 100644 Pods/Target Support Files/MZTimerLabel/MZTimerLabel-dummy.m create mode 100644 Pods/Target Support Files/MZTimerLabel/MZTimerLabel-prefix.pch create mode 100644 Pods/Target Support Files/MZTimerLabel/MZTimerLabel-umbrella.h create mode 100644 Pods/Target Support Files/MZTimerLabel/MZTimerLabel.modulemap create mode 100644 Pods/Target Support Files/MZTimerLabel/MZTimerLabel.xcconfig create mode 100644 Pods/Target Support Files/Pods-BlueGecko/Info.plist create mode 100644 Pods/Target Support Files/Pods-BlueGecko/Pods-BlueGecko-acknowledgements.markdown create mode 100644 Pods/Target Support Files/Pods-BlueGecko/Pods-BlueGecko-acknowledgements.plist create mode 100644 Pods/Target Support Files/Pods-BlueGecko/Pods-BlueGecko-dummy.m create mode 100755 Pods/Target Support Files/Pods-BlueGecko/Pods-BlueGecko-frameworks.sh create mode 100755 Pods/Target Support Files/Pods-BlueGecko/Pods-BlueGecko-resources.sh create mode 100644 Pods/Target Support Files/Pods-BlueGecko/Pods-BlueGecko-umbrella.h create mode 100644 Pods/Target Support Files/Pods-BlueGecko/Pods-BlueGecko.debug.xcconfig create mode 100644 Pods/Target Support Files/Pods-BlueGecko/Pods-BlueGecko.modulemap create mode 100644 Pods/Target Support Files/Pods-BlueGecko/Pods-BlueGecko.release.xcconfig create mode 100644 Pods/Target Support Files/Pods-BlueGeckoWithHomeKit/Info.plist create mode 100644 Pods/Target Support Files/Pods-BlueGeckoWithHomeKit/Pods-BlueGeckoWithHomeKit-acknowledgements.markdown create mode 100644 Pods/Target Support Files/Pods-BlueGeckoWithHomeKit/Pods-BlueGeckoWithHomeKit-acknowledgements.plist create mode 100644 Pods/Target Support Files/Pods-BlueGeckoWithHomeKit/Pods-BlueGeckoWithHomeKit-dummy.m create mode 100755 Pods/Target Support Files/Pods-BlueGeckoWithHomeKit/Pods-BlueGeckoWithHomeKit-frameworks.sh create mode 100755 Pods/Target Support Files/Pods-BlueGeckoWithHomeKit/Pods-BlueGeckoWithHomeKit-resources.sh create mode 100644 Pods/Target Support Files/Pods-BlueGeckoWithHomeKit/Pods-BlueGeckoWithHomeKit-umbrella.h create mode 100644 Pods/Target Support Files/Pods-BlueGeckoWithHomeKit/Pods-BlueGeckoWithHomeKit.debug.xcconfig create mode 100644 Pods/Target Support Files/Pods-BlueGeckoWithHomeKit/Pods-BlueGeckoWithHomeKit.modulemap create mode 100644 Pods/Target Support Files/Pods-BlueGeckoWithHomeKit/Pods-BlueGeckoWithHomeKit.release.xcconfig create mode 100644 Pods/Target Support Files/Pods-WirelessGecko/Info.plist create mode 100644 Pods/Target Support Files/Pods-WirelessGecko/Pods-WirelessGecko-acknowledgements.markdown create mode 100644 Pods/Target Support Files/Pods-WirelessGecko/Pods-WirelessGecko-acknowledgements.plist create mode 100644 Pods/Target Support Files/Pods-WirelessGecko/Pods-WirelessGecko-dummy.m create mode 100755 Pods/Target Support Files/Pods-WirelessGecko/Pods-WirelessGecko-frameworks.sh create mode 100755 Pods/Target Support Files/Pods-WirelessGecko/Pods-WirelessGecko-resources.sh create mode 100644 Pods/Target Support Files/Pods-WirelessGecko/Pods-WirelessGecko-umbrella.h create mode 100644 Pods/Target Support Files/Pods-WirelessGecko/Pods-WirelessGecko.debug.xcconfig create mode 100644 Pods/Target Support Files/Pods-WirelessGecko/Pods-WirelessGecko.modulemap create mode 100644 Pods/Target Support Files/Pods-WirelessGecko/Pods-WirelessGecko.release.xcconfig create mode 100644 Pods/Target Support Files/PureLayout/Info.plist create mode 100644 Pods/Target Support Files/PureLayout/PureLayout-dummy.m create mode 100644 Pods/Target Support Files/PureLayout/PureLayout-prefix.pch create mode 100644 Pods/Target Support Files/PureLayout/PureLayout-umbrella.h create mode 100644 Pods/Target Support Files/PureLayout/PureLayout.modulemap create mode 100644 Pods/Target Support Files/PureLayout/PureLayout.xcconfig create mode 100644 Pods/Target Support Files/SVProgressHUD/Info.plist create mode 100644 Pods/Target Support Files/SVProgressHUD/SVProgressHUD-dummy.m create mode 100644 Pods/Target Support Files/SVProgressHUD/SVProgressHUD-prefix.pch create mode 100644 Pods/Target Support Files/SVProgressHUD/SVProgressHUD-umbrella.h create mode 100644 Pods/Target Support Files/SVProgressHUD/SVProgressHUD.modulemap create mode 100644 Pods/Target Support Files/SVProgressHUD/SVProgressHUD.xcconfig create mode 100644 Pods/Target Support Files/UICircularProgressRing/Info.plist create mode 100644 Pods/Target Support Files/UICircularProgressRing/UICircularProgressRing-dummy.m create mode 100644 Pods/Target Support Files/UICircularProgressRing/UICircularProgressRing-prefix.pch create mode 100644 Pods/Target Support Files/UICircularProgressRing/UICircularProgressRing-umbrella.h create mode 100644 Pods/Target Support Files/UICircularProgressRing/UICircularProgressRing.modulemap create mode 100644 Pods/Target Support Files/UICircularProgressRing/UICircularProgressRing.xcconfig create mode 100644 Pods/Target Support Files/WYPopoverController/Info.plist create mode 100644 Pods/Target Support Files/WYPopoverController/WYPopoverController-dummy.m create mode 100644 Pods/Target Support Files/WYPopoverController/WYPopoverController-prefix.pch create mode 100644 Pods/Target Support Files/WYPopoverController/WYPopoverController-umbrella.h create mode 100644 Pods/Target Support Files/WYPopoverController/WYPopoverController.modulemap create mode 100644 Pods/Target Support Files/WYPopoverController/WYPopoverController.xcconfig create mode 100644 Pods/Target Support Files/XMLDictionary/Info.plist create mode 100644 Pods/Target Support Files/XMLDictionary/XMLDictionary-dummy.m create mode 100644 Pods/Target Support Files/XMLDictionary/XMLDictionary-prefix.pch create mode 100644 Pods/Target Support Files/XMLDictionary/XMLDictionary-umbrella.h create mode 100644 Pods/Target Support Files/XMLDictionary/XMLDictionary.modulemap create mode 100644 Pods/Target Support Files/XMLDictionary/XMLDictionary.xcconfig create mode 100644 Pods/UICircularProgressRing/LICENSE create mode 100644 Pods/UICircularProgressRing/README.md create mode 100644 Pods/UICircularProgressRing/src/UICircularProgressRing/UICircularProgressRing.h create mode 100644 Pods/UICircularProgressRing/src/UICircularProgressRing/UICircularProgressRing.swift create mode 100644 Pods/UICircularProgressRing/src/UICircularProgressRing/UICircularProgressRingDelegate.swift create mode 100644 Pods/UICircularProgressRing/src/UICircularProgressRing/UICircularProgressRingGradientPosition.swift create mode 100644 Pods/UICircularProgressRing/src/UICircularProgressRing/UICircularProgressRingLayer.swift create mode 100644 Pods/UICircularProgressRing/src/UICircularProgressRing/UICircularProgressRingStyle.swift create mode 100644 Pods/WYPopoverController/LICENSE create mode 100644 Pods/WYPopoverController/README.md create mode 100644 Pods/WYPopoverController/WYPopoverController/WYPopoverController.h create mode 100644 Pods/WYPopoverController/WYPopoverController/WYPopoverController.m create mode 100644 Pods/WYPopoverController/WYPopoverController/WYStoryboardPopoverSegue.h create mode 100644 Pods/WYPopoverController/WYPopoverController/WYStoryboardPopoverSegue.m create mode 100755 Pods/XMLDictionary/LICENCE.md create mode 100755 Pods/XMLDictionary/README.md create mode 100644 Pods/XMLDictionary/XMLDictionary/XMLDictionary.h create mode 100644 Pods/XMLDictionary/XMLDictionary/XMLDictionary.m delete mode 100644 SiliconLabsApp.pch rename SiliconLabsApp.xcodeproj/xcshareddata/xcschemes/{SiliconLabsAppWithoutHomeKit.xcscheme => BlueGecko.xcscheme} (84%) rename SiliconLabsApp.xcodeproj/xcshareddata/xcschemes/{SiliconLabsApp.xcscheme => BlueGeckoWithHomeKit.xcscheme} (89%) rename SiliconLabsApp.xcodeproj/xcshareddata/xcschemes/{SiliconLabsApp-WirelessGecko.xcscheme => WirelessGecko.xcscheme} (58%) create mode 100644 SiliconLabsApp.xcworkspace/contents.xcworkspacedata create mode 100644 SiliconLabsApp.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 SiliconLabsApp/Base.lproj/RangeTest/RangeTestStoryboard.storyboard create mode 100644 SiliconLabsApp/Base.lproj/RangeTest/SILRangeTestModeSelectionViewController.xib create mode 100644 SiliconLabsApp/SupportingFiles/BlueGecko/BlueGecko.pch rename SiliconLabsApp/{SiliconLabsAppWithoutHomeKit.entitlements => SupportingFiles/BlueGecko/Entitlements.entitlements} (100%) rename SiliconLabsApp/SupportingFiles/{Info-WithoutHomeKit.plist => BlueGecko/Info.plist} (92%) create mode 100644 SiliconLabsApp/SupportingFiles/BlueGeckoWithHomeKit/BlueGeckoWithHomeKit.pch rename SiliconLabsApp/{SiliconLabsApp.entitlements => SupportingFiles/BlueGeckoWithHomeKit/Entitlements.entitlements} (100%) rename SiliconLabsApp/SupportingFiles/{ => BlueGeckoWithHomeKit}/Info.plist (94%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/AltBeacon.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/AltBeacon.imageset/beacon_alt-ipad.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/AltBeacon.imageset/beacon_alt-ipad@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/AltBeacon.imageset/beacon_alt-iphone.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/AltBeacon.imageset/beacon_alt-iphone@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/AltBeacon.imageset/beacon_alt-iphone@3x.png (100%) rename SiliconLabsApp/{Images.xcassets/AppIcon.appiconset => SupportingFiles/Images.xcassets/AppIconBlueGecko.appiconset}/Contents.json (100%) rename SiliconLabsApp/{Images.xcassets/AppIcon.appiconset => SupportingFiles/Images.xcassets/AppIconBlueGecko.appiconset}/Icon-60@2x.png (100%) rename SiliconLabsApp/{Images.xcassets/AppIcon.appiconset => SupportingFiles/Images.xcassets/AppIconBlueGecko.appiconset}/Icon-60@3x.png (100%) rename SiliconLabsApp/{Images.xcassets/AppIcon.appiconset => SupportingFiles/Images.xcassets/AppIconBlueGecko.appiconset}/Icon-76.png (100%) rename SiliconLabsApp/{Images.xcassets/AppIcon.appiconset => SupportingFiles/Images.xcassets/AppIconBlueGecko.appiconset}/Icon-76@2x.png (100%) rename SiliconLabsApp/{Images.xcassets/AppIcon.appiconset => SupportingFiles/Images.xcassets/AppIconBlueGecko.appiconset}/Icon-83.5@2x.png (100%) rename SiliconLabsApp/{Images.xcassets/AppIcon.appiconset => SupportingFiles/Images.xcassets/AppIconBlueGecko.appiconset}/Icon-Small-40.png (100%) rename SiliconLabsApp/{Images.xcassets/AppIcon.appiconset => SupportingFiles/Images.xcassets/AppIconBlueGecko.appiconset}/Icon-Small-40@2x-1.png (100%) rename SiliconLabsApp/{Images.xcassets/AppIcon.appiconset => SupportingFiles/Images.xcassets/AppIconBlueGecko.appiconset}/Icon-Small-40@2x.png (100%) rename SiliconLabsApp/{Images.xcassets/AppIcon.appiconset => SupportingFiles/Images.xcassets/AppIconBlueGecko.appiconset}/Icon-Small-40@3x.png (100%) rename SiliconLabsApp/{Images.xcassets/AppIcon.appiconset => SupportingFiles/Images.xcassets/AppIconBlueGecko.appiconset}/Icon-Small.png (100%) rename SiliconLabsApp/{Images.xcassets/AppIcon.appiconset => SupportingFiles/Images.xcassets/AppIconBlueGecko.appiconset}/Icon-Small@2x-1.png (100%) rename SiliconLabsApp/{Images.xcassets/AppIcon.appiconset => SupportingFiles/Images.xcassets/AppIconBlueGecko.appiconset}/Icon-Small@2x.png (100%) rename SiliconLabsApp/{Images.xcassets/AppIcon.appiconset => SupportingFiles/Images.xcassets/AppIconBlueGecko.appiconset}/Icon-Small@3x.png (100%) rename SiliconLabsApp/{Images.xcassets/AppIcon.appiconset => SupportingFiles/Images.xcassets/AppIconBlueGecko.appiconset}/Icon_1024x1024.png (100%) rename SiliconLabsApp/{Images.xcassets/AppIcon.wireless.appiconset => SupportingFiles/Images.xcassets/AppIconWirelessGecko.appiconset}/Contents.json (100%) rename SiliconLabsApp/{Images.xcassets/AppIcon.wireless.appiconset => SupportingFiles/Images.xcassets/AppIconWirelessGecko.appiconset}/multiprotocol-60@2x.png (100%) rename SiliconLabsApp/{Images.xcassets/AppIcon.wireless.appiconset => SupportingFiles/Images.xcassets/AppIconWirelessGecko.appiconset}/multiprotocol-60@3x.png (100%) rename SiliconLabsApp/{Images.xcassets/AppIcon.wireless.appiconset => SupportingFiles/Images.xcassets/AppIconWirelessGecko.appiconset}/multiprotocol-76.png (100%) rename SiliconLabsApp/{Images.xcassets/AppIcon.wireless.appiconset => SupportingFiles/Images.xcassets/AppIconWirelessGecko.appiconset}/multiprotocol-76@2x.png (100%) rename SiliconLabsApp/{Images.xcassets/AppIcon.wireless.appiconset => SupportingFiles/Images.xcassets/AppIconWirelessGecko.appiconset}/multiprotocol-83.5@2x.png (100%) rename SiliconLabsApp/{Images.xcassets/AppIcon.wireless.appiconset => SupportingFiles/Images.xcassets/AppIconWirelessGecko.appiconset}/multiprotocol-Small-40.png (100%) rename SiliconLabsApp/{Images.xcassets/AppIcon.wireless.appiconset => SupportingFiles/Images.xcassets/AppIconWirelessGecko.appiconset}/multiprotocol-Small-40@2x-1.png (100%) rename SiliconLabsApp/{Images.xcassets/AppIcon.wireless.appiconset => SupportingFiles/Images.xcassets/AppIconWirelessGecko.appiconset}/multiprotocol-Small-40@2x.png (100%) rename SiliconLabsApp/{Images.xcassets/AppIcon.wireless.appiconset => SupportingFiles/Images.xcassets/AppIconWirelessGecko.appiconset}/multiprotocol-Small-40@3x.png (100%) rename SiliconLabsApp/{Images.xcassets/AppIcon.wireless.appiconset => SupportingFiles/Images.xcassets/AppIconWirelessGecko.appiconset}/multiprotocol-Small.png (100%) rename SiliconLabsApp/{Images.xcassets/AppIcon.wireless.appiconset => SupportingFiles/Images.xcassets/AppIconWirelessGecko.appiconset}/multiprotocol-Small@2x-1.png (100%) rename SiliconLabsApp/{Images.xcassets/AppIcon.wireless.appiconset => SupportingFiles/Images.xcassets/AppIconWirelessGecko.appiconset}/multiprotocol-Small@2x.png (100%) rename SiliconLabsApp/{Images.xcassets/AppIcon.wireless.appiconset => SupportingFiles/Images.xcassets/AppIconWirelessGecko.appiconset}/multiprotocol-Small@3x.png (100%) rename SiliconLabsApp/{Images.xcassets/AppIcon.wireless.appiconset => SupportingFiles/Images.xcassets/AppIconWirelessGecko.appiconset}/multiprotocol@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/BGBeacon.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/BGBeacon.imageset/beacon_gecko-ipad.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/BGBeacon.imageset/beacon_gecko-ipad@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/BGBeacon.imageset/beacon_gecko-iphone.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/BGBeacon.imageset/beacon_gecko-iphone@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/BGBeacon.imageset/beacon_gecko-iphone@3x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/BTMedium.imageset/BT_Medium~ipad.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/BTMedium.imageset/BT_Medium~ipad@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/BTMedium.imageset/BT_Medium~iphone.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/BTMedium.imageset/BT_Medium~iphone@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/BTMedium.imageset/BT_Medium~iphone@3x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/BTMedium.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/BTStrong.imageset/BT_Strong~ipad.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/BTStrong.imageset/BT_Strong~ipad@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/BTStrong.imageset/BT_Strong~iphone.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/BTStrong.imageset/BT_Strong~iphone@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/BTStrong.imageset/BT_Strong~iphone@3x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/BTStrong.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/BTWeak.imageset/BT_Weak~ipad.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/BTWeak.imageset/BT_Weak~ipad@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/BTWeak.imageset/BT_Weak~iphone.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/BTWeak.imageset/BT_Weak~iphone@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/BTWeak.imageset/BT_Weak~iphone@3x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/BTWeak.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/BackIcon.imageset/BackIcon.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/BackIcon.imageset/BackIcon@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/BackIcon.imageset/BackIcon@3x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/BackIcon.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/BeaconFar.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/BeaconFar.imageset/beacon_far-ipad.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/BeaconFar.imageset/beacon_far-ipad@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/BeaconFar.imageset/beacon_far-iphone.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/BeaconFar.imageset/beacon_far-iphone@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/BeaconFar.imageset/beacon_far-iphone@3x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/BeaconImmediate.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/BeaconImmediate.imageset/beacon_immediate-ipad.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/BeaconImmediate.imageset/beacon_immediate-ipad@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/BeaconImmediate.imageset/beacon_immediate-iphone.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/BeaconImmediate.imageset/beacon_immediate-iphone@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/BeaconImmediate.imageset/beacon_immediate-iphone@3x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/BeaconNear.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/BeaconNear.imageset/beacon_near-ipad.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/BeaconNear.imageset/beacon_near-ipad@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/BeaconNear.imageset/beacon_near-iphone.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/BeaconNear.imageset/beacon_near-iphone@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/BeaconNear.imageset/beacon_near-iphone@3x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/EddystoneBeacon.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/EddystoneBeacon.imageset/beacon_eddystone-ipad.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/EddystoneBeacon.imageset/beacon_eddystone-ipad@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/EddystoneBeacon.imageset/beacon_eddystone-iphone.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/EddystoneBeacon.imageset/beacon_eddystone-iphone@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/EddystoneBeacon.imageset/beacon_eddystone-iphone@3x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomeConnectedLighting.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomeConnectedLighting.imageset/iconLightBulb-1.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomeConnectedLighting.imageset/iconLightBulb.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomeConnectedLighting.imageset/iconLightBulb@2x-1.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomeConnectedLighting.imageset/iconLightBulb@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomeConnectedLighting.imageset/iconLightBulb@3x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomeDebug.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomeDebug.imageset/home_debug-ipad.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomeDebug.imageset/home_debug-ipad@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomeDebug.imageset/home_debug-iphone.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomeDebug.imageset/home_debug-iphone@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomeDebug.imageset/home_debug-iphone@3x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomeHelp.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomeHelp.imageset/Home_Help~ipad.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomeHelp.imageset/Home_Help~ipad@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomeHelp.imageset/Home_Help~iphone.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomeHelp.imageset/Home_Help~iphone@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomeHelp.imageset/Home_Help~iphone@3x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomeKeyFOB.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomeKeyFOB.imageset/Home_Key_FOB~ipad.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomeKeyFOB.imageset/Home_Key_FOB~ipad@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomeKeyFOB.imageset/Home_Key_FOB~iphone.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomeKeyFOB.imageset/Home_Key_FOB~iphone@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomeKeyFOB.imageset/Home_Key_FOB~iphone@3x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomeKitDebug.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomeKitDebug.imageset/homekit_debug-ipad.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomeKitDebug.imageset/homekit_debug-ipad@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomeKitDebug.imageset/homekit_debug-iphone.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomeKitDebug.imageset/homekit_debug-iphone@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomeKitDebug.imageset/homekit_debug-iphone@3x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomePropertyBroadcast.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomePropertyBroadcast.imageset/debug_prop_broadcast.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomePropertyBroadcast.imageset/debug_prop_broadcast@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomePropertyBroadcast.imageset/debug_prop_broadcast@3x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomePropertyExtended.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomePropertyExtended.imageset/debug_prop_broadcast@3x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomePropertyExtended.imageset/debug_prop_ext.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomePropertyExtended.imageset/debug_prop_ext@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomePropertyIndicate.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomePropertyIndicate.imageset/debug_prop_indicate.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomePropertyIndicate.imageset/debug_prop_indicate@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomePropertyIndicate.imageset/debug_prop_indicate@3x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomePropertyNotify.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomePropertyNotify.imageset/debug_prop_notify.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomePropertyNotify.imageset/debug_prop_notify@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomePropertyNotify.imageset/debug_prop_notify@3x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomePropertyRead.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomePropertyRead.imageset/debug_prop_read.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomePropertyRead.imageset/debug_prop_read@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomePropertyRead.imageset/debug_prop_read@3x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomePropertySignedWrite.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomePropertySignedWrite.imageset/debug_prop_signed_write.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomePropertySignedWrite.imageset/debug_prop_signed_write@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomePropertySignedWrite.imageset/debug_prop_signed_write@3x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomePropertyWrite.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomePropertyWrite.imageset/debug_prop_write.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomePropertyWrite.imageset/debug_prop_write@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomePropertyWrite.imageset/debug_prop_write@3x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomePropertyWriteNoResponse.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomePropertyWriteNoResponse.imageset/debug_prop_write_no_resp.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomePropertyWriteNoResponse.imageset/debug_prop_write_no_resp@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomePropertyWriteNoResponse.imageset/debug_prop_write_no_resp@3x.png (100%) create mode 100644 SiliconLabsApp/SupportingFiles/Images.xcassets/HomeRangeTestDemo.imageset/Contents.json create mode 100644 SiliconLabsApp/SupportingFiles/Images.xcassets/HomeRangeTestDemo.imageset/Range_Icon~ipad.png create mode 100644 SiliconLabsApp/SupportingFiles/Images.xcassets/HomeRangeTestDemo.imageset/Range_Icon~ipad@2x.png create mode 100644 SiliconLabsApp/SupportingFiles/Images.xcassets/HomeRangeTestDemo.imageset/Range_Icon~iphone.png create mode 100644 SiliconLabsApp/SupportingFiles/Images.xcassets/HomeRangeTestDemo.imageset/Range_Icon~iphone@2x.png create mode 100644 SiliconLabsApp/SupportingFiles/Images.xcassets/HomeRangeTestDemo.imageset/Range_Icon~iphone@3x.png rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomeRemoteKeyboard.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomeRemoteKeyboard.imageset/Home_Remote_Keyboard.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomeRemoteKeyboard.imageset/Home_Remote_Keyboard@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomeRetailBeacon.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomeRetailBeacon.imageset/Home_Retail_Beacon~ipad.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomeRetailBeacon.imageset/Home_Retail_Beacon~ipad@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomeRetailBeacon.imageset/Home_Retail_Beacon~iphone.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomeRetailBeacon.imageset/Home_Retail_Beacon~iphone@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomeRetailBeacon.imageset/Home_Retail_Beacon~iphone@3x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomeSmartWatch.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomeSmartWatch.imageset/Home_Smart_Watch.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomeSmartWatch.imageset/Home_Smart_Watch@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomeThermometer.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomeThermometer.imageset/Home_Thermometer~ipad.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomeThermometer.imageset/Home_Thermometer~ipad@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomeThermometer.imageset/Home_Thermometer~iphone.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomeThermometer.imageset/Home_Thermometer~iphone@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/HomeThermometer.imageset/Home_Thermometer~iphone@3x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/IBeacon.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/IBeacon.imageset/beacon_ibeacon-ipad.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/IBeacon.imageset/beacon_ibeacon-ipad@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/IBeacon.imageset/beacon_ibeacon-iphone.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/IBeacon.imageset/beacon_ibeacon-iphone@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/IBeacon.imageset/beacon_ibeacon-iphone@3x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/KeyFOBAverage.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/KeyFOBAverage.imageset/Key_FOB_Average~ipad.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/KeyFOBAverage.imageset/Key_FOB_Average~ipad@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/KeyFOBAverage.imageset/Key_FOB_Average~iphone.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/KeyFOBAverage.imageset/Key_FOB_Average~iphone@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/KeyFOBAverage.imageset/Key_FOB_Average~iphone@3x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/KeyFOBGood.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/KeyFOBGood.imageset/Key_FOB_Good~ipad.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/KeyFOBGood.imageset/Key_FOB_Good~ipad@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/KeyFOBGood.imageset/Key_FOB_Good~iphone.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/KeyFOBGood.imageset/Key_FOB_Good~iphone@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/KeyFOBGood.imageset/Key_FOB_Good~iphone@3x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/KeyFOBLED.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/KeyFOBLED.imageset/Key_FOB_LED~ipad.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/KeyFOBLED.imageset/Key_FOB_LED~ipad@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/KeyFOBLED.imageset/Key_FOB_LED~iphone.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/KeyFOBLED.imageset/Key_FOB_LED~iphone@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/KeyFOBLED.imageset/Key_FOB_LED~iphone@3x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/KeyFOBLEDLight.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/KeyFOBLEDLight.imageset/Key_FOB_LED_Light~ipad.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/KeyFOBLEDLight.imageset/Key_FOB_LED_Light~ipad@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/KeyFOBLEDLight.imageset/Key_FOB_LED_Light~iphone.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/KeyFOBLEDLight.imageset/Key_FOB_LED_Light~iphone@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/KeyFOBLEDLight.imageset/Key_FOB_LED_Light~iphone@3x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/KeyFOBWeak.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/KeyFOBWeak.imageset/Key_FOB_Weak~ipad.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/KeyFOBWeak.imageset/Key_FOB_Weak~ipad@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/KeyFOBWeak.imageset/Key_FOB_Weak~iphone.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/KeyFOBWeak.imageset/Key_FOB_Weak~iphone@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/KeyFOBWeak.imageset/Key_FOB_Weak~iphone@3x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/Keyboard.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/Keyboard.imageset/Keyboard.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/Keyboard.imageset/Keyboard@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/KeyboardCheckmark.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/KeyboardCheckmark.imageset/Keyboard_Checkmark.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/KeyboardCheckmark.imageset/Keyboard_Checkmark@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/LaunchImage.launchimage/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/LaunchImage.launchimage/launch_screen-568@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/LaunchImage.launchimage/launch_screen-iphone@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/LaunchImage.launchimage/launch_screen.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/LaunchImage.launchimage/launch_screen@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/PropertyIndicateDisabled.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/PropertyIndicateDisabled.imageset/debug_prop_indicate_disabled.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/PropertyIndicateEnabled.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/PropertyIndicateEnabled.imageset/debug_prop_indicate.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/PropertyNotifyDisabled.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/PropertyNotifyDisabled.imageset/debug_prop_notify_disabled.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/PropertyNotifyEnabled.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/PropertyNotifyEnabled.imageset/debug_prop_notify.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/PropertyReadDisabled.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/PropertyReadDisabled.imageset/debug_prop_read_disabled.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/PropertyReadEnabled.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/PropertyReadEnabled.imageset/debug_prop_read.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/PropertyWriteDisabled.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/PropertyWriteDisabled.imageset/debug_prop_write_disabled.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/PropertyWriteEnabled.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/PropertyWriteEnabled.imageset/debug_prop_write.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/PropertyWriteNoResponseDisabled.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/PropertyWriteNoResponseDisabled.imageset/no_response_grey.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/PropertyWriteNoResponseEnabled.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/PropertyWriteNoResponseEnabled.imageset/no_response_red.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/RetailBigRadar.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/RetailBigRadar.imageset/Retail_Big_Radar~ipad.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/RetailBigRadar.imageset/Retail_Big_Radar~ipad@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/RetailBigRadar.imageset/Retail_Big_Radar~iphone.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/RetailBigRadar.imageset/Retail_Big_Radar~iphone@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/RetailBigRadar.imageset/Retail_Big_Radar~iphone@3x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/RetailMessage.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/RetailMessage.imageset/Retail_Message~ipad.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/RetailMessage.imageset/Retail_Message~ipad@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/RetailMessage.imageset/Retail_Message~iphone.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/RetailMessage.imageset/Retail_Message~iphone@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/RetailMessage.imageset/Retail_Message~iphone@3x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/RetailSmallRadar.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/RetailSmallRadar.imageset/retail_small_radar-ipad.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/RetailSmallRadar.imageset/retail_small_radar-ipad@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/RetailSmallRadar.imageset/retail_small_radar-iphone.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/RetailSmallRadar.imageset/retail_small_radar-iphone@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/RetailSmallRadar.imageset/retail_small_radar-iphone@3x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/SiliconLabsLogo.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/SiliconLabsLogo.imageset/Silicon_Labs_Logo~ipad.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/SiliconLabsLogo.imageset/Silicon_Labs_Logo~ipad@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/SiliconLabsLogo.imageset/Silicon_Labs_Logo~iphone.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/SiliconLabsLogo.imageset/Silicon_Labs_Logo~iphone@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/SiliconLabsLogo.imageset/Silicon_Labs_Logo~iphone@3x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/ThermometerAdd.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/ThermometerAdd.imageset/Thermometer_Add.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/ThermometerAdd.imageset/Thermometer_Add@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/ThermometerAdd.imageset/Thermometer_Add@3x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/ThermometerClear.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/ThermometerClear.imageset/Thermometer_Clear.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/ThermometerClear.imageset/Thermometer_Clear@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/ThermometerClear.imageset/Thermometer_Clear@3x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/WatchCalendar.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/WatchCalendar.imageset/Watch_Calendar.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/WatchCalendar.imageset/Watch_Calendar@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/WatchPairMode.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/WatchPairMode.imageset/Watch_Pair_Mode.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/WatchPairMode.imageset/Watch_Pair_Mode@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/WatchPhoneCall.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/WatchPhoneCall.imageset/Watch_Phone_Call.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/WatchPhoneCall.imageset/Watch_Phone_Call@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/WatchSuccess.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/WatchSuccess.imageset/Watch_Success.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/WatchSuccess.imageset/Watch_Success@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/ad_info.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/ad_info.imageset/ad_info.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/ad_info.imageset/ad_info@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/ad_info.imageset/ad_info@3x.png (100%) create mode 100644 SiliconLabsApp/SupportingFiles/Images.xcassets/blue_arrow.imageset/Contents.json create mode 100644 SiliconLabsApp/SupportingFiles/Images.xcassets/blue_arrow.imageset/blue_arrow~ipad.png create mode 100644 SiliconLabsApp/SupportingFiles/Images.xcassets/blue_arrow.imageset/blue_arrow~ipad@2x.png create mode 100644 SiliconLabsApp/SupportingFiles/Images.xcassets/blue_arrow.imageset/blue_arrow~iphone.png create mode 100644 SiliconLabsApp/SupportingFiles/Images.xcassets/blue_arrow.imageset/blue_arrow~iphone@2x.png create mode 100644 SiliconLabsApp/SupportingFiles/Images.xcassets/blue_arrow.imageset/blue_arrow~iphone@3x.png create mode 100644 SiliconLabsApp/SupportingFiles/Images.xcassets/cancelScanning.imageset/Contents.json create mode 100644 SiliconLabsApp/SupportingFiles/Images.xcassets/cancelScanning.imageset/cancelScanning.png rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/checkmark.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/checkmark.imageset/checkmark-ipad.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/checkmark.imageset/checkmark-ipad@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/checkmark.imageset/checkmark-iphone.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/checkmark.imageset/checkmark-iphone@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/checkmark.imageset/checkmark-iphone@3x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/chevron_collapsed.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/chevron_collapsed.imageset/view_more.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/chevron_collapsed.imageset/view_more@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/chevron_collapsed.imageset/view_more@3x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/chevron_expanded.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/chevron_expanded.imageset/view_more_up.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/chevron_expanded.imageset/view_more_up_2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/chevron_expanded.imageset/view_more_up_3x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/clearText.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/clearText.imageset/clearText.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/clearText.imageset/clearText@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/clearText.imageset/clearText@3x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/debug_error.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/debug_error.imageset/debug_error.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/debug_error.imageset/debug_error@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/debug_error.imageset/debug_error@3x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/debug_loading_spinner.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/debug_loading_spinner.imageset/debug_loading_spinner.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/debug_loading_spinner.imageset/debug_loading_spinner@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/debug_loading_spinner.imageset/debug_loading_spinner@3x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/debug_not_found.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/debug_not_found.imageset/debug_not_found-ipad.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/debug_not_found.imageset/debug_not_found-ipad@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/debug_not_found.imageset/debug_not_found-iphone.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/debug_not_found.imageset/debug_not_found-iphone@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/debug_not_found.imageset/debug_not_found-iphone@3x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/debug_refresh.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/debug_refresh.imageset/debug_refresh.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/debug_refresh.imageset/debug_refresh@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/debug_refresh.imageset/debug_refresh@3x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/debug_scanning.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/debug_scanning.imageset/debug_scanning-ipad.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/debug_scanning.imageset/debug_scanning-ipad@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/debug_scanning.imageset/debug_scanning-iphone.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/debug_scanning.imageset/debug_scanning-iphone@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/debug_scanning.imageset/debug_scanning-iphone@3x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/debug_scanning_indicator.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/debug_scanning_indicator.imageset/debug_scanning_indicator-iphone.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/debug_scanning_indicator.imageset/debug_scanning_indicator-iphone@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/debug_scanning_indicator.imageset/debug_scanning_indicator-iphone@3x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/homekit_debug_scanning.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/homekit_debug_scanning.imageset/homekit_debug_scanning-ipad.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/homekit_debug_scanning.imageset/homekit_debug_scanning-ipad@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/homekit_debug_scanning.imageset/homekit_debug_scanning-iphone.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/homekit_debug_scanning.imageset/homekit_debug_scanning-iphone@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/homekit_debug_scanning.imageset/homekit_debug_scanning-iphone@3x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/icFilter.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/icFilter.imageset/icFilter.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/icFilter.imageset/icFilter@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/icFilter.imageset/icFilter@3x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/icRssi.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/icRssi.imageset/icRssi.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/icRssi.imageset/icRssi@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/icRssi.imageset/icRssi@3x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/icSearchName.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/icSearchName.imageset/icSearchName.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/icSearchName.imageset/icSearchName@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/icSearchName.imageset/icSearchName@3x.png (100%) create mode 100644 SiliconLabsApp/SupportingFiles/Images.xcassets/iconBleConnect.imageset/Contents.json create mode 100644 SiliconLabsApp/SupportingFiles/Images.xcassets/iconBleConnect.imageset/svgexport-15.png create mode 100644 SiliconLabsApp/SupportingFiles/Images.xcassets/iconBleConnect.imageset/svgexport-16.png create mode 100644 SiliconLabsApp/SupportingFiles/Images.xcassets/iconBleConnect.imageset/svgexport-17.png rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/iconBluetooth.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/iconBluetooth.imageset/iconBluetooth.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/iconBluetooth.imageset/iconBluetooth@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/iconBluetooth.imageset/iconBluetooth@3x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/iconProprietary.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/iconProprietary.imageset/iconProprietary.png (100%) create mode 100644 SiliconLabsApp/SupportingFiles/Images.xcassets/iconThread.imageset/Contents.json create mode 100644 SiliconLabsApp/SupportingFiles/Images.xcassets/iconThread.imageset/Thread_logomark_rgb@1x.png create mode 100644 SiliconLabsApp/SupportingFiles/Images.xcassets/iconThread.imageset/Thread_logomark_rgb@2x.png create mode 100644 SiliconLabsApp/SupportingFiles/Images.xcassets/iconThread.imageset/Thread_logomark_rgb@3x.png rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/iconZigbee.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/iconZigbee.imageset/iconZigbee.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/iconZigbee.imageset/iconZigbee@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/iconZigbee.imageset/iconZigbee@3x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/lightOff.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/lightOff.imageset/lightOff.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/lightOff.imageset/lightOff@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/lightOff.imageset/lightOff@3x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/lightOn.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/lightOn.imageset/lightOn.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/lightOn.imageset/lightOn@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/lightOn.imageset/lightOn@3x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/radio_off.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/radio_off.imageset/radio_off.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/radio_off.imageset/radio_off@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/radio_off.imageset/radio_off@3x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/radio_on.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/radio_on.imageset/radio_on.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/radio_on.imageset/radio_on@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/radio_on.imageset/radio_on@3x.png (100%) create mode 100644 SiliconLabsApp/SupportingFiles/Images.xcassets/red_arrow.imageset/Contents.json create mode 100644 SiliconLabsApp/SupportingFiles/Images.xcassets/red_arrow.imageset/red_arrow~ipad.png create mode 100644 SiliconLabsApp/SupportingFiles/Images.xcassets/red_arrow.imageset/red_arrow~ipad@2x.png create mode 100644 SiliconLabsApp/SupportingFiles/Images.xcassets/red_arrow.imageset/red_arrow~iphone.png create mode 100644 SiliconLabsApp/SupportingFiles/Images.xcassets/red_arrow.imageset/red_arrow~iphone@2x.png create mode 100644 SiliconLabsApp/SupportingFiles/Images.xcassets/red_arrow.imageset/red_arrow~iphone@3x.png rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/right_chevron.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/right_chevron.imageset/right_chevron.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/right_chevron.imageset/right_chevron@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/right_chevron.imageset/right_chevron@3x.png (100%) create mode 100644 SiliconLabsApp/SupportingFiles/Images.xcassets/startScanning.imageset/Contents.json create mode 100644 SiliconLabsApp/SupportingFiles/Images.xcassets/startScanning.imageset/startScanning.png rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/updateCheckmark.imageset/Contents.json (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/updateCheckmark.imageset/updateCheckmark.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/updateCheckmark.imageset/updateCheckmark@2x.png (100%) rename SiliconLabsApp/{ => SupportingFiles}/Images.xcassets/updateCheckmark.imageset/updateCheckmark@3x.png (100%) create mode 100644 SiliconLabsApp/SupportingFiles/WirelessGecko/Entitlements.entitlements create mode 100644 SiliconLabsApp/SupportingFiles/WirelessGecko/Info.plist create mode 100644 SiliconLabsApp/SupportingFiles/WirelessGecko/WirelessGecko.pch create mode 100644 SiliconLabsApp/ViewControllers/RangeTestApp/Board/SILRangeTestBoardFeatures.swift create mode 100644 SiliconLabsApp/ViewControllers/RangeTestApp/Board/SILRangeTestBoardInfo.swift create mode 100644 SiliconLabsApp/ViewControllers/RangeTestApp/Peripheral/SILRangeTestCharacteristic.swift create mode 100644 SiliconLabsApp/ViewControllers/RangeTestApp/Peripheral/SILRangeTestManufacturerData.swift create mode 100644 SiliconLabsApp/ViewControllers/RangeTestApp/Peripheral/SILRangeTestPeripheral.swift create mode 100644 SiliconLabsApp/ViewControllers/RangeTestApp/SILRangeTestAppViewController.swift create mode 100644 SiliconLabsApp/ViewControllers/RangeTestApp/SILRangeTestAppViewModel.swift create mode 100644 SiliconLabsApp/ViewControllers/RangeTestApp/SILRangeTestModeSelectionViewController.swift create mode 100644 SiliconLabsApp/ViewControllers/RangeTestApp/SILRangeTestMovingAverageCalculator.swift create mode 100644 SiliconLabsApp/ViewControllers/RangeTestApp/SILRangeTestSettingValue.swift create mode 100644 SiliconLabsApp/ViewControllers/RangeTestApp/SILRangeTestTXValueUpdater.swift delete mode 100644 SiliconLabsAppWithoutHomeKit.pch diff --git a/.gitignore b/.gitignore index b2af7bf8..0e37ed07 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,43 @@ -# Mac OSX -.DS_Store +# Created by https://www.gitignore.io/api/vim,xcode,macos,swift,objective-c + +### macOS ### +*.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### Objective-C ### # Xcode -build/* +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## Build generated +build/ +DerivedData/ + +## Various settings *.pbxuser !default.pbxuser *.mode1v3 @@ -11,14 +46,112 @@ build/* !default.mode2v3 *.perspectivev3 !default.perspectivev3 -*.xcworkspace -!default.xcworkspace -xcuserdata -profile +xcuserdata/ + +## Other *.moved-aside -DerivedData -Pods -**/Pods +*.xccheckout +*.xcscmblueprint + +## Obj-C/Swift specific +*.hmap +*.ipa +*.dSYM.zip +*.dSYM + +# CocoaPods - Refactored to standalone file + + +# Carthage - Refactored to standalone file + +# fastlane +# +# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the +# screenshots whenever they are needed. +# For more information about the recommended setup visit: +# https://docs.fastlane.tools/best-practices/source-control/#source-control + +fastlane/* +!fastlane/Fastfile +!fastlane/Appfile + +# Code Injection +# +# After new code Injection tools there's a generated folder /iOSInjectionProject +# https://github.com/johnno1962/injectionforxcode + +iOSInjectionProject/ + +### Objective-C Patch ### + +### Swift ### +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## Build generated + +## Various settings + +## Other + +## Obj-C/Swift specific + +## Playgrounds +timeline.xctimeline +playground.xcworkspace + +# Swift Package Manager +# +# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. +# Packages/ +# Package.pins +.build/ + +# CocoaPods - Refactored to standalone file + +# Carthage - Refactored to standalone file + +# fastlane +# +# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the +# screenshots whenever they are needed. +# For more information about the recommended setup visit: +# https://docs.fastlane.tools/best-practices/source-control/#source-control + + +### Vim ### +# swap +.sw[a-p] +.*.sw[a-p] +# session +Session.vim +# temporary +.netrwhist +*~ +# auto-generated tag files +tags + +### Xcode ### +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## Build generated + +## Various settings + +## Other + +### Xcode Patch ### +*.xcodeproj/* +!*.xcodeproj/project.pbxproj +!*.xcodeproj/xcshareddata/ +!*.xcworkspace/contents.xcworkspacedata +/*.gcno + -# AppCode -.idea +# End of https://www.gitignore.io/api/vim,xcode,macos,swift,objective-c +BluetoothMesh/docs/ +ios_application/ +ios/ diff --git a/Podfile b/Podfile index f275ed70..e4850789 100644 --- a/Podfile +++ b/Podfile @@ -1,36 +1,33 @@ source 'https://github.com/CocoaPods/Specs.git' -platform :ios, '8.0' +platform :ios, '9.3' inhibit_all_warnings! use_frameworks! def shared_pods - pod 'Crashlytics' + pod 'ActionSheetPicker-3.0', '~> 2.3.0' + pod 'ChameleonFramework', '~> 2.1.0' + pod 'Charts', '~> 3.3.0' pod 'Eddystone', :git => 'https://github.com/IntrepidPursuits/eddystone-ios.git', :branch => 'nservidio/add-properties-to-Generic' - pod 'Fabric' - pod 'IP-UIKit-Wisdom' - pod 'KVOController' - pod 'MZTimerLabel' - pod 'PureLayout', '~> 3.0' - pod 'SVProgressHUD' - pod 'UICircularProgressRing' - pod 'WYPopoverController', '~> 0.2.0' - pod 'XMLDictionary' + pod 'IP-UIKit-Wisdom', '~> 0.0.10' + pod 'KVOController', '~> 1.2.0' + pod 'MZTimerLabel', '~> 0.5.4' + pod 'PureLayout', '~> 3.1.4' + pod 'SVProgressHUD', '~> 2.2.5' + pod 'UICircularProgressRing', '~> 4.1.0' + pod 'WYPopoverController', '~> 0.2.2' + pod 'XMLDictionary', '~> 1.4.1' end -target 'SiliconLabsApp' do +target 'BlueGecko' do shared_pods end -target 'SiliconLabsAppWithoutHomeKit' do +target 'BlueGeckoWithHomeKit' do shared_pods end -post_install do |installer| - installer.pods_project.targets.each do |target| - target.build_configurations.each do |config| - config.build_settings['SWIFT_VERSION'] = '3.0' - end - end +target 'WirelessGecko' do + shared_pods end diff --git a/Podfile.lock b/Podfile.lock index 117ca865..24dbd3f7 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -1,29 +1,48 @@ PODS: - - Crashlytics (3.8.4): - - Fabric (~> 1.6.3) + - ActionSheetPicker-3.0 (2.3.0) + - ChameleonFramework (2.1.0): + - ChameleonFramework/Default (= 2.1.0) + - ChameleonFramework/Default (2.1.0) + - Charts (3.3.0): + - Charts/Core (= 3.3.0) + - Charts/Core (3.3.0) - Eddystone (1.1.3) - - Fabric (1.6.11) - IP-UIKit-Wisdom (0.0.10) - KVOController (1.2.0) - MZTimerLabel (0.5.4) - - PureLayout (3.0.2) - - SVProgressHUD (2.1.2) - - UICircularProgressRing (1.4.3) + - PureLayout (3.1.4) + - SVProgressHUD (2.2.5) + - UICircularProgressRing (4.1.0) - WYPopoverController (0.2.2) - XMLDictionary (1.4.1) DEPENDENCIES: - - Crashlytics + - ActionSheetPicker-3.0 (~> 2.3.0) + - ChameleonFramework (~> 2.1.0) + - Charts (~> 3.3.0) - Eddystone (from `https://github.com/IntrepidPursuits/eddystone-ios.git`, branch `nservidio/add-properties-to-Generic`) - - Fabric - - IP-UIKit-Wisdom - - KVOController - - MZTimerLabel - - PureLayout (~> 3.0) - - SVProgressHUD - - UICircularProgressRing - - WYPopoverController (~> 0.2.0) - - XMLDictionary + - IP-UIKit-Wisdom (~> 0.0.10) + - KVOController (~> 1.2.0) + - MZTimerLabel (~> 0.5.4) + - PureLayout (~> 3.1.4) + - SVProgressHUD (~> 2.2.5) + - UICircularProgressRing (~> 4.1.0) + - WYPopoverController (~> 0.2.2) + - XMLDictionary (~> 1.4.1) + +SPEC REPOS: + https://github.com/cocoapods/specs.git: + - ActionSheetPicker-3.0 + - ChameleonFramework + - Charts + - IP-UIKit-Wisdom + - KVOController + - MZTimerLabel + - PureLayout + - SVProgressHUD + - UICircularProgressRing + - WYPopoverController + - XMLDictionary EXTERNAL SOURCES: Eddystone: @@ -32,22 +51,23 @@ EXTERNAL SOURCES: CHECKOUT OPTIONS: Eddystone: - :commit: acf1bb97b16a52610ea0f55ac4b2f6cc264e26c7 + :commit: ecbaed68ff82aecc82a52671fae17552658c2b8d :git: https://github.com/IntrepidPursuits/eddystone-ios.git SPEC CHECKSUMS: - Crashlytics: 79e236942ca1e7fc641df1feb9a275360a78ab6a + ActionSheetPicker-3.0: eef157d75e151f255c5333d26656c7fbfe905a51 + ChameleonFramework: d21a3cc247abfe5e37609a283a8238b03575cf64 + Charts: ec1f57f9340054155691e84d4544a1d239d382c5 Eddystone: a56b4cb97540f43617d6fc488a9ff75eab1d66a4 - Fabric: 5911403591946b8228ab1c51d98f1d7137e863c6 IP-UIKit-Wisdom: b395a065344071b33659e5f6b918043a97c48a44 KVOController: d72ace34afea42468329623b3379ab3cd1d286b6 MZTimerLabel: cd9bfb9304540ef2a9e163384fca9c978f0dbf83 - PureLayout: 4d550abe49a94f24c2808b9b95db9131685fe4cd - SVProgressHUD: c404a55d78acbeb7ebb78b76d3faf986475a6994 - UICircularProgressRing: f90123562efc555f861f9955384a3450e81e82c0 + PureLayout: f08c01b8dec00bb14a1fefa3de4c7d9c265df85e + SVProgressHUD: 1428aafac632c1f86f62aa4243ec12008d7a51d6 + UICircularProgressRing: 5a32c01f54474571b1e66e8fa050c0f83d6d981b WYPopoverController: 00d879c25bddd1fd873dcc21aa98c8308d7f1555 XMLDictionary: fa07b6ff422b3a91d47a5de9bc82e3fc04fbd167 -PODFILE CHECKSUM: 678ec68272bdeeafeb41205d796985602c325793 +PODFILE CHECKSUM: 7d5b07fdc804b56a2f03fb911c3d79b3485319a5 -COCOAPODS: 1.3.1 +COCOAPODS: 1.5.3 diff --git a/Pods/ActionSheetPicker-3.0/LICENSE b/Pods/ActionSheetPicker-3.0/LICENSE new file mode 100644 index 00000000..1c418d6c --- /dev/null +++ b/Pods/ActionSheetPicker-3.0/LICENSE @@ -0,0 +1,24 @@ +Copyright (c) 2011, Tim Cinel (see AUTHORS) +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Pods/ActionSheetPicker-3.0/Pickers/AbstractActionSheetPicker.h b/Pods/ActionSheetPicker-3.0/Pickers/AbstractActionSheetPicker.h new file mode 100755 index 00000000..bd03ae9e --- /dev/null +++ b/Pods/ActionSheetPicker-3.0/Pickers/AbstractActionSheetPicker.h @@ -0,0 +1,126 @@ +// +//Copyright (c) 2011, Tim Cinel +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions are met: +//* Redistributions of source code must retain the above copyright +//notice, this list of conditions and the following disclaimer. +//* Redistributions in binary form must reproduce the above copyright +//notice, this list of conditions and the following disclaimer in the +//documentation and/or other materials provided with the distribution. +//* Neither the name of the nor the +//names of its contributors may be used to endorse or promote products +//derived from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +//ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +//WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +//DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +//DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +//(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +//ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +//(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +//SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#import +#import + +@class SWActionSheet; + +#define SuppressPerformSelectorLeakWarning(Stuff) \ +do { \ +_Pragma("clang diagnostic push") \ +_Pragma("clang diagnostic ignored \"-Warc-performSelector-leaks\"") \ +Stuff; \ +_Pragma("clang diagnostic pop") \ +} while (0) + +typedef NS_ENUM(NSInteger, ActionType) { + ActionTypeValue, + ActionTypeSelector, + ActionTypeBlock +}; + +typedef NS_ENUM(NSInteger, TapAction) { + TapActionNone, + TapActionSuccess, + TapActionCancel +}; + +typedef void (^ActionBlock)(void); + +static NSString *const kButtonValue = @"buttonValue"; + +static NSString *const kButtonTitle = @"buttonTitle"; + +static NSString *const kActionType = @"buttonAction"; + +static NSString *const kActionTarget = @"buttonActionTarget"; + +@interface AbstractActionSheetPicker : NSObject +@property(nonatomic, strong) SWActionSheet *actionSheet; +@property (nonatomic) UIWindowLevel windowLevel; +@property(nonatomic, assign) NSInteger tag; +@property(nonatomic, assign) int borderWidth; +@property(nonatomic, strong) UIToolbar *toolbar; +@property(nonatomic, copy) NSString *title; +@property(nonatomic, strong) UIView *pickerView; +@property(nonatomic, readonly) CGSize viewSize; +@property(nonatomic, strong) NSMutableArray *customButtons; +@property(nonatomic, assign) BOOL hideCancel; // show or hide cancel button. +@property(nonatomic, assign) CGRect presentFromRect; +@property(nonatomic) NSDictionary *titleTextAttributes; // default is nil. Used to specify Title Label attributes. +@property(nonatomic) NSAttributedString *attributedTitle; // default is nil. If titleTextAttributes not nil this value ignored. +@property(nonatomic) NSMutableDictionary *pickerTextAttributes; // default with a NSMutableParagraphStyle to set label align center. Used to specify Picker Label attributes. +@property(nonatomic) UIColor *pickerBackgroundColor; +@property(nonatomic) UIColor *toolbarBackgroundColor; +@property(nonatomic, strong) UIColor *toolbarButtonsColor; +@property(nonatomic) NSNumber *pickerBlurRadius; +@property(nonatomic, retain) Class popoverBackgroundViewClass; //allow popover customization on iPad +@property(nonatomic) UIInterfaceOrientationMask supportedInterfaceOrientations; // You can set your own supportedInterfaceOrientations value to prevent dismissing picker in some special cases. +@property(nonatomic) TapAction tapDismissAction; // Specify, which action should be fired in case of tapping outside of the picker (on top darkened side). Default is TapActionNone. +@property(nonatomic) BOOL popoverDisabled; // Disable popover behavior on iPad + + +- (void)setTextColor:(UIColor *)textColor; + +// For subclasses. +- (instancetype)initWithTarget:(id)target successAction:(SEL)successAction cancelAction:(SEL)cancelActionOrNil origin:(id)origin; + +// Present the ActionSheetPicker +- (void)showActionSheetPicker; + +// For subclasses. This is used to send a message to the target upon a successful selection and dismissal of the picker (i.e. not canceled). +- (void)notifyTarget:(id)target didSucceedWithAction:(SEL)successAction origin:(id)origin; + +// For subclasses. This is an optional message upon cancelation of the picker. +- (void)notifyTarget:(id)target didCancelWithAction:(SEL)cancelAction origin:(id)origin; + +// For subclasses. This returns a configured picker view. Subclasses should autorelease. +- (UIView *)configuredPickerView; + +// Adds custom buttons to the left of the UIToolbar that select specified values +- (void)addCustomButtonWithTitle:(NSString *)title value:(id)value; + +// Adds custom buttons to the left of the UIToolbar that implement specified block +- (void)addCustomButtonWithTitle:(NSString *)title actionBlock:(ActionBlock)block; + +// Adds custom buttons to the left of the UIToolbar that implement specified selector +- (void)addCustomButtonWithTitle:(NSString *)title target:(id)target selector:(SEL)selector; + +//For subclasses. This responds to a custom button being pressed. +- (IBAction)customButtonPressed:(id)sender; + +// Allow the user to specify a custom cancel button +- (void)setCancelButton:(UIBarButtonItem *)button; + +// Allow the user to specify a custom done button +- (void)setDoneButton:(UIBarButtonItem *)button; + +// Hide picker programmatically +- (void)hidePickerWithCancelAction; + +@end diff --git a/Pods/ActionSheetPicker-3.0/Pickers/AbstractActionSheetPicker.m b/Pods/ActionSheetPicker-3.0/Pickers/AbstractActionSheetPicker.m new file mode 100755 index 00000000..a20369bb --- /dev/null +++ b/Pods/ActionSheetPicker-3.0/Pickers/AbstractActionSheetPicker.m @@ -0,0 +1,804 @@ +// +//Copyright (c) 2011, Tim Cinel +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions are met: +//* Redistributions of source code must retain the above copyright +//notice, this list of conditions and the following disclaimer. +//* Redistributions in binary form must reproduce the above copyright +//notice, this list of conditions and the following disclaimer in the +//documentation and/or other materials provided with the distribution. +//* Neither the name of the nor the +//names of its contributors may be used to endorse or promote products +//derived from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +//ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +//WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +//DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +//DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +//(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +//ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +//(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +//SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#import "AbstractActionSheetPicker.h" +#import "SWActionSheet.h" +#import +#import + +CG_INLINE BOOL isIPhone4() { + struct utsname systemInfo; + uname(&systemInfo); + + NSString *modelName = [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding]; + return ([modelName rangeOfString:@"iPhone3"].location != NSNotFound); +} + +#define IS_WIDESCREEN ( fabs( ( double )[ [ UIScreen mainScreen ] bounds ].size.height - ( double )568 ) < DBL_EPSILON ) +#define IS_IPAD UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad +#define DEVICE_ORIENTATION [UIDevice currentDevice].orientation + +// UIInterfaceOrientationMask vs. UIInterfaceOrientation +// As far as I know, a function like this isn't available in the API. I derived this from the enum def for +// UIInterfaceOrientationMask. +#define OrientationMaskSupportsOrientation(mask, orientation) ((mask & (1 << orientation)) != 0) + + +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 + +@interface MyPopoverController : UIPopoverController +@end + +@implementation MyPopoverController ++ (BOOL)canShowPopover { + if (IS_IPAD) { + if ([UITraitCollection class]) { + UITraitCollection *traits = [UIApplication sharedApplication].keyWindow.traitCollection; + if (traits.horizontalSizeClass == UIUserInterfaceSizeClassCompact) + return NO; + } + return YES; + } + return NO; +} + +- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller traitCollection:(UITraitCollection *)traitCollection { + return UIModalPresentationNone; +} +@end + +#else + +@interface MyPopoverController:UIPopoverController +@end + +@implementation MyPopoverController ++(BOOL)canShowPopover { + return IS_IPAD; +} +@end + +#endif + +@interface AbstractActionSheetPicker () + +@property(nonatomic, strong) UIBarButtonItem *barButtonItem; +@property(nonatomic, strong) UIBarButtonItem *doneBarButtonItem; +@property(nonatomic, strong) UIBarButtonItem *cancelBarButtonItem; +@property(nonatomic, strong) UIView *containerView; +@property(nonatomic, unsafe_unretained) id target; +@property(nonatomic, assign) SEL successAction; +@property(nonatomic, assign) SEL cancelAction; +@property(nonatomic, strong) UIPopoverController *popOverController; +@property(nonatomic, strong) CIFilter *filter; +@property(nonatomic, strong) CIContext *context; +@property(nonatomic, strong) NSObject *selfReference; + +- (void)presentPickerForView:(UIView *)aView; + +- (void)configureAndPresentPopoverForView:(UIView *)aView; + +- (void)configureAndPresentActionSheetForView:(UIView *)aView; + +- (void)presentActionSheet:(SWActionSheet *)actionSheet; + +- (void)presentPopover:(UIPopoverController *)popover; + +- (void)dismissPicker; + +- (BOOL)isViewPortrait; + +- (BOOL)isValidOrigin:(id)origin; + +- (id)storedOrigin; + +- (UIToolbar *)createPickerToolbarWithTitle:(NSString *)aTitle; + +- (UIBarButtonItem *)createButtonWithType:(UIBarButtonSystemItem)type target:(id)target action:(SEL)buttonAction; + +- (IBAction)actionPickerDone:(id)sender; + +- (IBAction)actionPickerCancel:(id)sender; +@end + +@implementation AbstractActionSheetPicker + +#pragma mark - Abstract Implementation + +- (instancetype)init { + self = [super init]; + if (self) { + self.windowLevel = UIWindowLevelAlert; + self.presentFromRect = CGRectZero; + self.popoverBackgroundViewClass = nil; + self.popoverDisabled = NO; + +#pragma clang diagnostic push +#pragma ide diagnostic ignored "UnavailableInDeploymentTarget" + if ([UIApplication instancesRespondToSelector:@selector(supportedInterfaceOrientationsForWindow:)]) + self.supportedInterfaceOrientations = (UIInterfaceOrientationMask) [[UIApplication sharedApplication] + supportedInterfaceOrientationsForWindow: + [UIApplication sharedApplication].keyWindow]; + else { + self.supportedInterfaceOrientations = UIInterfaceOrientationMaskAllButUpsideDown; + if (IS_IPAD) + self.supportedInterfaceOrientations |= (1 << UIInterfaceOrientationPortraitUpsideDown); + } +#pragma clang diagnostic pop + + UIBarButtonItem *sysDoneButton = [self createButtonWithType:UIBarButtonSystemItemDone target:self + action:@selector(actionPickerDone:)]; + + UIBarButtonItem *sysCancelButton = [self createButtonWithType:UIBarButtonSystemItemCancel target:self + action:@selector(actionPickerCancel:)]; + + [self setCancelBarButtonItem:sysCancelButton]; + [self setDoneBarButtonItem:sysDoneButton]; + + self.tapDismissAction = TapActionNone; + //allows us to use this without needing to store a reference in calling class + self.selfReference = self; + + NSMutableParagraphStyle *labelParagraphStyle = [[NSMutableParagraphStyle alloc] init]; + labelParagraphStyle.alignment = NSTextAlignmentCenter; + self.pickerTextAttributes = [@{NSParagraphStyleAttributeName : labelParagraphStyle} mutableCopy]; + + self.context = [CIContext contextWithOptions:nil]; + self.filter = [CIFilter filterWithName:@"CIGaussianBlur"]; + } + + return self; +} + + +- (void)setTextColor:(UIColor *)textColor { + if (self.pickerTextAttributes) { + self.pickerTextAttributes[NSForegroundColorAttributeName] = textColor; + } else { + self.pickerTextAttributes = [@{NSForegroundColorAttributeName : [UIColor whiteColor]} mutableCopy]; + } +} + +- (instancetype)initWithTarget:(id)target successAction:(SEL)successAction cancelAction:(SEL)cancelActionOrNil origin:(id)origin { + self = [self init]; + if (self) { + self.target = target; + self.successAction = successAction; + self.cancelAction = cancelActionOrNil; + + if ([origin isKindOfClass:[UIBarButtonItem class]]) + self.barButtonItem = origin; + else if ([origin isKindOfClass:[UIView class]]) + self.containerView = origin; + else + NSAssert(NO, @"Invalid origin provided to ActionSheetPicker ( %@ )", origin); + } + return self; +} + +- (void)dealloc { + //need to clear picker delegates and datasources, otherwise they may call this object after it's gone + if ([self.pickerView respondsToSelector:@selector(setDelegate:)]) + [self.pickerView performSelector:@selector(setDelegate:) withObject:nil]; + + if ([self.pickerView respondsToSelector:@selector(setDataSource:)]) + [self.pickerView performSelector:@selector(setDataSource:) withObject:nil]; + + if ([self.pickerView respondsToSelector:@selector(removeTarget:action:forControlEvents:)]) + [((UIControl *) self.pickerView) removeTarget:nil action:NULL forControlEvents:UIControlEventAllEvents]; + + self.target = nil; + + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +- (UIView *)configuredPickerView { + NSAssert(NO, @"This is an abstract class, you must use a subclass of AbstractActionSheetPicker (like ActionSheetStringPicker)"); + return nil; +} + +- (void)notifyTarget:(id)target didSucceedWithAction:(SEL)successAction origin:(id)origin { + NSAssert(NO, @"This is an abstract class, you must use a subclass of AbstractActionSheetPicker (like ActionSheetStringPicker)"); +} + +- (void)notifyTarget:(id)target didCancelWithAction:(SEL)cancelAction origin:(id)origin { + if (target && cancelAction && [target respondsToSelector:cancelAction]) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + [target performSelector:cancelAction withObject:origin]; +#pragma clang diagnostic pop + } +} + +#pragma mark - Actions + +- (void)showActionSheetPicker { + UIView *masterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.viewSize.width, 260)]; + + // to fix bug, appeared only on iPhone 4 Device: https://github.com/skywinder/ActionSheetPicker-3.0/issues/5 + if (isIPhone4()) { + masterView.backgroundColor = [UIColor colorWithRed:0.97 green:0.97 blue:0.97 alpha:1.0]; + } + self.toolbar = [self createPickerToolbarWithTitle:self.title]; + [masterView addSubview:self.toolbar]; + + //ios7 picker draws a darkened alpha-only region on the first and last 8 pixels horizontally, but blurs the rest of its background. To make the whole popup appear to be edge-to-edge, we have to add blurring to the remaining left and right edges. + if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) { + CGRect rect = CGRectMake(0, self.toolbar.frame.origin.y, _borderWidth, masterView.frame.size.height - self.toolbar.frame.origin.y); + UIToolbar *leftEdge = [[UIToolbar alloc] initWithFrame:rect]; + rect.origin.x = masterView.frame.size.width - _borderWidth; + UIToolbar *rightEdge = [[UIToolbar alloc] initWithFrame:rect]; +#pragma clang diagnostic push +#pragma ide diagnostic ignored "UnavailableInDeploymentTarget" + leftEdge.barTintColor = rightEdge.barTintColor = self.toolbar.barTintColor; +#pragma clang diagnostic pop + [masterView insertSubview:leftEdge atIndex:0]; + [masterView insertSubview:rightEdge atIndex:0]; + } + + self.pickerView = [self configuredPickerView]; + NSAssert(_pickerView != NULL, @"Picker view failed to instantiate, perhaps you have invalid component data."); + // toolbar hidden remove the toolbar frame and update pickerview frame + if (self.toolbar.hidden) { + int halfWidth = (int) (_borderWidth * 0.5f); + masterView.frame = CGRectMake(0, 0, self.viewSize.width, 220); + self.pickerView.frame = CGRectMake(0, halfWidth, self.viewSize.width, 220 - halfWidth); + } + [masterView addSubview:_pickerView]; + + if ((![MyPopoverController canShowPopover] || self.popoverDisabled) && !self.pickerBackgroundColor && !self.toolbarBackgroundColor && [self.pickerBlurRadius intValue] > 0) { + [self blurPickerBackground]; + } else { + [self presentPickerForView:masterView]; + } + +#pragma clang diagnostic push +#pragma ide diagnostic ignored "UnavailableInDeploymentTarget" + { + switch (self.tapDismissAction) { + case TapActionNone: + break; + case TapActionSuccess: { + // add tap dismiss action + self.actionSheet.window.userInteractionEnabled = YES; + UITapGestureRecognizer *tapAction = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(actionPickerDone:)]; + tapAction.delegate = self; + [self.actionSheet.window addGestureRecognizer:tapAction]; + break; + } + case TapActionCancel: { + // add tap dismiss action + self.actionSheet.window.userInteractionEnabled = YES; + UITapGestureRecognizer *tapAction = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(actionPickerCancel:)]; + tapAction.delegate = self; + [self.actionSheet.window addGestureRecognizer:tapAction]; + break; + } + }; + } +#pragma clang diagnostic pop + +} + +- (IBAction)actionPickerDone:(id)sender { + [self notifyTarget:self.target didSucceedWithAction:self.successAction origin:[self storedOrigin]]; + [self dismissPicker]; +} + +- (IBAction)actionPickerCancel:(id)sender { + [self notifyTarget:self.target didCancelWithAction:self.cancelAction origin:[self storedOrigin]]; + [self dismissPicker]; +} + +- (void)dismissPicker { +#if __IPHONE_4_1 <= __IPHONE_OS_VERSION_MAX_ALLOWED + if (self.actionSheet) +#else + if (self.actionSheet && [self.actionSheet isVisible]) +#endif + [_actionSheet dismissWithClickedButtonIndex:0 animated:YES]; + else if (self.popOverController && self.popOverController.popoverVisible) + [_popOverController dismissPopoverAnimated:YES]; + self.actionSheet = nil; + self.popOverController = nil; + self.selfReference = nil; +} + +#pragma mark - Custom Buttons + +- (NSMutableArray *)customButtons { + if (!_customButtons) { + _customButtons = [[NSMutableArray alloc] init]; + } + + return _customButtons; +} + +- (void)addCustomButtonWithTitle:(NSString *)title value:(id)value { + if (!title) + title = @""; + if (!value) + value = @0; + NSDictionary *buttonDetails = @{ + kButtonTitle : title, + kActionType : @(ActionTypeValue), + kButtonValue : value + }; + [self.customButtons addObject:buttonDetails]; +} + +- (void)addCustomButtonWithTitle:(NSString *)title actionBlock:(ActionBlock)block { + if (!title) + title = @""; + if (!block) + block = (^{ + }); + NSDictionary *buttonDetails = @{ + kButtonTitle : title, + kActionType : @(ActionTypeBlock), + kButtonValue : [block copy] + }; + [self.customButtons addObject:buttonDetails]; +} + +- (void)addCustomButtonWithTitle:(NSString *)title target:(id)target selector:(SEL)selector { + if (!title) + title = @""; + if (!target) + target = [NSNull null]; + NSDictionary *buttonDetails = @{ + kButtonTitle : title, + kActionType : @(ActionTypeSelector), + kActionTarget : target, + kButtonValue : [NSValue valueWithPointer:selector] + }; + [self.customButtons addObject:buttonDetails]; +} + +- (IBAction)customButtonPressed:(id)sender { + UIBarButtonItem *button = (UIBarButtonItem *) sender; + NSInteger index = button.tag; + NSAssert((index >= 0 && index < self.customButtons.count), @"Bad custom button tag: %ld, custom button count: %lu", (long) index, (unsigned long) self.customButtons.count); + + NSDictionary *buttonDetails = (self.customButtons)[(NSUInteger) index]; + NSAssert(buttonDetails != NULL, @"Custom button dictionary is invalid"); + + ActionType actionType = (ActionType) [buttonDetails[kActionType] integerValue]; + switch (actionType) { + case ActionTypeValue: { + NSAssert([self.pickerView respondsToSelector:@ + selector(selectRow:inComponent:animated:)], @"customButtonPressed not overridden, cannot interact with subclassed pickerView"); + NSInteger buttonValue = [buttonDetails[kButtonValue] integerValue]; + UIPickerView *picker = (UIPickerView *) self.pickerView; + NSAssert(picker != NULL, @"PickerView is invalid"); + [picker selectRow:buttonValue inComponent:0 animated:YES]; + if ([self respondsToSelector:@selector(pickerView:didSelectRow:inComponent:)]) { + void (*objc_msgSendTyped)(id target, SEL _cmd, id pickerView, NSInteger row, NSInteger component) = (void *) objc_msgSend; // sending Integers as params + objc_msgSendTyped(self, @selector(pickerView:didSelectRow:inComponent:), picker, buttonValue, 0); + } + break; + } + + case ActionTypeBlock: { + ActionBlock actionBlock = buttonDetails[kButtonValue]; + [self dismissPicker]; + if (actionBlock) + actionBlock(); + break; + } + + case ActionTypeSelector: { + SEL selector = [buttonDetails[kButtonValue] pointerValue]; + id target = buttonDetails[kActionTarget]; + [self dismissPicker]; + if (target && [target respondsToSelector:selector]) { + SuppressPerformSelectorLeakWarning ( + [target performSelector:selector]; + ); + } + break; + } + + default: + NSAssert(false, @"Unknown action type"); + break; + } +} + +// Allow the user to specify a custom cancel button +- (void)setCancelButton:(UIBarButtonItem *)button { + if (!button) { + self.hideCancel = YES; + return; + } + + if ([button.customView isKindOfClass:[UIButton class]]) { + UIButton *uiButton = (UIButton *) button.customView; + [uiButton addTarget:self action:@selector(actionPickerCancel:) forControlEvents:UIControlEventTouchUpInside]; + } + else { + [button setTarget:self]; + [button setAction:@selector(actionPickerCancel:)]; + } + self.cancelBarButtonItem = button; +} + +// Allow the user to specify a custom done button +- (void)setDoneButton:(UIBarButtonItem *)button { + if ([button.customView isKindOfClass:[UIButton class]]) { + UIButton *uiButton = (UIButton *) button.customView; + [button setAction:@selector(actionPickerDone:)]; + [uiButton addTarget:self action:@selector(actionPickerDone:) forControlEvents:UIControlEventTouchUpInside]; + } + else { + [button setTarget:self]; + [button setAction:@selector(actionPickerDone:)]; + } + [button setTarget:self]; + [button setAction:@selector(actionPickerDone:)]; + self.doneBarButtonItem = button; +} + +- (void)hidePickerWithCancelAction { + [self actionPickerCancel:nil]; +} + + +- (UIToolbar *)createPickerToolbarWithTitle:(NSString *)title { + CGRect frame = CGRectMake(0, 0, self.viewSize.width, 44); + UIToolbar *pickerToolbar = [[UIToolbar alloc] initWithFrame:frame]; + pickerToolbar.barStyle = (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) ? UIBarStyleDefault : UIBarStyleBlackTranslucent; + + pickerToolbar.barTintColor = self.toolbarBackgroundColor; + pickerToolbar.tintColor = self.toolbarButtonsColor; + + NSMutableArray *barItems = [[NSMutableArray alloc] init]; + + if (!self.hideCancel) { + [barItems addObject:self.cancelBarButtonItem]; + } + + NSInteger index = 0; + for (NSDictionary *buttonDetails in self.customButtons) { + NSString *buttonTitle = buttonDetails[kButtonTitle]; + + UIBarButtonItem *button; + if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) { + button = [[UIBarButtonItem alloc] initWithTitle:buttonTitle style:UIBarButtonItemStylePlain + target:self action:@selector(customButtonPressed:)]; + } + else { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + button = [[UIBarButtonItem alloc] initWithTitle:buttonTitle style:UIBarButtonItemStyleBordered + target:self action:@selector(customButtonPressed:)]; +#pragma clang diagnostic pop + } + + button.tag = index; + [barItems addObject:button]; + index++; + } + + UIBarButtonItem *flexSpace = [self createButtonWithType:UIBarButtonSystemItemFlexibleSpace target:nil action:nil]; + [barItems addObject:flexSpace]; + if (title) { + UIBarButtonItem *labelButton; + + labelButton = [self createToolbarLabelWithTitle:title titleTextAttributes:self.titleTextAttributes andAttributedTitle:self.attributedTitle]; + + [barItems addObject:labelButton]; + [barItems addObject:flexSpace]; + } + [barItems addObject:self.doneBarButtonItem]; + + [pickerToolbar setItems:barItems animated:NO]; + [pickerToolbar layoutIfNeeded]; + return pickerToolbar; +} + +- (UIBarButtonItem *)createToolbarLabelWithTitle:(NSString *)aTitle + titleTextAttributes:(NSDictionary *)titleTextAttributes + andAttributedTitle:(NSAttributedString *)attributedTitle { + UILabel *toolBarItemLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 180, 30)]; + [toolBarItemLabel setTextAlignment:NSTextAlignmentCenter]; + [toolBarItemLabel setBackgroundColor:[UIColor clearColor]]; + + CGFloat strikeWidth; + CGSize textSize; + + + if (titleTextAttributes) { + toolBarItemLabel.attributedText = [[NSAttributedString alloc] initWithString:aTitle attributes:titleTextAttributes]; + textSize = toolBarItemLabel.attributedText.size; + } else if (attributedTitle) { + toolBarItemLabel.attributedText = attributedTitle; + textSize = toolBarItemLabel.attributedText.size; + } + else { + [toolBarItemLabel setTextColor:(NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) ? [UIColor blackColor] : [UIColor whiteColor]]; + [toolBarItemLabel setFont:[UIFont boldSystemFontOfSize:16]]; + toolBarItemLabel.text = aTitle; + + if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) { +#pragma clang diagnostic push +#pragma ide diagnostic ignored "UnavailableInDeploymentTarget" + textSize = [[toolBarItemLabel text] sizeWithAttributes:@{NSFontAttributeName : [toolBarItemLabel font]}]; +#pragma clang diagnostic pop + } else { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + textSize = [[toolBarItemLabel text] sizeWithFont:[toolBarItemLabel font]]; +#pragma clang diagnostic pop + } + } + + strikeWidth = textSize.width; + + if (strikeWidth < 180) { + [toolBarItemLabel sizeToFit]; + } + + UIBarButtonItem *buttonLabel = [[UIBarButtonItem alloc] initWithCustomView:toolBarItemLabel]; + return buttonLabel; +} + +- (UIBarButtonItem *)createButtonWithType:(UIBarButtonSystemItem)type target:(id)target action:(SEL)buttonAction { + + UIBarButtonItem *barButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:type target:target + action:buttonAction]; + return barButton; +} + +#pragma mark - Custom Color + +- (void)setPickerBackgroundColor:(UIColor *)backgroundColor { + _pickerBackgroundColor = backgroundColor; + _actionSheet.bgView.backgroundColor = backgroundColor; +} + +#pragma mark - Picker blur effect + +- (void)blurPickerBackground { + UIWindow *window = [UIApplication sharedApplication].delegate.window; + UIViewController *rootViewController = window.rootViewController; + + UIView *masterView = self.pickerView.superview; + + self.pickerView.backgroundColor = [UIColor clearColor]; + masterView.backgroundColor = [UIColor clearColor]; + + // Get the snapshot + UIGraphicsBeginImageContext(rootViewController.view.bounds.size); + [rootViewController.view drawViewHierarchyInRect:rootViewController.view.bounds afterScreenUpdates:NO]; + UIImage *backgroundImage = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + + [self presentPickerForView:masterView]; + + // Crop the snapshot to match picker frame + CIImage *image = [CIImage imageWithCGImage:[backgroundImage CGImage]]; + [self.filter setValue:image forKey:kCIInputImageKey]; + [self.filter setValue:self.pickerBlurRadius forKey:kCIInputRadiusKey]; + + CGRect blurFrame = [rootViewController.view convertRect:self.pickerView.frame fromView:masterView]; + // CoreImage coordinate system and UIKit coordinate system differs, so we need to adjust the frame + blurFrame.origin.y = - (blurFrame.origin.y - rootViewController.view.frame.size.height) - blurFrame.size.height; + + CGImageRef imageRef = [self.context createCGImage:self.filter.outputImage fromRect:blurFrame]; + + UIImageView *blurredImageView = [[UIImageView alloc] initWithFrame:self.pickerView.frame]; + blurredImageView.image = [UIImage imageWithCGImage:imageRef]; + blurredImageView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; + + [masterView addSubview:blurredImageView]; + [masterView sendSubviewToBack:blurredImageView]; + + CGImageRelease(imageRef); +} + +#pragma mark - Utilities and Accessors + +- (CGSize)viewSize { + if (IS_IPAD) { + if (!self.popoverDisabled && [MyPopoverController canShowPopover]) + return CGSizeMake(320, 320); + return [UIApplication sharedApplication].keyWindow.bounds.size; + } + +#if defined(__IPHONE_8_0) + if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_7_1) { + //iOS 7.1 or earlier + if ([self isViewPortrait]) + return CGSizeMake(320, IS_WIDESCREEN ? 568 : 480); + return CGSizeMake(IS_WIDESCREEN ? 568 : 480, 320); + + } else { + //iOS 8 or later + return [[UIScreen mainScreen] bounds].size; + } +#else + if ( [self isViewPortrait] ) + return CGSizeMake(320 , IS_WIDESCREEN ? 568 : 480); + return CGSizeMake(IS_WIDESCREEN ? 568 : 480, 320); +#endif +} + +- (BOOL)isViewPortrait { + return UIInterfaceOrientationIsPortrait([UIApplication sharedApplication].statusBarOrientation); +} + +- (BOOL)isValidOrigin:(id)origin { + if (!origin) + return NO; + BOOL isButton = [origin isKindOfClass:[UIBarButtonItem class]]; + BOOL isView = [origin isKindOfClass:[UIView class]]; + return (isButton || isView); +} + +- (id)storedOrigin { + if (self.barButtonItem) + return self.barButtonItem; + return self.containerView; +} + +#pragma mark - Popovers and ActionSheets + +- (void)presentPickerForView:(UIView *)aView { + self.presentFromRect = aView.frame; + + if (!self.popoverDisabled && [MyPopoverController canShowPopover]) + [self configureAndPresentPopoverForView:aView]; + else + [self configureAndPresentActionSheetForView:aView]; +} + +- (void)configureAndPresentActionSheetForView:(UIView *)aView { + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didRotate:) name:UIApplicationWillChangeStatusBarOrientationNotification object:nil]; + + _actionSheet = [[SWActionSheet alloc] initWithView:aView windowLevel:self.windowLevel]; + if (self.pickerBackgroundColor) { + _actionSheet.bgView.backgroundColor = self.pickerBackgroundColor; + } + + [self presentActionSheet:_actionSheet]; + + // Use beginAnimations for a smoother popup animation, otherwise the UIActionSheet pops into view + [UIView beginAnimations:nil context:nil]; +// _actionSheet.bounds = CGRectMake(0, 0, self.viewSize.width, sheetHeight); + [UIView commitAnimations]; +} + +- (void)didRotate:(NSNotification *)notification { + if (OrientationMaskSupportsOrientation(self.supportedInterfaceOrientations, DEVICE_ORIENTATION)) + [self dismissPicker]; +} + +- (void)presentActionSheet:(SWActionSheet *)actionSheet { + NSParameterAssert(actionSheet != NULL); + if (self.barButtonItem) + [actionSheet showFromBarButtonItem:_barButtonItem animated:YES]; + else + [actionSheet showInContainerView]; +} + +- (void)configureAndPresentPopoverForView:(UIView *)aView { + UIViewController *viewController = [[UIViewController alloc] initWithNibName:nil bundle:nil]; + viewController.view = aView; + + if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) { +#pragma clang diagnostic push +#pragma ide diagnostic ignored "UnavailableInDeploymentTarget" + viewController.preferredContentSize = aView.frame.size; +#pragma clang diagnostic pop + } + else { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + viewController.contentSizeForViewInPopover = viewController.view.frame.size; +#pragma clang diagnostic pop + } + + _popOverController = [[MyPopoverController alloc] initWithContentViewController:viewController]; + _popOverController.delegate = self; + if (self.pickerBackgroundColor) { + self.popOverController.backgroundColor = self.pickerBackgroundColor; + } + if (self.popoverBackgroundViewClass) { + [self.popOverController setPopoverBackgroundViewClass:self.popoverBackgroundViewClass]; + } + + [self presentPopover:_popOverController]; +} + +- (void)presentPopover:(UIPopoverController *)popover { + NSParameterAssert(popover != NULL); + if (self.barButtonItem) { + if (_containerView != nil) { + [popover presentPopoverFromRect:CGRectMake(_containerView.frame.size.width / 2.f, 0.f, 0, 0) inView:_containerView permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES]; + } else { + [popover presentPopoverFromBarButtonItem:_barButtonItem permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES]; + } + + return; + } + else if ((self.containerView)) { + dispatch_async(dispatch_get_main_queue(), ^{ + [popover presentPopoverFromRect:_containerView.bounds inView:_containerView + permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES]; + + }); + return; + } + // Unfortunately, things go to hell whenever you try to present a popover from a table view cell. These are failsafes. + UIView *origin = nil; + CGRect presentRect = CGRectZero; + @try { + origin = (_containerView.superview ? _containerView.superview : _containerView); + presentRect = origin.bounds; + dispatch_async(dispatch_get_main_queue(), ^{ + [popover presentPopoverFromRect:presentRect inView:origin + permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES]; + + }); + } + @catch (NSException *exception) { + origin = [[[[UIApplication sharedApplication] keyWindow] rootViewController] view]; + presentRect = CGRectMake(origin.center.x, origin.center.y, 1, 1); + dispatch_async(dispatch_get_main_queue(), ^{ + [popover presentPopoverFromRect:presentRect inView:origin + permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES]; + + }); + } +} + +#pragma mark - Popoverdelegate + +- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController { + switch (self.tapDismissAction) { + case TapActionSuccess: { + [self notifyTarget:self.target didSucceedWithAction:self.successAction origin:self.storedOrigin]; + break; + } + case TapActionNone: + case TapActionCancel: { + [self notifyTarget:self.target didCancelWithAction:self.cancelAction origin:self.storedOrigin]; + break; + } + }; +} + +#pragma mark UIGestureRecognizerDelegate + +- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer { + CGPoint location = [gestureRecognizer locationInView:self.toolbar]; + return !CGRectContainsPoint(self.toolbar.bounds, location); +} + +@end + diff --git a/Pods/ActionSheetPicker-3.0/Pickers/ActionSheetCustomPicker.h b/Pods/ActionSheetPicker-3.0/Pickers/ActionSheetCustomPicker.h new file mode 100644 index 00000000..9b177f36 --- /dev/null +++ b/Pods/ActionSheetPicker-3.0/Pickers/ActionSheetCustomPicker.h @@ -0,0 +1,37 @@ +// +// ActionSheetPicker.h +// ActionSheetPicker +// +// Created by on 13/03/2012. +// Copyright (c) 2012 Club 15CC. All rights reserved. +// +#import +#import "AbstractActionSheetPicker.h" +#import "ActionSheetCustomPickerDelegate.h" + +@interface ActionSheetCustomPicker : AbstractActionSheetPicker +{ +} + +///////////////////////////////////////////////////////////////////////// +#pragma mark - Properties +///////////////////////////////////////////////////////////////////////// +@property(nonatomic, strong) id delegate; + + +///////////////////////////////////////////////////////////////////////// +#pragma mark - Init Methods +///////////////////////////////////////////////////////////////////////// + +/** Designated init */ +- (instancetype)initWithTitle:(NSString *)title delegate:(id )delegate showCancelButton:(BOOL)showCancelButton origin:(id)origin; + +- (instancetype)initWithTitle:(NSString *)title delegate:(id )delegate showCancelButton:(BOOL)showCancelButton origin:(id)origin initialSelections:(NSArray *)initialSelections; + +/** Convenience class method for creating an launched */ ++ (instancetype)showPickerWithTitle:(NSString *)title delegate:(id )delegate showCancelButton:(BOOL)showCancelButton origin:(id)origin; + ++ (instancetype)showPickerWithTitle:(NSString *)title delegate:(id )delegate showCancelButton:(BOOL)showCancelButton origin:(id)origin initialSelections:(NSArray *)initialSelections; + + +@end diff --git a/Pods/ActionSheetPicker-3.0/Pickers/ActionSheetCustomPicker.m b/Pods/ActionSheetPicker-3.0/Pickers/ActionSheetCustomPicker.m new file mode 100644 index 00000000..6b7734ac --- /dev/null +++ b/Pods/ActionSheetPicker-3.0/Pickers/ActionSheetCustomPicker.m @@ -0,0 +1,125 @@ +// +// ActionSheetPicker.m +// ActionSheetPicker +// +// Created by on 13/03/2012. +// Copyright (c) 2012 Club 15CC. All rights reserved. +// + +#import "ActionSheetCustomPicker.h" + +@interface ActionSheetCustomPicker () +@property(nonatomic, strong) NSArray *initialSelections; +@end + +@implementation ActionSheetCustomPicker + +///////////////////////////////////////////////////////////////////////// +#pragma mark - Init +///////////////////////////////////////////////////////////////////////// + +- (instancetype)initWithTitle:(NSString *)title delegate:(id )delegate showCancelButton:(BOOL)showCancelButton origin:(id)origin +{ + return [self initWithTitle:title delegate:delegate + showCancelButton:showCancelButton origin:origin + initialSelections:nil]; +} + ++ (instancetype)showPickerWithTitle:(NSString *)title delegate:(id )delegate showCancelButton:(BOOL)showCancelButton origin:(id)origin +{ + return [self showPickerWithTitle:title delegate:delegate showCancelButton:showCancelButton origin:origin + initialSelections:nil ]; +} + +- (instancetype)initWithTitle:(NSString *)title delegate:(id )delegate showCancelButton:(BOOL)showCancelButton origin:(id)origin initialSelections:(NSArray *)initialSelections +{ + if ( self = [self initWithTarget:nil successAction:nil cancelAction:nil origin:origin] ) + { + + self.title = title; + self.hideCancel = !showCancelButton; + NSAssert(delegate, @"Delegate can't be nil"); + _delegate = delegate; + if (initialSelections) + self.initialSelections = [[NSArray alloc] initWithArray:initialSelections]; + } + return self; +} + +///////////////////////////////////////////////////////////////////////// + ++ (instancetype)showPickerWithTitle:(NSString *)title delegate:(id )delegate showCancelButton:(BOOL)showCancelButton origin:(id)origin initialSelections:(NSArray *)initialSelections +{ + ActionSheetCustomPicker *picker = [[ActionSheetCustomPicker alloc] initWithTitle:title delegate:delegate + showCancelButton:showCancelButton origin:origin + initialSelections:initialSelections]; + [picker showActionSheetPicker]; + return picker; +} + +///////////////////////////////////////////////////////////////////////// +#pragma mark - AbstractActionSheetPicker fulfilment +///////////////////////////////////////////////////////////////////////// + +- (UIView *)configuredPickerView +{ + CGRect pickerFrame = CGRectMake(0, 40, self.viewSize.width, 216); + UIPickerView *pv = [[UIPickerView alloc] initWithFrame:pickerFrame]; + self.pickerView = pv; + + // Default to our delegate being the picker's delegate and datasource + pv.delegate = _delegate; + pv.dataSource = _delegate; + pv.showsSelectionIndicator = YES; + + if ( self.initialSelections ) + { + NSAssert(pv.numberOfComponents == self.initialSelections.count, @"Number of sections not match"); + for (NSUInteger i = 0; i < [self.initialSelections count]; i++) + { + + NSInteger row = [(NSNumber *) self.initialSelections[i] integerValue]; + NSAssert([pv numberOfRowsInComponent:i] > row, @"Number of sections not match"); + [pv selectRow:row inComponent:i animated:NO]; + + // Strangely, the above selectRow:inComponent:animated: will not call + // pickerView:didSelectRow:inComponent: automatically, so we manually call it. + [pv reloadAllComponents]; + } + + } + + // Allow the delegate to override and set additional configs + //to backward compatibility: + if ( [_delegate respondsToSelector:@selector(actionSheetPicker:configurePickerView:)] ) + { + [_delegate actionSheetPicker:self configurePickerView:pv]; + } + return pv; +} + + +///////////////////////////////////////////////////////////////////////// + +- (void)notifyTarget:(id)target didSucceedWithAction:(SEL)successAction origin:(id)origin +{ + // Ignore parent args and just notify the delegate + if ( [_delegate respondsToSelector:@selector(actionSheetPickerDidSucceed:origin:)] ) + { + [_delegate actionSheetPickerDidSucceed:self origin:origin]; + } +} + +///////////////////////////////////////////////////////////////////////// + +- (void)notifyTarget:(id)target didCancelWithAction:(SEL)cancelAction origin:(id)origin +{ + // Ignore parent args and just notify the delegate + if ( [_delegate respondsToSelector:@selector(actionSheetPickerDidCancel:origin:)] ) + { + [_delegate actionSheetPickerDidCancel:self origin:origin]; + } +} + + +@end diff --git a/Pods/ActionSheetPicker-3.0/Pickers/ActionSheetCustomPickerDelegate.h b/Pods/ActionSheetPicker-3.0/Pickers/ActionSheetCustomPickerDelegate.h new file mode 100644 index 00000000..bb257cd0 --- /dev/null +++ b/Pods/ActionSheetPicker-3.0/Pickers/ActionSheetCustomPickerDelegate.h @@ -0,0 +1,39 @@ +// +// ActionSheetPickerDelegate.h +// ActionSheetPicker +// +// Created by on 13/03/2012. +// Copyright (c) 2012 Club 15CC. All rights reserved. +// + +#import +#import "AbstractActionSheetPicker.h" + +@protocol ActionSheetCustomPickerDelegate + +@optional + +/** + Allow the delegate to override default settings for the picker + + Allows for instance, ability to set separate delegates and data sources as well as GUI settings on the UIPickerView + If not defined and explicily overridden then this class will be the delegate and dataSource. + */ +- (void)configurePickerView:(UIPickerView *)pickerView DEPRECATED_MSG_ATTRIBUTE("use -actionSheetPicker:configurePickerView: instead."); +- (void)actionSheetPicker:(AbstractActionSheetPicker *)actionSheetPicker configurePickerView:(UIPickerView *)pickerView; + +/** + Success callback + + \param actionSheetPicker .pickerView property accesses the picker. Requires a cast to UIView subclass for the picker + \param origin The entity which launched the ActionSheetPicker + */ +- (void)actionSheetPickerDidSucceed:(AbstractActionSheetPicker *)actionSheetPicker origin:(id)origin; + +/** Cancel callback. See actionSheetPickerDidSuccess:origin: */ +- (void)actionSheetPickerDidCancel:(AbstractActionSheetPicker *)actionSheetPicker origin:(id)origin; + + +@required + +@end \ No newline at end of file diff --git a/Pods/ActionSheetPicker-3.0/Pickers/ActionSheetDatePicker.h b/Pods/ActionSheetPicker-3.0/Pickers/ActionSheetDatePicker.h new file mode 100755 index 00000000..d64a69a2 --- /dev/null +++ b/Pods/ActionSheetPicker-3.0/Pickers/ActionSheetDatePicker.h @@ -0,0 +1,95 @@ +// +//Copyright (c) 2011, Tim Cinel +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions are met: +//* Redistributions of source code must retain the above copyright +//notice, this list of conditions and the following disclaimer. +//* Redistributions in binary form must reproduce the above copyright +//notice, this list of conditions and the following disclaimer in the +//documentation and/or other materials provided with the distribution. +//* Neither the name of the nor the +//names of its contributors may be used to endorse or promote products +//derived from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +//ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +//WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +//DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +//DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +//(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +//ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +//(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +//SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#import "AbstractActionSheetPicker.h" + +@class ActionSheetDatePicker; + +typedef void(^ActionDateDoneBlock)(ActionSheetDatePicker *picker, id selectedDate, id origin); //selectedDate is NSDate or NSNumber for "UIDatePickerModeCountDownTimer" +typedef void(^ActionDateCancelBlock)(ActionSheetDatePicker *picker); + +@interface ActionSheetDatePicker : AbstractActionSheetPicker + +@property (nonatomic, retain) NSDate *minimumDate; // specify min/max date range. default is nil. When min > max, the values are ignored. Ignored in countdown timer mode +@property (nonatomic, retain) NSDate *maximumDate; // default is nil + +@property (nonatomic) NSInteger minuteInterval; // display minutes wheel with interval. interval must be evenly divided into 60. default is 1. min is 1, max is 30 + +@property (nonatomic, retain) NSLocale *locale; // default is [NSLocale currentLocale]. setting nil returns to default +@property (nonatomic, copy) NSCalendar *calendar; // default is [NSCalendar currentCalendar]. setting nil returns to default +@property (nonatomic, retain) NSTimeZone *timeZone; // default is nil. use current time zone or time zone from calendar + +@property (nonatomic, assign) NSTimeInterval countDownDuration; // for UIDatePickerModeCountDownTimer, ignored otherwise. default is 0.0. limit is 23:59 (86,399 seconds). value being set is div 60 (drops remaining seconds). + +@property (nonatomic, copy) ActionDateDoneBlock onActionSheetDone; +@property (nonatomic, copy) ActionDateCancelBlock onActionSheetCancel; + ++ (instancetype)showPickerWithTitle:(NSString *)title datePickerMode:(UIDatePickerMode)datePickerMode selectedDate:(NSDate *)selectedDate target:(id)target action:(SEL)action origin:(id)origin; + ++ (instancetype)showPickerWithTitle:(NSString *)title datePickerMode:(UIDatePickerMode)datePickerMode selectedDate:(NSDate *)selectedDate target:(id)target action:(SEL)action origin:(id)origin cancelAction:(SEL)cancelAction; + ++ (instancetype)showPickerWithTitle:(NSString *)title + datePickerMode:(UIDatePickerMode)datePickerMode selectedDate:(NSDate *)selectedDate + minimumDate:(NSDate *)minimumDate maximumDate:(NSDate *)maximumDate + target:(id)target action:(SEL)action origin:(id)origin; + ++ (instancetype)showPickerWithTitle:(NSString *)title + datePickerMode:(UIDatePickerMode)datePickerMode + selectedDate:(NSDate *)selectedDate + doneBlock:(ActionDateDoneBlock)doneBlock + cancelBlock:(ActionDateCancelBlock)cancelBlock + origin:(UIView*)view; + ++ (instancetype)showPickerWithTitle:(NSString *)title + datePickerMode:(UIDatePickerMode)datePickerMode + selectedDate:(NSDate *)selectedDate + minimumDate:(NSDate *)minimumDate + maximumDate:(NSDate *)maximumDate + doneBlock:(ActionDateDoneBlock)doneBlock + cancelBlock:(ActionDateCancelBlock)cancelBlock + origin:(UIView*)view; + + +- (id)initWithTitle:(NSString *)title datePickerMode:(UIDatePickerMode)datePickerMode selectedDate:(NSDate *)selectedDate target:(id)target action:(SEL)action origin:(id)origin; + +- (instancetype)initWithTitle:(NSString *)title datePickerMode:(UIDatePickerMode)datePickerMode selectedDate:(NSDate *)selectedDate minimumDate:(NSDate *)minimumDate maximumDate:(NSDate *)maximumDate target:(id)target action:(SEL)action origin:(id)origin; + +- (instancetype)initWithTitle:(NSString *)title datePickerMode:(UIDatePickerMode)datePickerMode selectedDate:(NSDate *)selectedDate target:(id)target action:(SEL)action origin:(id)origin cancelAction:(SEL)cancelAction; + +- (instancetype)initWithTitle:(NSString *)title datePickerMode:(UIDatePickerMode)datePickerMode selectedDate:(NSDate *)selectedDate minimumDate:(NSDate *)minimumDate maximumDate:(NSDate *)maximumDate target:(id)target action:(SEL)action cancelAction:(SEL)cancelAction origin:(id)origin; + + +- (instancetype)initWithTitle:(NSString *)title + datePickerMode:(UIDatePickerMode)datePickerMode + selectedDate:(NSDate *)selectedDate + doneBlock:(ActionDateDoneBlock)doneBlock + cancelBlock:(ActionDateCancelBlock)cancelBlock + origin:(UIView*)view; + +- (void)eventForDatePicker:(id)sender; + +@end diff --git a/Pods/ActionSheetPicker-3.0/Pickers/ActionSheetDatePicker.m b/Pods/ActionSheetPicker-3.0/Pickers/ActionSheetDatePicker.m new file mode 100755 index 00000000..fd5df63e --- /dev/null +++ b/Pods/ActionSheetPicker-3.0/Pickers/ActionSheetDatePicker.m @@ -0,0 +1,272 @@ +// +//Copyright (c) 2011, Tim Cinel +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions are met: +//* Redistributions of source code must retain the above copyright +//notice, this list of conditions and the following disclaimer. +//* Redistributions in binary form must reproduce the above copyright +//notice, this list of conditions and the following disclaimer in the +//documentation and/or other materials provided with the distribution. +//* Neither the name of the nor the +//names of its contributors may be used to endorse or promote products +//derived from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +//ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +//WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +//DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +//DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +//(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +//ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +//(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +//SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + + +#import "ActionSheetDatePicker.h" +#import + +@interface ActionSheetDatePicker() +@property (nonatomic, assign) UIDatePickerMode datePickerMode; +@property (nonatomic, strong) NSDate *selectedDate; +@end + +@implementation ActionSheetDatePicker + ++ (instancetype)showPickerWithTitle:(NSString *)title + datePickerMode:(UIDatePickerMode)datePickerMode selectedDate:(NSDate *)selectedDate + target:(id)target action:(SEL)action origin:(id)origin { + ActionSheetDatePicker *picker = [[ActionSheetDatePicker alloc] initWithTitle:title datePickerMode:datePickerMode selectedDate:selectedDate target:target action:action origin:origin]; + [picker showActionSheetPicker]; + return picker; +} + ++ (instancetype)showPickerWithTitle:(NSString *)title + datePickerMode:(UIDatePickerMode)datePickerMode selectedDate:(NSDate *)selectedDate + target:(id)target action:(SEL)action origin:(id)origin cancelAction:(SEL)cancelAction { + ActionSheetDatePicker *picker = [[ActionSheetDatePicker alloc] initWithTitle:title datePickerMode:datePickerMode selectedDate:selectedDate target:target action:action origin:origin cancelAction:cancelAction]; + [picker showActionSheetPicker]; + return picker; +} + ++ (instancetype)showPickerWithTitle:(NSString *)title + datePickerMode:(UIDatePickerMode)datePickerMode selectedDate:(NSDate *)selectedDate + minimumDate:(NSDate *)minimumDate maximumDate:(NSDate *)maximumDate + target:(id)target action:(SEL)action origin:(id)origin { + ActionSheetDatePicker *picker = [[ActionSheetDatePicker alloc] initWithTitle:title datePickerMode:datePickerMode selectedDate:selectedDate target:target action:action origin:origin]; + [picker setMinimumDate:minimumDate]; + [picker setMaximumDate:maximumDate]; + [picker showActionSheetPicker]; + return picker; +} + ++ (instancetype)showPickerWithTitle:(NSString *)title + datePickerMode:(UIDatePickerMode)datePickerMode + selectedDate:(NSDate *)selectedDate + doneBlock:(ActionDateDoneBlock)doneBlock + cancelBlock:(ActionDateCancelBlock)cancelBlock + origin:(UIView*)view +{ + ActionSheetDatePicker* picker = [[ActionSheetDatePicker alloc] initWithTitle:title + datePickerMode:datePickerMode + selectedDate:selectedDate + doneBlock:doneBlock + cancelBlock:cancelBlock + origin:view]; + [picker showActionSheetPicker]; + return picker; +} + ++ (instancetype)showPickerWithTitle:(NSString *)title + datePickerMode:(UIDatePickerMode)datePickerMode + selectedDate:(NSDate *)selectedDate + minimumDate:(NSDate *)minimumDate + maximumDate:(NSDate *)maximumDate + doneBlock:(ActionDateDoneBlock)doneBlock + cancelBlock:(ActionDateCancelBlock)cancelBlock + origin:(UIView*)view +{ + ActionSheetDatePicker* picker = [[ActionSheetDatePicker alloc] initWithTitle:title + datePickerMode:datePickerMode + selectedDate:selectedDate + doneBlock:doneBlock + cancelBlock:cancelBlock + origin:view]; + [picker setMinimumDate:minimumDate]; + [picker setMaximumDate:maximumDate]; + [picker showActionSheetPicker]; + return picker; +} + +- (id)initWithTitle:(NSString *)title datePickerMode:(UIDatePickerMode)datePickerMode selectedDate:(NSDate *)selectedDate target:(id)target action:(SEL)action origin:(id)origin +{ + self = [self initWithTitle:title datePickerMode:datePickerMode selectedDate:selectedDate target:target action:action origin:origin cancelAction:nil]; + return self; +} + +- (instancetype)initWithTitle:(NSString *)title datePickerMode:(UIDatePickerMode)datePickerMode selectedDate:(NSDate *)selectedDate minimumDate:(NSDate *)minimumDate maximumDate:(NSDate *)maximumDate target:(id)target action:(SEL)action origin:(id)origin +{ + self = [self initWithTitle:title datePickerMode:datePickerMode selectedDate:selectedDate target:target action:action origin:origin cancelAction:nil]; + self.minimumDate = minimumDate; + self.maximumDate = maximumDate; + return self; +} + +- (instancetype)initWithTitle:(NSString *)title datePickerMode:(UIDatePickerMode)datePickerMode selectedDate:(NSDate *)selectedDate target:(id)target action:(SEL)action origin:(id)origin cancelAction:(SEL)cancelAction +{ + self = [super initWithTarget:target successAction:action cancelAction:cancelAction origin:origin]; + if (self) { + self.title = title; + self.datePickerMode = datePickerMode; + self.selectedDate = selectedDate; + } + return self; +} + +- (instancetype)initWithTitle:(NSString *)title datePickerMode:(UIDatePickerMode)datePickerMode selectedDate:(NSDate *)selectedDate minimumDate:(NSDate *)minimumDate maximumDate:(NSDate *)maximumDate target:(id)target action:(SEL)action cancelAction:(SEL)cancelAction origin:(id)origin +{ + self = [super initWithTarget:target successAction:action cancelAction:cancelAction origin:origin]; + if (self) { + self.title = title; + self.datePickerMode = datePickerMode; + self.selectedDate = selectedDate; + self.minimumDate = minimumDate; + self.maximumDate = maximumDate; + } + return self; +} + +- (instancetype)initWithTitle:(NSString *)title + datePickerMode:(UIDatePickerMode)datePickerMode + selectedDate:(NSDate *)selectedDate + doneBlock:(ActionDateDoneBlock)doneBlock + cancelBlock:(ActionDateCancelBlock)cancelBlock + origin:(UIView*)origin +{ + self = [self initWithTitle:title datePickerMode:datePickerMode selectedDate:selectedDate target:nil action:nil origin:origin]; + if (self) { + self.onActionSheetDone = doneBlock; + self.onActionSheetCancel = cancelBlock; + } + return self; +} + +- (UIView *)configuredPickerView { + CGRect datePickerFrame = CGRectMake(0, 40, self.viewSize.width, 216); + UIDatePicker *datePicker = [[UIDatePicker alloc] initWithFrame:datePickerFrame]; + datePicker.datePickerMode = self.datePickerMode; + datePicker.maximumDate = self.maximumDate; + datePicker.minimumDate = self.minimumDate; + datePicker.minuteInterval = self.minuteInterval; + datePicker.calendar = self.calendar; + datePicker.timeZone = self.timeZone; + datePicker.locale = self.locale; + + // if datepicker is set with a date in countDownMode then + // 1h is added to the initial countdown + if (self.datePickerMode == UIDatePickerModeCountDownTimer) { + datePicker.countDownDuration = self.countDownDuration; + // Due to a bug in UIDatePicker, countDownDuration needs to be set asynchronously + // more info: http://stackoverflow.com/a/20204317/1161723 + dispatch_async(dispatch_get_main_queue(), ^{ + datePicker.countDownDuration = self.countDownDuration; + }); + } else { + [datePicker setDate:self.selectedDate animated:NO]; + } + + [datePicker addTarget:self action:@selector(eventForDatePicker:) forControlEvents:UIControlEventValueChanged]; + + //need to keep a reference to the picker so we can clear the DataSource / Delegate when dismissing (not used in this picker, but just in case somebody uses this as a template for another picker) + self.pickerView = datePicker; + + return datePicker; +} + +- (void)notifyTarget:(id)target didSucceedWithAction:(SEL)action origin:(id)origin +{ + if (self.onActionSheetDone) + { + if (self.datePickerMode == UIDatePickerModeCountDownTimer) + self.onActionSheetDone(self, @(((UIDatePicker *)self.pickerView).countDownDuration), origin); + else + self.onActionSheetDone(self, self.selectedDate, origin); + + return; + } + else if ([target respondsToSelector:action]) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + if (self.datePickerMode == UIDatePickerModeCountDownTimer) { + [target performSelector:action withObject:@(((UIDatePicker *)self.pickerView).countDownDuration) withObject:origin]; + + } else { + [target performSelector:action withObject:self.selectedDate withObject:origin]; + } +#pragma clang diagnostic pop + else + NSAssert(NO, @"Invalid target/action ( %s / %s ) combination used for ActionSheetPicker", object_getClassName(target), sel_getName(action)); +} + +- (void)notifyTarget:(id)target didCancelWithAction:(SEL)cancelAction origin:(id)origin +{ + if (self.onActionSheetCancel) + { + self.onActionSheetCancel(self); + return; + } + else + if ( target && cancelAction && [target respondsToSelector:cancelAction] ) + { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + [target performSelector:cancelAction withObject:origin]; +#pragma clang diagnostic pop + } +} + +- (void)eventForDatePicker:(id)sender +{ + if (!sender || ![sender isKindOfClass:[UIDatePicker class]]) + return; + UIDatePicker *datePicker = (UIDatePicker *)sender; + self.selectedDate = datePicker.date; + self.countDownDuration = datePicker.countDownDuration; +} + +- (void)customButtonPressed:(id)sender { + UIBarButtonItem *button = (UIBarButtonItem*)sender; + NSInteger index = button.tag; + NSAssert((index >= 0 && index < self.customButtons.count), @"Bad custom button tag: %zd, custom button count: %zd", index, self.customButtons.count); + NSDictionary *buttonDetails = (self.customButtons)[(NSUInteger) index]; + NSAssert(buttonDetails != NULL, @"Custom button dictionary is invalid"); + + ActionType actionType = (ActionType) [buttonDetails[kActionType] integerValue]; + switch (actionType) { + case ActionTypeValue: { + NSAssert([self.pickerView respondsToSelector:@selector(setDate:animated:)], @"Bad pickerView for ActionSheetDatePicker, doesn't respond to setDate:animated:"); + NSDate *itemValue = buttonDetails[kButtonValue]; + UIDatePicker *picker = (UIDatePicker *)self.pickerView; + if (self.datePickerMode != UIDatePickerModeCountDownTimer) + { + [picker setDate:itemValue animated:YES]; + [self eventForDatePicker:picker]; + } + break; + } + + case ActionTypeBlock: + case ActionTypeSelector: + [super customButtonPressed:sender]; + break; + + default: + NSAssert(false, @"Unknown action type"); + break; + } +} + +@end diff --git a/Pods/ActionSheetPicker-3.0/Pickers/ActionSheetDistancePicker.h b/Pods/ActionSheetPicker-3.0/Pickers/ActionSheetDistancePicker.h new file mode 100644 index 00000000..f8f74e4e --- /dev/null +++ b/Pods/ActionSheetPicker-3.0/Pickers/ActionSheetDistancePicker.h @@ -0,0 +1,39 @@ +// +//Copyright (c) 2011, Tim Cinel +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions are met: +//* Redistributions of source code must retain the above copyright +//notice, this list of conditions and the following disclaimer. +//* Redistributions in binary form must reproduce the above copyright +//notice, this list of conditions and the following disclaimer in the +//documentation and/or other materials provided with the distribution. +//* Neither the name of the nor the +//names of its contributors may be used to endorse or promote products +//derived from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +//ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +//WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +//DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +//DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +//(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//åLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +//ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +//(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +//SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#import "AbstractActionSheetPicker.h" +#import "DistancePickerView.h" +@interface ActionSheetDistancePicker : AbstractActionSheetPicker + ++ (instancetype)showPickerWithTitle:(NSString *)title bigUnitString:(NSString *)bigUnitString bigUnitMax:(NSInteger)bigUnitMax selectedBigUnit:(NSInteger)selectedBigUnit smallUnitString:(NSString *)smallUnitString smallUnitMax:(NSInteger)smallUnitMax selectedSmallUnit:(NSInteger)selectedSmallUnit target:(id)target action:(SEL)action origin:(id)origin; + +- (instancetype)initWithTitle:(NSString *)title bigUnitString:(NSString *)bigUnitString bigUnitMax:(NSInteger)bigUnitMax selectedBigUnit:(NSInteger)selectedBigUnit smallUnitString:(NSString *)smallUnitString smallUnitMax:(NSInteger)smallUnitMax selectedSmallUnit:(NSInteger)selectedSmallUnit target:(id)target action:(SEL)action origin:(id)origin; + ++ (instancetype)showPickerWithTitle:(NSString *)title bigUnitString:(NSString *)bigUnitString bigUnitMax:(NSInteger)bigUnitMax selectedBigUnit:(NSInteger)selectedBigUnit smallUnitString:(NSString *)smallUnitString smallUnitMax:(NSInteger)smallUnitMax selectedSmallUnit:(NSInteger)selectedSmallUnit target:(id)target action:(SEL)action origin:(id)origin cancelAction:(SEL)cancelAction; + +- (instancetype)initWithTitle:(NSString *)title bigUnitString:(NSString *)bigUnitString bigUnitMax:(NSInteger)bigUnitMax selectedBigUnit:(NSInteger)selectedBigUnit smallUnitString:(NSString *)smallUnitString smallUnitMax:(NSInteger)smallUnitMax selectedSmallUnit:(NSInteger)selectedSmallUnit target:(id)target action:(SEL)action origin:(id)origin cancelAction:(SEL)cancelAction; +@end diff --git a/Pods/ActionSheetPicker-3.0/Pickers/ActionSheetDistancePicker.m b/Pods/ActionSheetPicker-3.0/Pickers/ActionSheetDistancePicker.m new file mode 100644 index 00000000..c9abcb94 --- /dev/null +++ b/Pods/ActionSheetPicker-3.0/Pickers/ActionSheetDistancePicker.m @@ -0,0 +1,207 @@ +// +//Copyright (c) 2011, Tim Cinel +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions are met: +//* Redistributions of source code must retain the above copyright +//notice, this list of conditions and the following disclaimer. +//* Redistributions in binary form must reproduce the above copyright +//notice, this list of conditions and the following disclaimer in the +//documentation and/or other materials provided with the distribution. +//* Neither the name of the nor the +//names of its contributors may be used to endorse or promote products +//derived from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +//ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +//WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +//DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +//DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +//(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +//ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +//(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +//SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#import "ActionSheetDistancePicker.h" +#import + +@interface ActionSheetDistancePicker() +@property (nonatomic, strong) NSString *bigUnitString; +@property (nonatomic, assign) NSInteger selectedBigUnit; +@property (nonatomic, assign) NSInteger bigUnitMax; +@property (nonatomic, assign) NSInteger bigUnitDigits; +@property (nonatomic, strong) NSString *smallUnitString; +@property (nonatomic, assign) NSInteger selectedSmallUnit; +@property (nonatomic, assign) NSInteger smallUnitMax; +@property (nonatomic, assign) NSInteger smallUnitDigits; +@end + +@implementation ActionSheetDistancePicker + ++ (instancetype)showPickerWithTitle:(NSString *)title bigUnitString:(NSString *)bigUnitString bigUnitMax:(NSInteger)bigUnitMax selectedBigUnit:(NSInteger)selectedBigUnit smallUnitString:(NSString *)smallUnitString smallUnitMax:(NSInteger)smallUnitMax selectedSmallUnit:(NSInteger)selectedSmallUnit target:(id)target action:(SEL)action origin:(id)origin { + ActionSheetDistancePicker *picker = [[ActionSheetDistancePicker alloc] initWithTitle:title bigUnitString:bigUnitString bigUnitMax:bigUnitMax selectedBigUnit:selectedBigUnit smallUnitString:smallUnitString smallUnitMax:smallUnitMax selectedSmallUnit:selectedSmallUnit target:target action:action origin:origin]; + [picker showActionSheetPicker]; + return picker; +} + +- (instancetype)initWithTitle:(NSString *)title bigUnitString:(NSString *)bigUnitString bigUnitMax:(NSInteger)bigUnitMax selectedBigUnit:(NSInteger)selectedBigUnit smallUnitString:(NSString *)smallUnitString smallUnitMax:(NSInteger)smallUnitMax selectedSmallUnit:(NSInteger)selectedSmallUnit target:(id)target action:(SEL)action origin:(id)origin { + self = [super initWithTarget:target successAction:action cancelAction:nil origin:origin]; + if (self) { + self.title = title; + self.bigUnitString = bigUnitString; + self.bigUnitMax = bigUnitMax; + self.selectedBigUnit = selectedBigUnit; + self.smallUnitString = smallUnitString; + self.smallUnitMax = smallUnitMax; + self.selectedSmallUnit = selectedSmallUnit; + self.bigUnitDigits = [[NSString stringWithFormat:@"%li", (long)self.bigUnitMax] length]; + self.smallUnitDigits = [[NSString stringWithFormat:@"%li", (long)self.smallUnitMax] length]; + } + return self; +} + ++ (instancetype)showPickerWithTitle:(NSString *)title bigUnitString:(NSString *)bigUnitString bigUnitMax:(NSInteger)bigUnitMax selectedBigUnit:(NSInteger)selectedBigUnit smallUnitString:(NSString *)smallUnitString smallUnitMax:(NSInteger)smallUnitMax selectedSmallUnit:(NSInteger)selectedSmallUnit target:(id)target action:(SEL)action origin:(id)origin cancelAction:(SEL)cancelAction +{ + ActionSheetDistancePicker *picker = [[ActionSheetDistancePicker alloc] initWithTitle:title bigUnitString:bigUnitString bigUnitMax:bigUnitMax selectedBigUnit:selectedBigUnit smallUnitString:smallUnitString smallUnitMax:smallUnitMax selectedSmallUnit:selectedSmallUnit target:target action:action origin:origin cancelAction:cancelAction]; + [picker showActionSheetPicker]; + return picker; +} + +- (instancetype)initWithTitle:(NSString *)title bigUnitString:(NSString *)bigUnitString bigUnitMax:(NSInteger)bigUnitMax selectedBigUnit:(NSInteger)selectedBigUnit smallUnitString:(NSString *)smallUnitString smallUnitMax:(NSInteger)smallUnitMax selectedSmallUnit:(NSInteger)selectedSmallUnit target:(id)target action:(SEL)action origin:(id)origin cancelAction:(SEL)cancelAction +{ + self = [super initWithTarget:target successAction:action cancelAction:cancelAction origin:origin]; + if (self) { + self.title = title; + self.bigUnitString = bigUnitString; + self.bigUnitMax = bigUnitMax; + self.selectedBigUnit = selectedBigUnit; + self.smallUnitString = smallUnitString; + self.smallUnitMax = smallUnitMax; + self.selectedSmallUnit = selectedSmallUnit; + self.bigUnitDigits = [[NSString stringWithFormat:@"%li", (long)self.bigUnitMax] length]; + self.smallUnitDigits = [[NSString stringWithFormat:@"%li", (long)self.smallUnitMax] length]; + } + return self; +} + + +- (UIView *)configuredPickerView { + CGRect distancePickerFrame = CGRectMake(0, 40, self.viewSize.width, 216); + DistancePickerView *picker = [[DistancePickerView alloc] initWithFrame:distancePickerFrame]; + picker.delegate = self; + picker.dataSource = self; + picker.showsSelectionIndicator = YES; +// [picker addLabel:self.bigUnitString forComponent:(NSUInteger) (self.bigUnitDigits - 1) forLongestString:nil]; +// [picker addLabel:self.smallUnitString forComponent:(NSUInteger) (self.bigUnitDigits + self.smallUnitDigits - 1) +// forLongestString:nil]; + + NSInteger unitSubtract = 0; + NSInteger currentDigit = 0; + + for (int i = 0; i < self.bigUnitDigits; ++i) { + NSInteger factor = (int)pow((double)10, (double)(self.bigUnitDigits - (i+1))); + currentDigit = (( self.selectedBigUnit - unitSubtract ) / factor ) ; + [picker selectRow:currentDigit inComponent:i animated:NO]; + unitSubtract += currentDigit * factor; + } + + unitSubtract = 0; + + for (NSInteger i = self.bigUnitDigits + 1; i < self.bigUnitDigits + self.smallUnitDigits + 1; ++i) { + NSInteger factor = (int)pow((double)10, (double)(self.bigUnitDigits + self.smallUnitDigits + 1 - (i+1))); + currentDigit = (( self.selectedSmallUnit - unitSubtract ) / factor ) ; + [picker selectRow:currentDigit inComponent:i animated:NO]; + unitSubtract += currentDigit * factor; + } + + //need to keep a reference to the picker so we can clear the DataSource / Delegate when dismissing + self.pickerView = picker; + + return picker; +} + +- (void)notifyTarget:(id)target didSucceedWithAction:(SEL)action origin:(id)origin { + NSInteger bigUnits = 0; + NSInteger smallUnits = 0; + DistancePickerView *picker = (DistancePickerView *)self.pickerView; + for (int i = 0; i < self.bigUnitDigits; ++i) + bigUnits += [picker selectedRowInComponent:i] * (int)pow((double)10, (double)(self.bigUnitDigits - (i + 1))); + + for (NSInteger i = self.bigUnitDigits + 1; i < self.bigUnitDigits + self.smallUnitDigits + 1; ++i) + smallUnits += [picker selectedRowInComponent:i] * (int)pow((double)10, (double)((picker.numberOfComponents - i - 2))); + + //sending three objects, so can't use performSelector: + if ([target respondsToSelector:action]) + { + void (*response)(id, SEL, id, id,id) = (void (*)(id, SEL, id, id,id)) objc_msgSend; + response(target, action, @(bigUnits), @(smallUnits), origin); + } + else + NSAssert(NO, @"Invalid target/action ( %s / %s ) combination used for ActionSheetPicker", object_getClassName(target), sel_getName(action)); +} + +#pragma mark - +#pragma mark UIPickerViewDataSource + +- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView { + return self.bigUnitDigits + self.smallUnitDigits + 2; +} + +- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component { + + //for labels + if (component == self.bigUnitDigits || component == self.bigUnitDigits + self.smallUnitDigits + 1) + return 1; + + if (component + 1 <= self.bigUnitDigits) { + if (component == 0) + return self.bigUnitMax / (int)pow((double)10, (double)(self.bigUnitDigits - 1)) + 1; + return 10; + } + if (component == self.bigUnitDigits + 1) + return self.smallUnitMax / (int)pow((double)10, (double)(self.smallUnitDigits - 1)) + 1; + return 10; +} + +- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view{ + + CGFloat totalWidth = pickerView.frame.size.width - 30; + CGFloat otherSize = (totalWidth )/(self.bigUnitDigits + self.smallUnitDigits + 2); + + UILabel * label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, otherSize, 30)]; + + label.textAlignment = NSTextAlignmentCenter; + + label.font = [UIFont boldSystemFontOfSize:20]; + + if ( component == self.bigUnitDigits ) + { + label.text = self.bigUnitString; + return label; + } + else if ( component == self.bigUnitDigits + self.smallUnitDigits + 1 ) + { + label.text = self.smallUnitString; + return label; + } + + label.font = [UIFont systemFontOfSize:20]; + label.text = [NSString stringWithFormat:@"%li", (long)row]; + return label; +} + +- (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component { + CGFloat totalWidth = pickerView.frame.size.width - 30; + CGFloat otherSize = (totalWidth )/(self.bigUnitDigits + self.smallUnitDigits + 2); + return otherSize; +} + + +- (void)customButtonPressed:(id)sender { + NSLog(@"Not implemented. If you get around to it, please contribute back to the project :)"); +} + +@end diff --git a/Pods/ActionSheetPicker-3.0/Pickers/ActionSheetLocalePicker.h b/Pods/ActionSheetPicker-3.0/Pickers/ActionSheetLocalePicker.h new file mode 100644 index 00000000..0ba50a6b --- /dev/null +++ b/Pods/ActionSheetPicker-3.0/Pickers/ActionSheetLocalePicker.h @@ -0,0 +1,63 @@ +// +//Copyright (c) 2011, Tim Cinel +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions are met: +//* Redistributions of source code must retain the above copyright +//notice, this list of conditions and the following disclaimer. +//* Redistributions in binary form must reproduce the above copyright +//notice, this list of conditions and the following disclaimer in the +//documentation and/or other materials provided with the distribution. +//* Neither the name of the nor the +//names of its contributors may be used to endorse or promote products +//derived from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +//ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +//WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +//DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +//DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +//(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//åLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +//ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +//(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +//SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#import "AbstractActionSheetPicker.h" + +@class ActionSheetLocalePicker; +typedef void(^ActionLocaleDoneBlock)(ActionSheetLocalePicker *picker, NSTimeZone * selectedValue); +typedef void(^ActionLocaleCancelBlock)(ActionSheetLocalePicker *picker); + +static const float firstColumnWidth = 100.0f; +static const float secondColumnWidth = 160.0f; + +@interface ActionSheetLocalePicker : AbstractActionSheetPicker + +/** + * Create and display an action sheet picker. + * + * @param title Title label for picker + * @param index is used to establish the initially selected row; + * @param target must not be empty. It should respond to "onSuccess" actions. + * @param successAction successAction + * @param cancelActionOrNil cancelAction + * @param origin must not be empty. It can be either an originating container view or a UIBarButtonItem to use with a popover arrow. + * + * @return return instance of picker + */ ++ (instancetype)showPickerWithTitle:(NSString *)title initialSelection:(NSTimeZone *)index target:(id)target successAction:(SEL)successAction cancelAction:(SEL)cancelActionOrNil origin:(id)origin; + +// Create an action sheet picker, but don't display until a subsequent call to "showActionPicker". Receiver must release the picker when ready. */ +- (instancetype)initWithTitle:(NSString *)title initialSelection:(NSTimeZone *)index target:(id)target successAction:(SEL)successAction cancelAction:(SEL)cancelActionOrNil origin:(id)origin; + ++ (instancetype)showPickerWithTitle:(NSString *)title initialSelection:(NSTimeZone *)index doneBlock:(ActionLocaleDoneBlock)doneBlock cancelBlock:(ActionLocaleCancelBlock)cancelBlock origin:(id)origin; + +- (instancetype)initWithTitle:(NSString *)title initialSelection:(NSTimeZone *)timeZone doneBlock:(ActionLocaleDoneBlock)doneBlock cancelBlock:(ActionLocaleCancelBlock)cancelBlockOrNil origin:(id)origin; + +@property (nonatomic, copy) ActionLocaleDoneBlock onActionSheetDone; +@property (nonatomic, copy) ActionLocaleCancelBlock onActionSheetCancel; + +@end \ No newline at end of file diff --git a/Pods/ActionSheetPicker-3.0/Pickers/ActionSheetLocalePicker.m b/Pods/ActionSheetPicker-3.0/Pickers/ActionSheetLocalePicker.m new file mode 100644 index 00000000..05308bea --- /dev/null +++ b/Pods/ActionSheetPicker-3.0/Pickers/ActionSheetLocalePicker.m @@ -0,0 +1,408 @@ +// +//Copyright (c) 2011, Tim Cinel +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions are met: +//* Redistributions of source code must retain the above copyright +//notice, this list of conditions and the following disclaimer. +//* Redistributions in binary form must reproduce the above copyright +//notice, this list of conditions and the following disclaimer in the +//documentation and/or other materials provided with the distribution. +//* Neither the name of the nor the +//names of its contributors may be used to endorse or promote products +//derived from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +//ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +//WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +//DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +//DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +//(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//åLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +//ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +//(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +//SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#import "ActionSheetLocalePicker.h" + +@interface ActionSheetLocalePicker() +//@property (nonatomic,strong) NSArray *data; +//@property (nonatomic,assign) NSInteger selectedIndex; + +@property(nonatomic, strong) NSTimeZone *initialTimeZone; + +@property (nonatomic, strong) NSString *selectedContinent; +@property (nonatomic, strong) NSString *selectedCity; + +@property(nonatomic, strong) NSMutableDictionary *continentsAndCityDictionary; +@property(nonatomic, strong) NSMutableArray *continents; +@end + +@implementation ActionSheetLocalePicker + ++ (instancetype)showPickerWithTitle:(NSString *)title initialSelection:(NSTimeZone *)index doneBlock:(ActionLocaleDoneBlock)doneBlock cancelBlock:(ActionLocaleCancelBlock)cancelBlockOrNil origin:(id)origin +{ + ActionSheetLocalePicker * picker = [[ActionSheetLocalePicker alloc] initWithTitle:title initialSelection:index doneBlock:doneBlock cancelBlock:cancelBlockOrNil origin:origin]; + [picker showActionSheetPicker]; + return picker; +} + +- (instancetype)initWithTitle:(NSString *)title initialSelection:(NSTimeZone *)timeZone doneBlock:(ActionLocaleDoneBlock)doneBlock cancelBlock:(ActionLocaleCancelBlock)cancelBlockOrNil origin:(id)origin +{ + self = [self initWithTitle:title initialSelection:timeZone target:nil successAction:nil cancelAction:nil origin:origin]; + if (self) { + self.onActionSheetDone = doneBlock; + self.onActionSheetCancel = cancelBlockOrNil; + } + return self; +} + ++ (instancetype)showPickerWithTitle:(NSString *)title initialSelection:(NSTimeZone *)index target:(id)target successAction:(SEL)successAction cancelAction:(SEL)cancelActionOrNil origin:(id)origin +{ + ActionSheetLocalePicker *picker = [[ActionSheetLocalePicker alloc] initWithTitle:title initialSelection:index target:target successAction:successAction cancelAction:cancelActionOrNil origin:origin]; + [picker showActionSheetPicker]; + return picker; +} + +- (instancetype)initWithTitle:(NSString *)title initialSelection:(NSTimeZone *)index target:(id)target successAction:(SEL)successAction cancelAction:(SEL)cancelActionOrNil origin:(id)origin +{ + self = [self initWithTarget:target successAction:successAction cancelAction:cancelActionOrNil origin:origin]; + if (self) { + self.initialTimeZone = index; + self.title = title; + } + return self; +} + + +- (UIView *)configuredPickerView { + [self fillContinentsAndCities]; + [self setSelectedRows]; + + CGRect pickerFrame = CGRectMake(0, 40, self.viewSize.width, 216); + UIPickerView *pickerView = [[UIPickerView alloc] initWithFrame:pickerFrame]; + pickerView.delegate = self; + pickerView.dataSource = self; + + pickerView.showsSelectionIndicator = YES; + + [self selectCurrentLocale:pickerView]; + + //need to keep a reference to the picker so we can clear the DataSource / Delegate when dismissing + self.pickerView = pickerView; + + return pickerView; +} + +- (void)selectCurrentLocale:(UIPickerView *)pickerView +{ + NSUInteger rowContinent = [_continents indexOfObject:self.selectedContinent]; + NSUInteger rowCity = [[self getCitiesByContinent:self.selectedContinent] indexOfObject:self.selectedCity]; + + if ((rowContinent != NSNotFound) && (rowCity != NSNotFound)) // to fix some crashes from prev versions http://crashes.to/s/ecb0f15ce49 + { + [pickerView selectRow:rowContinent inComponent:0 animated:YES]; + [pickerView reloadComponent:1]; + [pickerView selectRow:rowCity inComponent:1 animated:YES]; + } + else + { + [pickerView selectRow:0 inComponent:0 animated:YES]; + [pickerView selectRow:0 inComponent:1 animated:YES]; + } +} + +-(void)fillContinentsAndCities +{ + NSArray *timeZones = [NSTimeZone knownTimeZoneNames]; + + NSMutableDictionary *continentsDict = [[NSMutableDictionary alloc] init]; + + _continents= [[NSMutableArray alloc] init]; + + [timeZones enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) + { + if ( [obj isKindOfClass:[NSString class]] ) + { + NSString *string = (NSString *) obj; + NSArray *array = [string componentsSeparatedByString:@"/"]; + + if ( [array count] == 2) + { + if ( continentsDict[array[0]] ) //if continent exists + { + NSMutableArray *citys = continentsDict[array[0]]; + [citys addObject:array[1]]; + } + else //it's new continent + { + NSMutableArray *mutableArray = [@[array[1]] mutableCopy]; + continentsDict[array[0]] = mutableArray; + [_continents addObject:array[0]]; + } + } + else if (array.count == 3) + { + NSString *string0 = array[0]; + NSString *string1 = array[1]; + NSString *string2 = array[2]; + NSString *string3 = [string1 stringByAppendingFormat:@"/%@", string2]; + + if ( continentsDict[string0] ) //if continent exists + { + NSMutableArray *citys = continentsDict[string0]; + [citys addObject:string3]; + } + else //it's new continent + { + NSMutableArray *mutableArray = [@[string3] mutableCopy]; + continentsDict[string0] = mutableArray; + [_continents addObject:string0]; + } + } + } + + }]; + + self.continentsAndCityDictionary = continentsDict; +}; + +- (void)setSelectedRows +{ + NSString *string; + if (self.initialTimeZone) + string = self.initialTimeZone.name; + else + string = [[NSTimeZone localTimeZone] name]; + + NSArray *array = [string componentsSeparatedByString:@"/"]; + if (array.count == 1) + { + // Unknown time zone - appeared only in travis builds. + self.selectedContinent = _continents[0]; + self.selectedCity = [self getCitiesByContinent:self.selectedContinent][0]; + } + else if (array.count == 2) + { + self.selectedContinent = array[0]; + self.selectedCity = array[1]; + } + else + { + assert(NO); + } + +} + + +- (void)notifyTarget:(id)target didSucceedWithAction:(SEL)successAction origin:(id)origin { + + NSString *timeZoneId = [NSString stringWithFormat:@"%@/%@", self.selectedContinent, self.selectedCity]; + NSTimeZone *timeZone = [[NSTimeZone alloc] initWithName:timeZoneId]; + + if (self.onActionSheetDone) { + _onActionSheetDone(self, timeZone); + return; + } + else if (target && [target respondsToSelector:successAction]) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + [target performSelector:successAction withObject:timeZone withObject:origin]; +#pragma clang diagnostic pop + return; + } + NSLog(@"Invalid target/action ( %s / %s ) combination used for ActionSheetPicker", object_getClassName(target), sel_getName(successAction)); +} + +- (void)notifyTarget:(id)target didCancelWithAction:(SEL)cancelAction origin:(id)origin { + if (self.onActionSheetCancel) { + _onActionSheetCancel(self); + return; + } + else if (target && cancelAction && [target respondsToSelector:cancelAction]) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + [target performSelector:cancelAction withObject:origin]; +#pragma clang diagnostic pop + } +} + +#pragma mark - UIPickerViewDelegate / DataSource +// +//- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component { +// id obj = [self.data objectAtIndex:(NSUInteger) row]; +// +// // return the object if it is already a NSString, +// // otherwise, return the description, just like the toString() method in Java +// // else, return nil to prevent exception +// +// if ([obj isKindOfClass:[NSString class]]) +// return obj; +// +// if ([obj respondsToSelector:@selector(description)]) +// return [obj performSelector:@selector(description)]; +// +// return nil; +//} +// + + +///////////////////////////////////////////////////////////////////////// +#pragma mark - UIPickerViewDataSource Implementation +///////////////////////////////////////////////////////////////////////// + +- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView +{ + return 2; +} + +- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component +{ + // Returns + switch (component) { + case 0: return [_continents count]; + case 1: return [[self getCitiesByContinent:self.selectedContinent] count]; + default:break; + } + return 0; +} + +///////////////////////////////////////////////////////////////////////// +#pragma mark UIPickerViewDelegate Implementation +///////////////////////////////////////////////////////////////////////// + +// returns width of column and height of row for each component. +- (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component +{ + + switch (component) { + + case 0: return firstColumnWidth; + case 1: return secondColumnWidth; + default:break; + } + + return 0; +} + +- (UIView *)pickerView:(UIPickerView *)pickerView + viewForRow:(NSInteger)row + forComponent:(NSInteger)component + reusingView:(UIView *)view { + + UILabel *pickerLabel = (UILabel *)view; + + if (pickerLabel == nil) { + CGRect frame = CGRectZero; + + + switch (component) { + case 0: frame = CGRectMake(0.0, 0.0, firstColumnWidth, 32); + break; + case 1: + frame = CGRectMake(0.0, 0.0, secondColumnWidth, 32); + break; + default: + assert(NO); + break; + } + + pickerLabel = [[UILabel alloc] initWithFrame:frame]; + [pickerLabel setTextAlignment:NSTextAlignmentCenter]; + if ([pickerLabel respondsToSelector:@selector(setMinimumScaleFactor:)]) + [pickerLabel setMinimumScaleFactor:0.5]; + [pickerLabel setAdjustsFontSizeToFitWidth:YES]; + [pickerLabel setBackgroundColor:[UIColor clearColor]]; + [pickerLabel setFont:[UIFont systemFontOfSize:20]]; + } + + NSString *text; + switch (component) { + case 0: text = (self.continents)[(NSUInteger) row]; + break; + case 1: + { + NSString *cityTitle = [self getCitiesByContinent:self.selectedContinent][(NSUInteger) row]; + NSString *timeZoneId = [NSString stringWithFormat:@"%@/%@", self.selectedContinent, cityTitle]; + NSTimeZone *timeZone = [[NSTimeZone alloc] initWithName:timeZoneId]; + + NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; + [dateFormatter setTimeZone:timeZone]; + [dateFormatter setDateFormat:@"z"]; + text = [cityTitle stringByAppendingString:[NSString stringWithFormat: @" (%@)", [dateFormatter stringFromDate:[NSDate date]]]]; + + break; + } + default:break; + } + + [pickerLabel setText:text]; + + return pickerLabel; + +} + +///////////////////////////////////////////////////////////////////////// + +- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component +{ + switch (component) { + case 0: + { + self.selectedContinent = (self.continents)[(NSUInteger) row]; + [pickerView reloadComponent:1]; + self.selectedCity = [self getCitiesByContinent:self.selectedContinent][(NSUInteger) [pickerView selectedRowInComponent:1]]; + return; + } + + case 1: + self.selectedCity = [self getCitiesByContinent:self.selectedContinent][(NSUInteger) row]; + return; + default:break; + } +} + +-(NSMutableArray *)getCitiesByContinent:(NSString *)continent +{ + NSMutableArray *citiesIncontinent = _continentsAndCityDictionary[continent]; + return citiesIncontinent; +}; + + +- (void)customButtonPressed:(id)sender { + UIBarButtonItem *button = (UIBarButtonItem*)sender; + NSInteger index = button.tag; + NSAssert((index >= 0 && index < self.customButtons.count), @"Bad custom button tag: %ld, custom button count: %lu", (long)index, (unsigned long)self.customButtons.count); + + NSDictionary *buttonDetails = (self.customButtons)[(NSUInteger) index]; + NSAssert(buttonDetails != NULL, @"Custom button dictionary is invalid"); + + ActionType actionType = (ActionType) [buttonDetails[kActionType] intValue]; + switch (actionType) { + case ActionTypeValue: { + id itemValue = buttonDetails[kButtonValue]; + if ( [itemValue isKindOfClass:[NSTimeZone class]] ) + { + NSTimeZone *timeZone = (NSTimeZone *) itemValue; + self.initialTimeZone = timeZone; + [self setSelectedRows]; + [self selectCurrentLocale:(UIPickerView *) self.pickerView]; + } + break; + } + + case ActionTypeBlock: + case ActionTypeSelector: + [super customButtonPressed:sender]; + break; + default: + NSAssert(false, @"Unknown action type"); + break; + } +} + + + +@end \ No newline at end of file diff --git a/Pods/ActionSheetPicker-3.0/Pickers/ActionSheetMultipleStringPicker.h b/Pods/ActionSheetPicker-3.0/Pickers/ActionSheetMultipleStringPicker.h new file mode 100644 index 00000000..5145f285 --- /dev/null +++ b/Pods/ActionSheetPicker-3.0/Pickers/ActionSheetMultipleStringPicker.h @@ -0,0 +1,65 @@ +// +// ActionSheetMultipleStringPicker.h +// CoreActionSheetPicker +// +// Created by Alejandro on 21/07/15. +// Copyright (c) 2015 Petr Korolev. All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions are met: +//* Redistributions of source code must retain the above copyright +//notice, this list of conditions and the following disclaimer. +//* Redistributions in binary form must reproduce the above copyright +//notice, this list of conditions and the following disclaimer in the +//documentation and/or other materials provided with the distribution. +//* Neither the name of the nor the +//names of its contributors may be used to endorse or promote products +//derived from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +//ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +//WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +//DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +//DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +//(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//åLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +//ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +//(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +//SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#import "AbstractActionSheetPicker.h" + +@class ActionSheetMultipleStringPicker; +typedef void(^ActionMultipleStringDoneBlock)(ActionSheetMultipleStringPicker *picker, NSArray *selectedIndexes, id selectedValues); +typedef void(^ActionMultipleStringCancelBlock)(ActionSheetMultipleStringPicker *picker); + +@interface ActionSheetMultipleStringPicker : AbstractActionSheetPicker +/** + * Create and display an action sheet picker. + * + * @param title Title label for picker + * @param data is an array of strings to use for the picker's available selection choices + * @param indexes is used to establish the initially selected row; + * @param target must not be empty. It should respond to "onSuccess" actions. + * @param successAction successAction + * @param cancelActionOrNil cancelAction + * @param origin must not be empty. It can be either an originating container view or a UIBarButtonItem to use with a popover arrow. + * + * @return return instance of picker + */ ++ (instancetype)showPickerWithTitle:(NSString *)title rows:(NSArray *)data initialSelection:(NSArray *)indexes target:(id)target successAction:(SEL)successAction cancelAction:(SEL)cancelActionOrNil origin:(id)origin; + +// Create an action sheet picker, but don't display until a subsequent call to "showActionPicker". Receiver must release the picker when ready. */ +- (instancetype)initWithTitle:(NSString *)title rows:(NSArray *)data initialSelection:(NSArray *)indexes target:(id)target successAction:(SEL)successAction cancelAction:(SEL)cancelActionOrNil origin:(id)origin; + + + ++ (instancetype)showPickerWithTitle:(NSString *)title rows:(NSArray *)strings initialSelection:(NSArray *)indexes doneBlock:(ActionMultipleStringDoneBlock)doneBlock cancelBlock:(ActionMultipleStringCancelBlock)cancelBlock origin:(id)origin; + +- (instancetype)initWithTitle:(NSString *)title rows:(NSArray *)strings initialSelection:(NSArray *)indexes doneBlock:(ActionMultipleStringDoneBlock)doneBlock cancelBlock:(ActionMultipleStringCancelBlock)cancelBlockOrNil origin:(id)origin; + +@property (nonatomic, copy) ActionMultipleStringDoneBlock onActionSheetDone; +@property (nonatomic, copy) ActionMultipleStringCancelBlock onActionSheetCancel; + +@end diff --git a/Pods/ActionSheetPicker-3.0/Pickers/ActionSheetMultipleStringPicker.m b/Pods/ActionSheetPicker-3.0/Pickers/ActionSheetMultipleStringPicker.m new file mode 100644 index 00000000..8eb2dea1 --- /dev/null +++ b/Pods/ActionSheetPicker-3.0/Pickers/ActionSheetMultipleStringPicker.m @@ -0,0 +1,225 @@ +// +// ActionSheetMultipleStringPicker.m +// CoreActionSheetPicker +// +// Created by Alejandro on 21/07/15. +// Copyright (c) 2015 Petr Korolev. All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions are met: +//* Redistributions of source code must retain the above copyright +//notice, this list of conditions and the following disclaimer. +//* Redistributions in binary form must reproduce the above copyright +//notice, this list of conditions and the following disclaimer in the +//documentation and/or other materials provided with the distribution. +//* Neither the name of the nor the +//names of its contributors may be used to endorse or promote products +//derived from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +//ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +//WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +//DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +//DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +//(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//åLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +//ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +//(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +//SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#import "ActionSheetMultipleStringPicker.h" + +@interface ActionSheetMultipleStringPicker() +@property (nonatomic,strong) NSArray *data; //Array of string arrays :) +@property (nonatomic,strong) NSArray *initialSelection; +@end + +@implementation ActionSheetMultipleStringPicker + ++ (instancetype)showPickerWithTitle:(NSString *)title rows:(NSArray *)strings initialSelection:(NSArray *)indexes doneBlock:(ActionMultipleStringDoneBlock)doneBlock cancelBlock:(ActionMultipleStringCancelBlock)cancelBlockOrNil origin:(id)origin { + ActionSheetMultipleStringPicker * picker = [[ActionSheetMultipleStringPicker alloc] initWithTitle:title rows:strings initialSelection:indexes doneBlock:doneBlock cancelBlock:cancelBlockOrNil origin:origin]; + [picker showActionSheetPicker]; + return picker; +} + +- (instancetype)initWithTitle:(NSString *)title rows:(NSArray *)strings initialSelection:(NSArray *)indexes doneBlock:(ActionMultipleStringDoneBlock)doneBlock cancelBlock:(ActionMultipleStringCancelBlock)cancelBlockOrNil origin:(id)origin { + self = [self initWithTitle:title rows:strings initialSelection:indexes target:nil successAction:nil cancelAction:nil origin:origin]; + if (self) { + self.onActionSheetDone = doneBlock; + self.onActionSheetCancel = cancelBlockOrNil; + } + return self; +} + ++ (instancetype)showPickerWithTitle:(NSString *)title rows:(NSArray *)data initialSelection:(NSArray *)indexes target:(id)target successAction:(SEL)successAction cancelAction:(SEL)cancelActionOrNil origin:(id)origin { + ActionSheetMultipleStringPicker *picker = [[ActionSheetMultipleStringPicker alloc] initWithTitle:title rows:data initialSelection:indexes target:target successAction:successAction cancelAction:cancelActionOrNil origin:origin]; + [picker showActionSheetPicker]; + return picker; +} + +- (instancetype)initWithTitle:(NSString *)title rows:(NSArray *)data initialSelection:(NSArray *)indexes target:(id)target successAction:(SEL)successAction cancelAction:(SEL)cancelActionOrNil origin:(id)origin { + self = [self initWithTarget:target successAction:successAction cancelAction:cancelActionOrNil origin:origin]; + if (self) { + self.data = data; + self.initialSelection = indexes; + self.title = title; + } + return self; +} + + +- (UIView *)configuredPickerView { + if (!self.data) + return nil; + CGRect pickerFrame = CGRectMake(0, 40, self.viewSize.width, 216); + UIPickerView *stringPicker = [[UIPickerView alloc] initWithFrame:pickerFrame]; + stringPicker.delegate = self; + stringPicker.dataSource = self; + + [self performInitialSelectionInPickerView:stringPicker]; + + if (self.data.count == 0) { + stringPicker.showsSelectionIndicator = NO; + stringPicker.userInteractionEnabled = NO; + } else { + stringPicker.showsSelectionIndicator = YES; + stringPicker.userInteractionEnabled = YES; + } + + //need to keep a reference to the picker so we can clear the DataSource / Delegate when dismissing + self.pickerView = stringPicker; + + return stringPicker; +} + +- (void)notifyTarget:(id)target didSucceedWithAction:(SEL)successAction origin:(id)origin { + if (self.onActionSheetDone) { + _onActionSheetDone(self, [self selectedIndexes], [self selection]); + return; + } + else if (target && [target respondsToSelector:successAction]) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + [target performSelector:successAction withObject:self.selectedIndexes withObject:origin]; +#pragma clang diagnostic pop + return; + } + NSLog(@"Invalid target/action ( %s / %s ) combination used for ActionSheetPicker and done block is nil.", object_getClassName(target), sel_getName(successAction)); +} + +- (void)notifyTarget:(id)target didCancelWithAction:(SEL)cancelAction origin:(id)origin { + if (self.onActionSheetCancel) { + _onActionSheetCancel(self); + return; + } + else if (target && cancelAction && [target respondsToSelector:cancelAction]) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + [target performSelector:cancelAction withObject:origin]; +#pragma clang diagnostic pop + } +} + +#pragma mark - UIPickerViewDelegate / DataSource + +- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component { + +} + +- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView { + return [self.data count]; +} + +- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component { + return ((NSArray *)self.data[component]).count; +} + +- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component { + id obj = (self.data)[(NSUInteger) row]; + + // return the object if it is already a NSString, + // otherwise, return the description, just like the toString() method in Java + // else, return nil to prevent exception + + if ([obj isKindOfClass:[NSString class]]) + return obj; + + if ([obj respondsToSelector:@selector(description)]) + return [obj performSelector:@selector(description)]; + + return nil; +} + +- (NSAttributedString *)pickerView:(UIPickerView *)pickerView attributedTitleForRow:(NSInteger)row forComponent:(NSInteger)component { + id obj = (self.data)[component][(NSUInteger) row]; + + // return the object if it is already a NSString, + // otherwise, return the description, just like the toString() method in Java + // else, return nil to prevent exception + + if ([obj isKindOfClass:[NSString class]]) + return [[NSAttributedString alloc] initWithString:obj attributes:self.pickerTextAttributes]; + + if ([obj respondsToSelector:@selector(description)]) + return [[NSAttributedString alloc] initWithString:[obj performSelector:@selector(description)] attributes:self.pickerTextAttributes]; + + return nil; +} + +- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view { + UILabel *pickerLabel = (UILabel *)view; + if (pickerLabel == nil) { + pickerLabel = [[UILabel alloc] init]; + } + id obj = (self.data)[component][row]; + + NSAttributedString *attributeTitle = nil; + // use the object if it is already a NSString, + // otherwise, use the description, just like the toString() method in Java + // else, use String with no text to ensure this delegate do not return a nil value. + + if ([obj isKindOfClass:[NSString class]]) + attributeTitle = [[NSAttributedString alloc] initWithString:obj attributes:self.pickerTextAttributes]; + + if ([obj respondsToSelector:@selector(description)]) + attributeTitle = [[NSAttributedString alloc] initWithString:[obj performSelector:@selector(description)] attributes:self.pickerTextAttributes]; + + if (attributeTitle == nil) { + attributeTitle = [[NSAttributedString alloc] initWithString:@"" attributes:self.pickerTextAttributes]; + } + pickerLabel.attributedText = attributeTitle; + return pickerLabel; +} + + +- (void)performInitialSelectionInPickerView:(UIPickerView *)pickerView { + for (int i = 0; i < self.selectedIndexes.count; i++) { + NSInteger row = [(NSNumber *)self.initialSelection[i] integerValue]; + [pickerView selectRow:row inComponent:i animated:NO]; + } +} + +- (NSArray *)selection { + NSMutableArray * array = [NSMutableArray array]; + for (int i = 0; i < self.data.count; i++) { + id object = self.data[i][[(UIPickerView *)self.pickerView selectedRowInComponent:(NSInteger)i]]; + [array addObject: object]; + } + return [array copy]; +} + +- (NSArray *)selectedIndexes { + NSMutableArray * indexes = [NSMutableArray array]; + for (int i = 0; i < self.data.count; i++) { + NSNumber *index = [NSNumber numberWithInteger:[(UIPickerView *)self.pickerView selectedRowInComponent:(NSInteger)i]]; + [indexes addObject: index]; + } + return [indexes copy]; +} + +//- (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component { +// return pickerView.frame.size.width - 30; +//} + +@end diff --git a/Pods/ActionSheetPicker-3.0/Pickers/ActionSheetPicker.h b/Pods/ActionSheetPicker-3.0/Pickers/ActionSheetPicker.h new file mode 100644 index 00000000..69c67ee7 --- /dev/null +++ b/Pods/ActionSheetPicker-3.0/Pickers/ActionSheetPicker.h @@ -0,0 +1,35 @@ +// +//Copyright (c) 2011, Tim Cinel +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions are met: +//* Redistributions of source code must retain the above copyright +//notice, this list of conditions and the following disclaimer. +//* Redistributions in binary form must reproduce the above copyright +//notice, this list of conditions and the following disclaimer in the +//documentation and/or other materials provided with the distribution. +//* Neither the name of the nor the +//names of its contributors may be used to endorse or promote products +//derived from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +//ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +//WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +//DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +//DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +//(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +//ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +//(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +//SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#import "ActionSheetCustomPickerDelegate.h" +#import "AbstractActionSheetPicker.h" +#import "ActionSheetCustomPicker.h" +#import "ActionSheetDatePicker.h" +#import "ActionSheetDistancePicker.h" +#import "ActionSheetLocalePicker.h" +#import "ActionSheetStringPicker.h" +#import "ActionSheetMultipleStringPicker.h" \ No newline at end of file diff --git a/Pods/ActionSheetPicker-3.0/Pickers/ActionSheetStringPicker.h b/Pods/ActionSheetPicker-3.0/Pickers/ActionSheetStringPicker.h new file mode 100644 index 00000000..7ba0c842 --- /dev/null +++ b/Pods/ActionSheetPicker-3.0/Pickers/ActionSheetStringPicker.h @@ -0,0 +1,62 @@ +// +//Copyright (c) 2011, Tim Cinel +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions are met: +//* Redistributions of source code must retain the above copyright +//notice, this list of conditions and the following disclaimer. +//* Redistributions in binary form must reproduce the above copyright +//notice, this list of conditions and the following disclaimer in the +//documentation and/or other materials provided with the distribution. +//* Neither the name of the nor the +//names of its contributors may be used to endorse or promote products +//derived from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +//ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +//WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +//DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +//DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +//(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//åLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +//ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +//(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +//SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#import "AbstractActionSheetPicker.h" + +@class ActionSheetStringPicker; +typedef void(^ActionStringDoneBlock)(ActionSheetStringPicker *picker, NSInteger selectedIndex, id selectedValue); +typedef void(^ActionStringCancelBlock)(ActionSheetStringPicker *picker); + +@interface ActionSheetStringPicker : AbstractActionSheetPicker +/** + * Create and display an action sheet picker. + * + * @param title Title label for picker + * @param data is an array of strings to use for the picker's available selection choices + * @param index is used to establish the initially selected row; + * @param target must not be empty. It should respond to "onSuccess" actions. + * @param successAction successAction + * @param cancelActionOrNil cancelAction + * @param origin must not be empty. It can be either an originating container view or a UIBarButtonItem to use with a popover arrow. + * + * @return return instance of picker + */ ++ (instancetype)showPickerWithTitle:(NSString *)title rows:(NSArray *)data initialSelection:(NSInteger)index target:(id)target successAction:(SEL)successAction cancelAction:(SEL)cancelActionOrNil origin:(id)origin; + + // Create an action sheet picker, but don't display until a subsequent call to "showActionPicker". Receiver must release the picker when ready. */ +- (instancetype)initWithTitle:(NSString *)title rows:(NSArray *)data initialSelection:(NSInteger)index target:(id)target successAction:(SEL)successAction cancelAction:(SEL)cancelActionOrNil origin:(id)origin; + + + ++ (instancetype)showPickerWithTitle:(NSString *)title rows:(NSArray *)strings initialSelection:(NSInteger)index doneBlock:(ActionStringDoneBlock)doneBlock cancelBlock:(ActionStringCancelBlock)cancelBlock origin:(id)origin; + +- (instancetype)initWithTitle:(NSString *)title rows:(NSArray *)strings initialSelection:(NSInteger)index doneBlock:(ActionStringDoneBlock)doneBlock cancelBlock:(ActionStringCancelBlock)cancelBlockOrNil origin:(id)origin; + +@property (nonatomic, copy) ActionStringDoneBlock onActionSheetDone; +@property (nonatomic, copy) ActionStringCancelBlock onActionSheetCancel; + +@end \ No newline at end of file diff --git a/Pods/ActionSheetPicker-3.0/Pickers/ActionSheetStringPicker.m b/Pods/ActionSheetPicker-3.0/Pickers/ActionSheetStringPicker.m new file mode 100644 index 00000000..8849b174 --- /dev/null +++ b/Pods/ActionSheetPicker-3.0/Pickers/ActionSheetStringPicker.m @@ -0,0 +1,195 @@ +// +//Copyright (c) 2011, Tim Cinel +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions are met: +//* Redistributions of source code must retain the above copyright +//notice, this list of conditions and the following disclaimer. +//* Redistributions in binary form must reproduce the above copyright +//notice, this list of conditions and the following disclaimer in the +//documentation and/or other materials provided with the distribution. +//* Neither the name of the nor the +//names of its contributors may be used to endorse or promote products +//derived from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +//ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +//WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +//DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +//DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +//(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//åLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +//ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +//(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +//SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#import "ActionSheetStringPicker.h" + +@interface ActionSheetStringPicker() +@property (nonatomic,strong) NSArray *data; +@property (nonatomic,assign) NSInteger selectedIndex; +@end + +@implementation ActionSheetStringPicker + ++ (instancetype)showPickerWithTitle:(NSString *)title rows:(NSArray *)strings initialSelection:(NSInteger)index doneBlock:(ActionStringDoneBlock)doneBlock cancelBlock:(ActionStringCancelBlock)cancelBlockOrNil origin:(id)origin { + ActionSheetStringPicker * picker = [[ActionSheetStringPicker alloc] initWithTitle:title rows:strings initialSelection:index doneBlock:doneBlock cancelBlock:cancelBlockOrNil origin:origin]; + [picker showActionSheetPicker]; + return picker; +} + +- (instancetype)initWithTitle:(NSString *)title rows:(NSArray *)strings initialSelection:(NSInteger)index doneBlock:(ActionStringDoneBlock)doneBlock cancelBlock:(ActionStringCancelBlock)cancelBlockOrNil origin:(id)origin { + self = [self initWithTitle:title rows:strings initialSelection:index target:nil successAction:nil cancelAction:nil origin:origin]; + if (self) { + self.onActionSheetDone = doneBlock; + self.onActionSheetCancel = cancelBlockOrNil; + } + return self; +} + ++ (instancetype)showPickerWithTitle:(NSString *)title rows:(NSArray *)data initialSelection:(NSInteger)index target:(id)target successAction:(SEL)successAction cancelAction:(SEL)cancelActionOrNil origin:(id)origin { + ActionSheetStringPicker *picker = [[ActionSheetStringPicker alloc] initWithTitle:title rows:data initialSelection:index target:target successAction:successAction cancelAction:cancelActionOrNil origin:origin]; + [picker showActionSheetPicker]; + return picker; +} + +- (instancetype)initWithTitle:(NSString *)title rows:(NSArray *)data initialSelection:(NSInteger)index target:(id)target successAction:(SEL)successAction cancelAction:(SEL)cancelActionOrNil origin:(id)origin { + self = [self initWithTarget:target successAction:successAction cancelAction:cancelActionOrNil origin:origin]; + if (self) { + self.data = data; + self.selectedIndex = index; + self.title = title; + } + return self; +} + + +- (UIView *)configuredPickerView { + if (!self.data) + return nil; + CGRect pickerFrame = CGRectMake(0, 40, self.viewSize.width, 216); + UIPickerView *stringPicker = [[UIPickerView alloc] initWithFrame:pickerFrame]; + stringPicker.delegate = self; + stringPicker.dataSource = self; + [stringPicker selectRow:self.selectedIndex inComponent:0 animated:NO]; + if (self.data.count == 0) { + stringPicker.showsSelectionIndicator = NO; + stringPicker.userInteractionEnabled = NO; + } else { + stringPicker.showsSelectionIndicator = YES; + stringPicker.userInteractionEnabled = YES; + } + + //need to keep a reference to the picker so we can clear the DataSource / Delegate when dismissing + self.pickerView = stringPicker; + + return stringPicker; +} + +- (void)notifyTarget:(id)target didSucceedWithAction:(SEL)successAction origin:(id)origin { + if (self.onActionSheetDone) { + id selectedObject = (self.data.count > 0) ? (self.data)[(NSUInteger) self.selectedIndex] : nil; + _onActionSheetDone(self, self.selectedIndex, selectedObject); + return; + } + else if (target && [target respondsToSelector:successAction]) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + [target performSelector:successAction withObject:@(self.selectedIndex) withObject:origin]; +#pragma clang diagnostic pop + return; + } + NSLog(@"Invalid target/action ( %s / %s ) combination used for ActionSheetPicker and done block is nil.", object_getClassName(target), sel_getName(successAction)); +} + +- (void)notifyTarget:(id)target didCancelWithAction:(SEL)cancelAction origin:(id)origin { + if (self.onActionSheetCancel) { + _onActionSheetCancel(self); + return; + } + else if (target && cancelAction && [target respondsToSelector:cancelAction]) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + [target performSelector:cancelAction withObject:origin]; +#pragma clang diagnostic pop + } +} + +#pragma mark - UIPickerViewDelegate / DataSource + +- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component { + self.selectedIndex = row; +} + +- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView { + return 1; +} + +- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component { + return self.data.count; +} + +- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component { + id obj = (self.data)[(NSUInteger) row]; + + // return the object if it is already a NSString, + // otherwise, return the description, just like the toString() method in Java + // else, return nil to prevent exception + + if ([obj isKindOfClass:[NSString class]]) + return obj; + + if ([obj respondsToSelector:@selector(description)]) + return [obj performSelector:@selector(description)]; + + return nil; +} + +- (NSAttributedString *)pickerView:(UIPickerView *)pickerView attributedTitleForRow:(NSInteger)row forComponent:(NSInteger)component { + id obj = (self.data)[(NSUInteger) row]; + + // return the object if it is already a NSString, + // otherwise, return the description, just like the toString() method in Java + // else, return nil to prevent exception + + if ([obj isKindOfClass:[NSString class]]) + return [[NSAttributedString alloc] initWithString:obj attributes:self.pickerTextAttributes]; + + if ([obj respondsToSelector:@selector(description)]) + return [[NSAttributedString alloc] initWithString:[obj performSelector:@selector(description)] attributes:self.pickerTextAttributes]; + + return nil; +} + +- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view { + UILabel *pickerLabel = (UILabel *)view; + if (pickerLabel == nil) { + pickerLabel = [[UILabel alloc] init]; + } + id obj = (self.data)[(NSUInteger) row]; + + NSAttributedString *attributeTitle = nil; + // use the object if it is already a NSString, + // otherwise, use the description, just like the toString() method in Java + // else, use String with no text to ensure this delegate do not return a nil value. + + if ([obj isKindOfClass:[NSString class]]) + attributeTitle = [[NSAttributedString alloc] initWithString:obj attributes:self.pickerTextAttributes]; + + if ([obj respondsToSelector:@selector(description)]) + attributeTitle = [[NSAttributedString alloc] initWithString:[obj performSelector:@selector(description)] attributes:self.pickerTextAttributes]; + + if (attributeTitle == nil) { + attributeTitle = [[NSAttributedString alloc] initWithString:@"" attributes:self.pickerTextAttributes]; + } + pickerLabel.attributedText = attributeTitle; + return pickerLabel; +} + +- (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component { + return pickerView.frame.size.width - 30; +} + +@end diff --git a/Pods/ActionSheetPicker-3.0/Pickers/DistancePickerView.h b/Pods/ActionSheetPicker-3.0/Pickers/DistancePickerView.h new file mode 100644 index 00000000..c6921b13 --- /dev/null +++ b/Pods/ActionSheetPicker-3.0/Pickers/DistancePickerView.h @@ -0,0 +1,21 @@ +// +// DistancePickerView.h +// +// Created by Evan on 12/27/10. +// Copyright 2010 NCPTT. All rights reserved. +// +// Adapted from LabeledPickerView by Kåre Morstøl (NotTooBad Software). +// This file only Copyright (c) 2009 Kåre Morstøl (NotTooBad Software). +// This file only under the Eclipse public license v1.0 +// http://www.eclipse.org/legal/epl-v10.html + +#import + + +@interface DistancePickerView : UIPickerView { + NSMutableDictionary *labels; +} + +- (void) addLabel:(NSString *)labeltext forComponent:(NSUInteger)component forLongestString:(NSString *)longestString; +- (void) updateLabel:(NSString *)labeltext forComponent:(NSUInteger)component; +@end diff --git a/Pods/ActionSheetPicker-3.0/Pickers/DistancePickerView.m b/Pods/ActionSheetPicker-3.0/Pickers/DistancePickerView.m new file mode 100644 index 00000000..72bfcc53 --- /dev/null +++ b/Pods/ActionSheetPicker-3.0/Pickers/DistancePickerView.m @@ -0,0 +1,208 @@ +// +// DistancePickerView.m +// +// Created by Evan on 12/27/10. +// Copyright 2010 NCPTT. All rights reserved. +// +// Adapted from LabeledPickerView by Kåre Morstøl (NotTooBad Software). +// This file only Copyright (c) 2009 Kåre Morstøl (NotTooBad Software). +// This file only under the Eclipse public license v1.0 +// http://www.eclipse.org/legal/epl-v10.html + +#import "DistancePickerView.h" + + +@implementation DistancePickerView + + +- (instancetype)initWithFrame:(CGRect)frame +{ + + self = [super initWithFrame:frame]; + if ( self ) + { + labels = [[NSMutableDictionary alloc] initWithCapacity:2]; + } + return self; +} + +- (void)addLabel:(NSString *)labeltext forComponent:(NSUInteger)component forLongestString:(NSString *)longestString +{ + labels[@(component)] = labeltext; + + NSString *keyName = [NSString stringWithFormat:@"%@_%ld", @"longestString", (unsigned long)component]; + + if ( !longestString ) + { + longestString = labeltext; + } + + labels[keyName] = longestString; +} + +- (void)updateLabel:(NSString *)labeltext forComponent:(NSUInteger)component +{ + + UILabel *theLabel = (UILabel *) [self viewWithTag:component + 1]; + + // Update label if it doesn’t match current label + if ( ![theLabel.text isEqualToString:labeltext] ) + { + + NSString *keyName = [NSString stringWithFormat:@"%@_%ld", @"longestString", (unsigned long)component]; + NSString *longestString = labels[keyName]; + + // Update label array with our new string value + [self addLabel:labeltext forComponent:component forLongestString:longestString]; + + // change label during fade out/in + [UIView beginAnimations:nil context:NULL]; + [UIView setAnimationDuration:0.75]; + [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; + theLabel.alpha = 0.00; + theLabel.text = labeltext; + theLabel.alpha = 1.00; + [UIView commitAnimations]; + } + +} + +/** + Adds the labels to the view, below the selection indicator glass. + The labels are aligned to the right side of the wheel. + The delegate is responsible for providing enough width for both the value and the label. + */ +- (void)didMoveToWindow +{ + // exit if view is removed from the window or there are no labels. + if ( !self.window || [labels count] == 0 ) + return; + + UIFont *labelfont = [UIFont boldSystemFontOfSize:20]; + + // find the width of all the wheels combined + CGFloat widthofwheels = 0; + for (int i = 0; i < self.numberOfComponents; i++) + { + widthofwheels += [self rowSizeForComponent:i].width; + } + + // find the left side of the first wheel. + // seems like a misnomer, but that will soon be corrected. + CGFloat rightsideofwheel = (self.frame.size.width - widthofwheels) / 2; + + // cycle through all wheels + for (int component = 0; component < self.numberOfComponents; component++) + { + // find the right side of the wheel + rightsideofwheel += [self rowSizeForComponent:component].width; + + // get the text for the label. + // move on to the next if there is no label for this wheel. + NSString *text = labels[@(component)]; + if ( text ) + { + + // set up the frame for the label using our longestString length + NSString *keyName = [NSString stringWithFormat:@"%@_%@", @"longestString", + @(component)]; + NSString *longestString = labels[keyName]; + CGRect frame; + + if ( NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) + { +#pragma clang diagnostic push +#pragma ide diagnostic ignored "UnavailableInDeploymentTarget" + frame.size = [longestString sizeWithAttributes: + @{NSFontAttributeName : + labelfont}]; +#pragma clang diagnostic pop + } + else + { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + frame.size = [longestString sizeWithFont:labelfont]; +#pragma clang diagnostic pop + } + + + + // center it vertically + frame.origin.y = (CGFloat) ((self.frame.size.height / 2.f) - (frame.size.height / 2.f) - 0.5f); + + // align it to the right side of the wheel, with a margin. + // use a smaller margin for the rightmost wheel. + frame.origin.x = rightsideofwheel - frame.size.width - (component == self.numberOfComponents - 1 ? 5 : 7); + + // set up the label. If label already exists, just get a reference to it + BOOL addlabelView = NO; + UILabel *label = (UILabel *) [self viewWithTag:component + 1]; + if ( !label ) + { + label = [[UILabel alloc] initWithFrame:frame]; + addlabelView = YES; + } + + label.text = text; + label.font = labelfont; + label.backgroundColor = [UIColor clearColor]; + label.shadowColor = [UIColor whiteColor]; + label.shadowOffset = CGSizeMake(0, 1); + + // Tag cannot be 0 so just increment component number to esnure we get a positive + // NB update/remove Label methods are aware of this incrementation! + label.tag = component + 1; + + if ( addlabelView ) + { + /* + and now for the tricky bit: adding the label to the view. + kind of a hack to be honest, might stop working if Apple decides to + change the inner workings of the UIPickerView. + */ + if ( self.showsSelectionIndicator ) + { + // if this is the last wheel, add label as the third view from the top + if ( component == self.numberOfComponents - 1 ) if ( NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) + { + UIView *o = [self.subviews[0] subviews][[[self.subviews[0] subviews] count] - 1]; + UIView *subview = [o subviews][2]; + UIView *view = [(subview.subviews)[0] subviews][1]; + [self insertSubview:label aboveSubview:view]; + } + else + { + [self insertSubview:label atIndex:[self.subviews count] - 3]; + } + // otherwise add label as the 5th, 10th, 15th etc view from the top + else + { + if ( NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) + { + [self insertSubview:label + aboveSubview:[self.subviews[0] subviews][(NSUInteger) component]]; + } + else + { + [self insertSubview:label aboveSubview:(self.subviews)[(NSUInteger) (5 * (component + 1))]]; + } + + } + } else + // there is no selection indicator, so just add it to the top + [self addSubview:label]; + + } + + if ( [self.delegate respondsToSelector:@selector(pickerView:didSelectRow:inComponent:)] ) + [self.delegate pickerView:self didSelectRow:[self selectedRowInComponent:component] + inComponent:component]; + } + + } + +} + + +@end diff --git a/Pods/ActionSheetPicker-3.0/Pickers/SWActionSheet.h b/Pods/ActionSheetPicker-3.0/Pickers/SWActionSheet.h new file mode 100644 index 00000000..802f2421 --- /dev/null +++ b/Pods/ActionSheetPicker-3.0/Pickers/SWActionSheet.h @@ -0,0 +1,19 @@ +// +// Created by Petr Korolev on 11/08/14. +// + + +#import +#import + +@interface SWActionSheet : UIView +@property(nonatomic, strong) UIView *bgView; + +- (void)dismissWithClickedButtonIndex:(int)i animated:(BOOL)animated; + +- (void)showFromBarButtonItem:(UIBarButtonItem *)item animated:(BOOL)animated; + +- (instancetype)initWithView:(UIView *)view windowLevel:(UIWindowLevel)windowLevel; + +- (void)showInContainerView; +@end \ No newline at end of file diff --git a/Pods/ActionSheetPicker-3.0/Pickers/SWActionSheet.m b/Pods/ActionSheetPicker-3.0/Pickers/SWActionSheet.m new file mode 100644 index 00000000..da8ddb45 --- /dev/null +++ b/Pods/ActionSheetPicker-3.0/Pickers/SWActionSheet.m @@ -0,0 +1,223 @@ +// +// Created by Petr Korolev on 11/08/14. +// + +#import "SWActionSheet.h" + + +static const float delay = 0.f; + +static const float duration = .25f; + +static const enum UIViewAnimationOptions options = UIViewAnimationOptionCurveEaseIn; + + +@interface SWActionSheetVC : UIViewController + +@property (nonatomic, retain) SWActionSheet *actionSheet; + +@end + + +@interface SWActionSheet () +{ + UIWindow *SWActionSheetWindow; +} + +@property (nonatomic, assign) BOOL presented; +@property (nonatomic) UIWindowLevel windowLevel; + +- (void)configureFrameForBounds:(CGRect)bounds; +- (void)showInContainerViewAnimated:(BOOL)animated; + +@end + + +@implementation SWActionSheet +{ + UIView *view; + UIView *_bgView; +} + +- (void)dismissWithClickedButtonIndex:(int)i animated:(BOOL)animated +{ + CGPoint fadeOutToPoint = CGPointMake(view.center.x, + self.center.y + CGRectGetHeight(view.frame)); + // Window of app + //UIWindow *appWindow = [UIApplication sharedApplication].windows.firstObject; + // Actions + void (^actions)(void) = ^{ + self.center = fadeOutToPoint; + self.backgroundColor = [UIColor colorWithWhite:0.f alpha:0.0f]; + }; + void (^completion)(BOOL) = ^(BOOL finished) { + // if (![appWindow isKeyWindow]) + // [appWindow makeKeyAndVisible]; + [self destroyWindow]; + [self removeFromSuperview]; + }; + // Do actions animated or not + if (animated) { + [UIView animateWithDuration:duration delay:delay options:options animations:actions completion:completion]; + } else { + actions(); + completion(YES); + } + self.presented = NO; +} + +- (void)destroyWindow +{ + if (SWActionSheetWindow) + { + [self actionSheetContainer].actionSheet = nil; + SWActionSheetWindow.hidden = YES; + if ([SWActionSheetWindow isKeyWindow]) + [SWActionSheetWindow resignFirstResponder]; + SWActionSheetWindow.rootViewController = nil; + SWActionSheetWindow = nil; + } +} + +- (UIWindow *)window +{ + if ( SWActionSheetWindow ) + { + return SWActionSheetWindow; + } + else + { + return SWActionSheetWindow = ({ + UIWindow *window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; + window.windowLevel = self.windowLevel; + window.backgroundColor = [UIColor clearColor]; + window.rootViewController = [SWActionSheetVC new]; + window; + }); + } +} + +- (SWActionSheetVC *)actionSheetContainer +{ + return (SWActionSheetVC *) [self window].rootViewController; +} + +- (instancetype)initWithView:(UIView *)aView windowLevel:(UIWindowLevel)windowLevel +{ + if ((self = [super init])) + { + view = aView; + _windowLevel = windowLevel; + self.backgroundColor = [UIColor colorWithWhite:0.f alpha:0.0f]; + _bgView = [UIView new]; + _bgView.backgroundColor = [UIColor colorWithRed:247.f/255.f green:247.f/255.f blue:247.f/255.f alpha:1.0f]; + [self addSubview:_bgView]; + [self addSubview:view]; + } + return self; +} + +- (void)configureFrameForBounds:(CGRect)bounds +{ + self.frame = CGRectMake(bounds.origin.x, bounds.origin.y, bounds.size.width, bounds.size.height + view.bounds.size.height); + view.frame = CGRectMake(view.bounds.origin.x, bounds.size.height, view.bounds.size.width, view.bounds.size.height); + view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin; + _bgView.frame = view.frame; + _bgView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; +} + +- (void)showFromBarButtonItem:(UIBarButtonItem *)item animated:(BOOL)animated +{ + [self showInContainerView]; +} + +- (void)showInContainerView +{ + // Make sheet window visible and active + UIWindow *sheetWindow = [self window]; + if (![sheetWindow isKeyWindow]) + [sheetWindow makeKeyAndVisible]; + sheetWindow.hidden = NO; + // Put our ActionSheet in Container (it will be presented as soon as possible) + self.actionSheetContainer.actionSheet = self; +} + +- (void)showInContainerViewAnimated:(BOOL)animated +{ + CGPoint toPoint; + CGFloat y = self.center.y - CGRectGetHeight(view.frame); + toPoint = CGPointMake(self.center.x, y); + // Present actions + void (^animations)(void) = ^{ + self.center = toPoint; + self.backgroundColor = [UIColor colorWithWhite:0.f alpha:0.5f]; + }; + // Present sheet + if (animated) + [UIView animateWithDuration:duration delay:delay options:options animations:animations completion:nil]; + else + animations(); + self.presented = YES; +} + +@end + + +#pragma mark - SWActionSheet Container + +@implementation SWActionSheetVC + + +- (UIStatusBarStyle)preferredStatusBarStyle { + return [UIApplication sharedApplication].statusBarStyle; +} + +- (void)setActionSheet:(SWActionSheet *)actionSheet +{ + // Prevent processing one action sheet twice + if (_actionSheet == actionSheet) + return; + // Dissmiss previous action sheet if it presented + if (_actionSheet.presented) + [_actionSheet dismissWithClickedButtonIndex:0 animated:YES]; + // Remember new action sheet + _actionSheet = actionSheet; + // Present new action sheet + [self presentActionSheetAnimated:YES]; +} + +- (void)viewWillAppear:(BOOL)animated +{ + [super viewWillAppear:animated]; + [self presentActionSheetAnimated:YES]; +} + +- (void)presentActionSheetAnimated:(BOOL)animated +{ + // New action sheet will be presented only when view controller will be loaded + if (_actionSheet && [self isViewLoaded] && !_actionSheet.presented) + { + [_actionSheet configureFrameForBounds:self.view.bounds]; + _actionSheet.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + [self.view addSubview:_actionSheet]; + [_actionSheet showInContainerViewAnimated:animated]; + } +} + +- (BOOL)prefersStatusBarHidden { + return [UIApplication sharedApplication].statusBarHidden; +} + +- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation +{ + return NO; +} + +// iOS6 support +// --- +- (BOOL)shouldAutorotate +{ + return YES; +} + +@end diff --git a/Pods/ActionSheetPicker-3.0/README.md b/Pods/ActionSheetPicker-3.0/README.md new file mode 100644 index 00000000..e48080fe --- /dev/null +++ b/Pods/ActionSheetPicker-3.0/README.md @@ -0,0 +1,230 @@ +[![Version](http://img.shields.io/cocoapods/v/ActionSheetPicker-3.0.svg)](http://cocoadocs.org/docsets/ActionSheetPicker-3.0) +[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) +[![Build Status](https://travis-ci.org/skywinder/ActionSheetPicker-3.0.svg?branch=master)](https://travis-ci.org/skywinder/ActionSheetPicker-3.0) +[![Issues](http://img.shields.io/github/issues/skywinder/ActionSheetPicker-3.0.svg)](https://github.com/skywinder/ActionSheetPicker-3.0/issues?state=open) +[![License](https://img.shields.io/cocoapods/l/ActionSheetPicker-3.0.svg)](http://cocoadocs.org/docsets/ActionSheetPicker-3.0) +[![Platform](https://img.shields.io/cocoapods/p/ActionSheetPicker-3.0.svg)](http://cocoadocs.org/docsets/ActionSheetPicker-3.0) + +ActionSheetPicker-3.0 +================== + +- [Overview](#overview) + - [Benefits](#benefits) +- [QuickStart](#quickstart) + - [Basic Usage](#basic-usage) +- [Installation](#installation) +- [Example Projects](#example-projects) +- [Screenshots](#screenshots) +- [Apps using this library](#apps-using-this-library) +- [Maintainer and Contributor](#maintainer-and-contributor) +- [Credits](#credits) +- [Contributing](#contributing) + +Please welcome: **ActionSheetPicker-3.0**! + +`pod 'ActionSheetPicker-3.0', '~> 2.3.0'` (**iOS 5.1.1-9.x** compatible!) + +##ActionSheetPicker = UIPickerView + UIActionSheet ## + +![Animation](Screenshots/example.gif) + +Well, that's how it started. Now, the following is more accurate: + + * _**iPhone/iPod** ActionSheetPicker = ActionSheetPicker = A Picker + UIActionSheet_ + * _**iPad** ActionSheetPicker = A Picker + UIPopoverController_ + + +## Overview ## +Easily present an ActionSheet with a PickerView, allowing user to select from a number of immutable options. + +### Benefits ## + + * Spawn pickers with convenience function - delegate or reference + not required. Just provide a target/action callback. + * Add buttons to UIToolbar for quick selection (see ActionSheetDatePicker below) + * Delegate protocol available for more control + * Universal (iPhone/iPod/iPad) + +## QuickStart + +There are 4 distinct picker view options: `ActionSheetStringPicker`, `ActionSheetDistancePicker`, `ActionSheetDatePicker`, and `ActionSheetCustomPicker`. We'll focus here on how to use the `ActionSheetStringPicker` since it's most likely the one you want to use. + +### Basic Usage ## + +**For detailed info about customisations, please look [BASIC USAGE](https://github.com/skywinder/ActionSheetPicker-3.0/blob/master/BASIC-USAGE.md)** + +- Custom buttons view +- Custom buttons callbacks +- Action by clicking outside of the picker +- Background color and blur effect +- Other customisations + +**For detailed examples, please check [Example Projects](#example-projects) in this repo.** + +#### `Swift:` + +```swift + ActionSheetMultipleStringPicker.show(withTitle: "Multiple String Picker", rows: [ + ["One", "Two", "A lot"], + ["Many", "Many more", "Infinite"] + ], initialSelection: [2, 2], doneBlock: { + picker, indexes, values in + + print("values = \(values)") + print("indexes = \(indexes)") + print("picker = \(picker)") + return + }, cancel: { ActionMultipleStringCancelBlock in return }, origin: sender) +``` + +#### `Objective-C:` + +```obj-c +// Inside a IBAction method: + +// Create an array of strings you want to show in the picker: +NSArray *colors = [NSArray arrayWithObjects:@"Red", @"Green", @"Blue", @"Orange", nil]; + +[ActionSheetStringPicker showPickerWithTitle:@"Select a Color" + rows:colors + initialSelection:0 + doneBlock:^(ActionSheetStringPicker *picker, NSInteger selectedIndex, id selectedValue) { + NSLog(@"Picker: %@, Index: %@, value: %@", + picker, selectedIndex, selectedValue); + } + cancelBlock:^(ActionSheetStringPicker *picker) { + NSLog(@"Block Picker Canceled"); + } + origin:sender]; +// You can also use self.view if you don't have a sender +``` + + + +##Installation## + +### CocoaPods + +[CocoaPods](http://cocoapods.org) is a dependency manager for Cocoa projects. + +You can install it with the following command: + +```bash +$ gem install cocoapods +``` + +To integrate ActionSheetPicker-3.0 into your Xcode project using CocoaPods, specify it in your `Podfile`: + +```ruby +source 'https://github.com/CocoaPods/Specs.git' +use_frameworks! + +pod 'ActionSheetPicker-3.0' +``` + +Then, run the following command: + +```bash +$ pod install +``` + +### Import to project + +To import pod you should add string: + +- For `Obj-c` projects: + +```obj-c + #import "ActionSheetPicker.h" +``` +- For `Swift` projects: + +```swift + import ActionSheetPicker_3_0 +``` +### Carthage + +Carthage is a decentralized dependency manager that automates the process of adding frameworks to your Cocoa application. + +You can install Carthage with [Homebrew](http://brew.sh/) using the following command: + +```bash +$ brew update +$ brew install carthage +``` + +To integrate ActionSheetPicker-3.0 into your Xcode project using Carthage, specify it in your `Cartfile`: + +```ogdl +github "skywinder/ActionSheetPicker-3.0" +``` + +### Manually + +If you prefer not to use either of the aforementioned dependency managers, you can integrate ActionSheetPicker-3.0 into your project manually. + +The "old school" way is manually add to your project all from [Pickers](/Pickers) folder. + +### Embedded Framework + +- Add ActionSheetPicker-3.0 as a [submodule](http://git-scm.com/docs/git-submodule) by opening the Terminal, `cd`-ing into your top-level project directory, and entering the following command: + +```bash +$ git submodule add https://github.com/skywinder/ActionSheetPicker-3.0.git +``` + +- Open the `ActionSheetPicker-3.0` folder, and drag `CoreActionSheetPicker.xcodeproj` into the file navigator of your app project. +- In Xcode, navigate to the target configuration window by clicking on the blue project icon, and selecting the application target under the "Targets" heading in the sidebar. +- Ensure that the deployment target of CoreActionSheetPicker.framework matches that of the application target. +- In the tab bar at the top of that window, open the "Build Phases" panel. +- Expand the "Target Dependencies" group, and add `CoreActionSheetPicker.framework`. +- Click on the `+` button at the top left of the panel and select "New Copy Files Phase". Rename this new phase to "Copy Frameworks", set the "Destination" to "Frameworks", and add `CoreActionSheetPicker.framework`. + +## Example Projects## + +`open ActionSheetPicker-3.0.xcworkspace` + +Here is 4 projects: + +- **CoreActionSheetPicker** - all picker files combined in one Framework. (available since `iOS 8`) +- **ActionSheetPicker** - modern and descriptive Obj-C project with many examples. +- **Swift-Example** - example, written on Swift. (only with basic 3 Pickers examples, for all examples please run `ActionSheetPicker` project) +- **ActionSheetPicker-iOS6-7** - iOS 6 and 7 comparable project. or to run only this project `open Example-for-and-6/ActionSheetPicker.xcodeproj` + +## Screenshots + +![ActionSheetPicker](https://raw.githubusercontent.com/skywinder/ActionSheetPicker-3.0/master/Screenshots/string.png "ActionSheetPicker") +![ActionSheetDatePicker](https://raw.githubusercontent.com/skywinder/ActionSheetPicker-3.0/master/Screenshots/date.png "ActionSheetDatePicker") +![ActionSheetDatePicker](https://raw.githubusercontent.com/Jack-s/ActionSheetPicker-3.0/master/Screenshots/time.png "ActionSheetDatePicker") +![CustomButtons](https://raw.githubusercontent.com/skywinder/ActionSheetPicker-3.0/master/Screenshots/custom.png "CustomButtons") +![iPad Support](https://raw.githubusercontent.com/skywinder/ActionSheetPicker-3.0/master/Screenshots/ipad.png "iPad Support") + + +## [Apps using this library](https://github.com/skywinder/ActionSheetPicker-3.0/wiki/Apps-using-ActionSheetPicker-3.0) + +If you've used this project in a live app, please let me know! Nothing makes me happier than seeing someone else take my work and go wild with it. + +*If you are using `ActionSheetPicker-3.0` in your app or know of an app that uses it, please add it to [this] (https://github.com/skywinder/ActionSheetPicker-3.0/wiki/Apps-using-ActionSheetPicker-3.0) list.* + +## Maintainer and Contributor + +- [Petr Korolev](http://github.com/skywinder) (update to iOS 7 and iOS 8, implementing new pickers, community support) + +## Credits + +- ActionSheetPicker was originally created by [Tim Cinel](http://github.com/TimCinel) ([@TimCinel](http://twitter.com/TimCinel)) Since the [Tim's repo](https://github.com/TimCinel/ActionSheetPicker) is not support iOS 7+, I forked from his repo and implement iOS 7-8 support, and also bunch of UI fixes, crash-fixes and different customisation abilities. + +- And most of all, thanks to ActionSheetPicker-3.0's [growing list of contributors](https://github.com/skywinder/ActionSheetPicker-3.0/graphs/contributors). + +## Contributing + +1. Create an issue to discuss about your idea +2. Fork it (https://github.com/skywinder/ActionSheetPicker-3.0/fork) +3. Create your feature branch (`git checkout -b my-new-feature`) +4. Commit your changes (`git commit -am 'Add some feature'`) +5. Push to the branch (`git push origin my-new-feature`) +6. Create a new Pull Request + +**Bug reports, feature requests, patches, well-wishes, and rap demo tapes are always welcome.** + +[![Analytics](https://ga-beacon.appspot.com/UA-52127948-3/ActionSheetPicker-3.0/readme)](https://ga-beacon.appspot.com/UA-52127948-3/ActionSheetPicker-3.0/readme) diff --git a/Pods/ChameleonFramework/LICENSE.md b/Pods/ChameleonFramework/LICENSE.md new file mode 100755 index 00000000..7fd117d0 --- /dev/null +++ b/Pods/ChameleonFramework/LICENSE.md @@ -0,0 +1,21 @@ +##The MIT License (MIT) + +> Copyright (c) 2014-2015 Vicc Alexander + +> Permission is hereby granted, free of charge, to any person obtaining a copy +> of this software and associated documentation files (the "Software"), to deal +> in the Software without restriction, including without limitation the rights +> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +> copies of the Software, and to permit persons to whom the Software is +> furnished to do so, subject to the following conditions: + +> The above copyright notice and this permission notice shall be included in all +> copies or substantial portions of the Software. + +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +> SOFTWARE. diff --git a/Pods/ChameleonFramework/Pod/Classes/Objective-C/Chameleon.h b/Pods/ChameleonFramework/Pod/Classes/Objective-C/Chameleon.h new file mode 100755 index 00000000..9573d112 --- /dev/null +++ b/Pods/ChameleonFramework/Pod/Classes/Objective-C/Chameleon.h @@ -0,0 +1,31 @@ +// +// Chameleon.h +// Chameleon +// +// Created by Vicc Alexander on 9/24/15. +// Copyright © 2015 Vicc Alexander. All rights reserved. +// + +#import + +//! Project version number for Chameleon. +FOUNDATION_EXPORT double ChameleonVersionNumber; + +//! Project version string for Chameleon. +FOUNDATION_EXPORT const unsigned char ChameleonVersionString[]; + +// In this header, you should import all the public headers of your framework using statements like #import + +#import "Chameleon_.h" + +#import "UIButton+Chameleon.h" +#import "UILabel+Chameleon.h" +#import "UIColor+ChameleonPrivate.h" +#import "UIImage+ChameleonPrivate.h" +#import "UIView+ChameleonPrivate.h" +#import "UIAppearance+Swift.h" + +#import "NSArray+Chameleon.h" +#import "UIColor+Chameleon.h" +#import "UINavigationController+Chameleon.h" +#import "UIViewController+Chameleon.h" diff --git a/Pods/ChameleonFramework/Pod/Classes/Objective-C/ChameleonConstants.h b/Pods/ChameleonFramework/Pod/Classes/Objective-C/ChameleonConstants.h new file mode 100755 index 00000000..9c9c3452 --- /dev/null +++ b/Pods/ChameleonFramework/Pod/Classes/Objective-C/ChameleonConstants.h @@ -0,0 +1,21 @@ +// +// Constants.h +// Chameleon +// +// Created by Vicc Alexander on 6/4/15. +// Copyright (c) 2015 Vicc Alexander. All rights reserved. +// + +#import +#import + +/** + * A contrasting status bar, intended for use on any backgrounds. + * + * @since 2.0 + */ +extern const UIStatusBarStyle UIStatusBarStyleContrast; + +@interface ChameleonConstants : NSObject + +@end diff --git a/Pods/ChameleonFramework/Pod/Classes/Objective-C/ChameleonConstants.m b/Pods/ChameleonFramework/Pod/Classes/Objective-C/ChameleonConstants.m new file mode 100755 index 00000000..02cdc7f3 --- /dev/null +++ b/Pods/ChameleonFramework/Pod/Classes/Objective-C/ChameleonConstants.m @@ -0,0 +1,15 @@ +// +// Constants.m +// Chameleon +// +// Created by Vicc Alexander on 6/4/15. +// Copyright (c) 2015 Vicc Alexander. All rights reserved. +// + +#import "ChameleonConstants.h" + +const UIStatusBarStyle UIStatusBarStyleContrast = 100; + +@implementation ChameleonConstants + +@end diff --git a/Pods/ChameleonFramework/Pod/Classes/Objective-C/ChameleonEnums.h b/Pods/ChameleonFramework/Pod/Classes/Objective-C/ChameleonEnums.h new file mode 100755 index 00000000..0a9fed38 --- /dev/null +++ b/Pods/ChameleonFramework/Pod/Classes/Objective-C/ChameleonEnums.h @@ -0,0 +1,39 @@ +// +// ChameleonEnums.h +// Chameleon +// +// Created by Vicc Alexander on 6/8/15. +// Copyright (c) 2015 Vicc Alexander. All rights reserved. +// + +#ifndef Chameleon_ChameleonEnums_h +#define Chameleon_ChameleonEnums_h + +/** + * Specifies how text-based UI elements and other content such as switch knobs, should be colored. + * + * @since 2.0 + */ + +typedef NS_ENUM(NSUInteger, UIContentStyle) { + /** + * Automatically chooses and colors text-based elements with the shade that best contrasts its @c backgroundColor. + * + * @since 2.0 + */ + UIContentStyleContrast, + /** + * Colors text-based elements using a light shade. + * + * @since 2.0 + */ + UIContentStyleLight, + /** + * Colors text-based elements using a light shade. + * + * @since 2.0 + */ + UIContentStyleDark +}; + +#endif diff --git a/Pods/ChameleonFramework/Pod/Classes/Objective-C/ChameleonMacros.h b/Pods/ChameleonFramework/Pod/Classes/Objective-C/ChameleonMacros.h new file mode 100755 index 00000000..237c579e --- /dev/null +++ b/Pods/ChameleonFramework/Pod/Classes/Objective-C/ChameleonMacros.h @@ -0,0 +1,125 @@ + +// ChameleonMacros.h + +/* + + The MIT License (MIT) + + Copyright (c) 2014-2015 Vicc Alexander. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + + */ + +#import "UIColor+Chameleon.h" + +#pragma mark - Light Shades Shorthand + +#define FlatBlack [UIColor flatBlackColor] +#define FlatBlue [UIColor flatBlueColor] +#define FlatBrown [UIColor flatBrownColor] +#define FlatCoffee [UIColor flatCoffeeColor] +#define FlatForestGreen [UIColor flatForestGreenColor] +#define FlatGray [UIColor flatGrayColor] +#define FlatGreen [UIColor flatGreenColor] +#define FlatLime [UIColor flatLimeColor] +#define FlatMagenta [UIColor flatMagentaColor] +#define FlatMaroon [UIColor flatMaroonColor] +#define FlatMint [UIColor flatMintColor] +#define FlatNavyBlue [UIColor flatNavyBlueColor] +#define FlatOrange [UIColor flatOrangeColor] +#define FlatPink [UIColor flatPinkColor] +#define FlatPlum [UIColor flatPlumColor] +#define FlatPowderBlue [UIColor flatPowderBlueColor] +#define FlatPurple [UIColor flatPurpleColor] +#define FlatRed [UIColor flatRedColor] +#define FlatSand [UIColor flatSandColor] +#define FlatSkyBlue [UIColor flatSkyBlueColor] +#define FlatTeal [UIColor flatTealColor] +#define FlatWatermelon [UIColor flatWatermelonColor] +#define FlatWhite [UIColor flatWhiteColor] +#define FlatYellow [UIColor flatYellowColor] + +// --------------------------------------------------- + +#pragma mark - Dark Shades Shorthand + +#define FlatBlackDark [UIColor flatBlackColorDark] +#define FlatBlueDark [UIColor flatBlueColorDark] +#define FlatBrownDark [UIColor flatBrownColorDark] +#define FlatCoffeeDark [UIColor flatCoffeeColorDark] +#define FlatForestGreenDark [UIColor flatForestGreenColorDark] +#define FlatGrayDark [UIColor flatGrayColorDark] +#define FlatGreenDark [UIColor flatGreenColorDark] +#define FlatLimeDark [UIColor flatLimeColorDark] +#define FlatMagentaDark [UIColor flatMagentaColorDark] +#define FlatMaroonDark [UIColor flatMaroonColorDark] +#define FlatMintDark [UIColor flatMintColorDark] +#define FlatNavyBlueDark [UIColor flatNavyBlueColorDark] +#define FlatOrangeDark [UIColor flatOrangeColorDark] +#define FlatPinkDark [UIColor flatPinkColorDark] +#define FlatPlumDark [UIColor flatPlumColorDark] +#define FlatPowderBlueDark [UIColor flatPowderBlueColorDark] +#define FlatPurpleDark [UIColor flatPurpleColorDark] +#define FlatRedDark [UIColor flatRedColorDark] +#define FlatSandDark [UIColor flatSandColorDark] +#define FlatSkyBlueDark [UIColor flatSkyBlueColorDark] +#define FlatTealDark [UIColor flatTealColorDark] +#define FlatWatermelonDark [UIColor flatWatermelonColorDark] +#define FlatWhiteDark [UIColor flatWhiteColorDark] +#define FlatYellowDark [UIColor flatYellowColorDark] + +// --------------------------------------------------- + +#pragma mark - Special Colors Shorthand + +#define RandomFlatColor [UIColor randomFlatColor] +#define ClearColor [UIColor clearColor] + +// --------------------------------------------------- + +#pragma mark - UIColor Methods Shorthand + +#define AverageColorFromImage(image) [UIColor colorWithAverageColorFromImage:image] +#define AverageColorFromImageWithAlpha(image, alpha) [UIColor colorWithAverageColorFromImage:image withAlpha:alpha] + +#define ComplementaryFlatColor(color) [UIColor colorWithComplementaryFlatColorOf:color] +#define ComplementaryFlatColorWithAlpha(color, alpha) [UIColor colorWithComplementaryFlatColorOf:color withAlpha:alpha] + +#define ContrastColor(backgroundColor, returnFlat) [UIColor colorWithContrastingBlackOrWhiteColorOn:backgroundColor isFlat:returnFlat] +#define ContrastColorWithAlpha(backgroundColor, returnFlat, alpha) [UIColor colorWithContrastingBlackOrWhiteColorOn:backgroundColor isFlat:returnFlat alpha:alpha] + +#define GradientColor(gradientStyle, frame, colors) [UIColor colorWithGradientStyle:gradientStyle withFrame:frame andColors:colors] + +#define HexColor(hexString) [UIColor colorWithHexString:hexString] +#define HexColorWithAlpha(hexString, alpha) [UIColor colorWithHexString:hexString withAlpha:alpha] + +#define RandomFlatColorInArray(colors) [UIColor colorWithRandomColorInArray:colors] +#define RandomFlatColorExcluding(colors) [UIColor colorWithRandomFlatColorExcludingColorsInArray:colors]; +#define RandomFlatColorWithShade(shade) [UIColor colorWithRandomFlatColorOfShadeStyle:shade] +#define RandomFlatColorWithShadeAndAlpha(shade, alpha) [UIColor colorWithRandomFlatColorOfShadeStyle:shade withAlpha:alpha] + +// --------------------------------------------------- + +#pragma mark - NSArray Shorthand + +#define ColorsWithScheme(colorSchemeType, color, isFlatScheme) [NSArray arrayOfColorsWithColorScheme:colorSchemeType usingColor:color withFlatScheme:isFlatScheme] +#define ColorsFromImage(image, isFlatScheme) [NSArray arrayOfColorsFromImage:image withFlatScheme:isFlatScheme] + + diff --git a/Pods/ChameleonFramework/Pod/Classes/Objective-C/Chameleon_.h b/Pods/ChameleonFramework/Pod/Classes/Objective-C/Chameleon_.h new file mode 100755 index 00000000..d492a47a --- /dev/null +++ b/Pods/ChameleonFramework/Pod/Classes/Objective-C/Chameleon_.h @@ -0,0 +1,66 @@ +// +// ChameleonInternal.h +// Chameleon +// +// Created by Vicc Alexander on 6/4/15. +// Copyright (c) 2015 Vicc Alexander. All rights reserved. +// + +#import +#import + +#import "ChameleonConstants.h" +#import "ChameleonEnums.h" +#import "ChameleonMacros.h" + +#import "NSArray+Chameleon.h" +#import "UIColor+Chameleon.h" +#import "UINavigationController+Chameleon.h" +#import "UIViewController+Chameleon.h" + +@interface Chameleon : NSObject + +#pragma mark - Global Theming + +/** + * Set a global theme using a primary color and the specified content style. + * + * @param primaryColor The primary color to theme all controllers with. + * @param contentStyle The contentStyle. + * + * @note By default the secondary color will be a darker shade of the specified primary color. + * + * @since 2.0 + */ ++ (void)setGlobalThemeUsingPrimaryColor:(UIColor *)primaryColor + withContentStyle:(UIContentStyle)contentStyle; + +/** + * Set a global theme using a primary color, secondary color, and the specified content style. + * + * @param primaryColor The primary color to theme all controllers with. + * @param secondaryColor The secondary color to theme all controllers with. + * @param contentStyle The contentStyle. + * + * @since 2.0 + */ ++ (void)setGlobalThemeUsingPrimaryColor:(UIColor *)primaryColor + withSecondaryColor:(UIColor *)secondaryColor + andContentStyle:(UIContentStyle)contentStyle; + +/** + * Set a global theme using a primary color, secondary color, font name, and the specified content style. + * + * @param primaryColor The primary color to theme all controllers with. + * @param secondaryColor The secondary color to theme all controllers with. + * @param fontName The default font for all text-based UI elements. + * @param contentStyle The contentStyle. + * + * @since 2.0 + */ ++ (void)setGlobalThemeUsingPrimaryColor:(UIColor *)primaryColor + withSecondaryColor:(UIColor *)secondaryColor + usingFontName:(NSString *)fontName + andContentStyle:(UIContentStyle)contentStyle; + +@end diff --git a/Pods/ChameleonFramework/Pod/Classes/Objective-C/Chameleon_.m b/Pods/ChameleonFramework/Pod/Classes/Objective-C/Chameleon_.m new file mode 100755 index 00000000..4aab5a23 --- /dev/null +++ b/Pods/ChameleonFramework/Pod/Classes/Objective-C/Chameleon_.m @@ -0,0 +1,793 @@ +// +// ChameleonInternal.m +// Chameleon +// +// Created by Vicc Alexander on 6/4/15. +// Copyright (c) 2015 Vicc Alexander. All rights reserved. +// + +#import "Chameleon_.h" +#import "UILabel+Chameleon.h" +#import "UIButton+Chameleon.h" +#import "UIAppearance+Swift.h" + +@implementation Chameleon + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + ++ (void)setGlobalThemeUsingPrimaryColor:(UIColor *)primaryColor + withContentStyle:(UIContentStyle)contentStyle { + + if (contentStyle == UIContentStyleContrast) { + + if ([ContrastColor(primaryColor, YES) isEqual:FlatWhite]) { + [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent]; + } else { + [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault]; + } + + } else if (contentStyle == UIContentStyleLight) { + + [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent]; + + } else { + + [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault]; + } + + [[self class] customizeBarButtonItemWithPrimaryColor:primaryColor contentStyle:contentStyle]; + [[self class] customizeButtonWithPrimaryColor:primaryColor withContentStyle:contentStyle]; + [[self class] customizeNavigationBarWithPrimaryColor:primaryColor withContentStyle:contentStyle]; + [[self class] customizePageControlWithPrimaryColor:primaryColor withContentStyle:contentStyle]; + [[self class] customizeProgressViewWithPrimaryColor:primaryColor withContentStyle:contentStyle]; + [[self class] customizeSearchBarWithPrimaryColor:primaryColor withContentStyle:contentStyle]; + [[self class] customizeSegmentedControlWithPrimaryColor:primaryColor withContentStyle:contentStyle]; + [[self class] customizeSliderWithPrimaryColor:primaryColor withContentStyle:contentStyle]; + [[self class] customizeStepperWithPrimaryColor:primaryColor withContentStyle:contentStyle]; + [[self class] customizeSwitchWithPrimaryColor:primaryColor]; + [[self class] customizeTabBarWithBarTintColor:FlatWhite andTintColor:primaryColor]; + [[self class] customizeToolbarWithPrimaryColor:primaryColor withContentStyle:contentStyle]; + [[self class] customizeImagePickerControllerWithPrimaryColor:primaryColor withContentStyle:contentStyle]; +} + + ++ (void)setGlobalThemeUsingPrimaryColor:(UIColor *)primaryColor + withSecondaryColor:(UIColor *)secondaryColor + andContentStyle:(UIContentStyle)contentStyle { + + if (contentStyle == UIContentStyleContrast) { + + if ([ContrastColor(primaryColor, YES) isEqual:FlatWhite]) { + [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent]; + } else { + [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault]; + } + + } else if (contentStyle == UIContentStyleLight) { + + [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent]; + + } else { + + [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault]; + } + + [[self class] customizeBarButtonItemWithPrimaryColor:primaryColor contentStyle:contentStyle]; + [[self class] customizeButtonWithPrimaryColor:primaryColor secondaryColor:secondaryColor withContentStyle:contentStyle]; + [[self class] customizeNavigationBarWithPrimaryColor:primaryColor withContentStyle:contentStyle]; + [[self class] customizePageControlWithPrimaryColor:primaryColor withContentStyle:contentStyle]; + [[self class] customizeProgressViewWithPrimaryColor:primaryColor andSecondaryColor:secondaryColor]; + [[self class] customizeSearchBarWithPrimaryColor:primaryColor withContentStyle:contentStyle]; + [[self class] customizeSegmentedControlWithPrimaryColor:primaryColor withContentStyle:contentStyle]; + [[self class] customizeSliderWithPrimaryColor:primaryColor andSecondaryColor:secondaryColor]; + [[self class] customizeStepperWithPrimaryColor:primaryColor withContentStyle:contentStyle]; + [[self class] customizeSwitchWithPrimaryColor:primaryColor andSecondaryColor:secondaryColor]; + [[self class] customizeTabBarWithBarTintColor:FlatWhite andTintColor:primaryColor]; + [[self class] customizeToolbarWithPrimaryColor:primaryColor withContentStyle:contentStyle]; + [[self class] customizeImagePickerControllerWithPrimaryColor:primaryColor withContentStyle:contentStyle]; +} + ++ (void)setGlobalThemeUsingPrimaryColor:(UIColor *)primaryColor + withSecondaryColor:(UIColor *)secondaryColor + usingFontName:(NSString *)fontName + andContentStyle:(UIContentStyle)contentStyle { + + if (contentStyle == UIContentStyleContrast) { + + if ([ContrastColor(primaryColor, YES) isEqual:FlatWhite]) { + [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent]; + } else { + [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault]; + } + + } else if (contentStyle == UIContentStyleLight) { + + [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent]; + + } else { + + [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault]; + } + + [[UILabel appearance] setSubstituteFontName:fontName]; + [[UIButton appearance] setSubstituteFontName:fontName]; + + [[self class] customizeNavigationBarWithBarColor:primaryColor textColor:ContrastColor(primaryColor, YES) fontName:fontName fontSize:20 buttonColor:ContrastColor(primaryColor, YES)]; + [[self class] customizeBarButtonItemWithPrimaryColor:primaryColor fontName:fontName fontSize:18 contentStyle:contentStyle]; + [[self class] customizeSegmentedControlWithPrimaryColor:primaryColor withFontName:fontName withFontSize:14 withContentStyle:contentStyle]; + [[self class] customizeButtonWithPrimaryColor:primaryColor secondaryColor:secondaryColor withContentStyle:contentStyle]; + [[self class] customizePageControlWithPrimaryColor:primaryColor withContentStyle:contentStyle]; + [[self class] customizeProgressViewWithPrimaryColor:primaryColor andSecondaryColor:secondaryColor]; + [[self class] customizeSearchBarWithPrimaryColor:primaryColor withContentStyle:contentStyle]; + [[self class] customizeSliderWithPrimaryColor:primaryColor andSecondaryColor:secondaryColor]; + [[self class] customizeStepperWithPrimaryColor:primaryColor withContentStyle:contentStyle]; + [[self class] customizeSwitchWithPrimaryColor:primaryColor andSecondaryColor:secondaryColor]; + [[self class] customizeTabBarWithBarTintColor:FlatWhite andTintColor:primaryColor]; + [[self class] customizeToolbarWithPrimaryColor:primaryColor withContentStyle:contentStyle]; + [[self class] customizeImagePickerControllerWithPrimaryColor:primaryColor withContentStyle:contentStyle]; + + /* + + if (contentStyle == UIContentStyleContrast) { + + if ([ContrastColor(primaryColor, YES) isEqual:FlatWhite]) { + [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent]; + } else { + [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault]; + } + + } else if (contentStyle == UIContentStyleLight) { + + [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent]; + + } else { + + [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault]; + } + + [[self class] customizeBarButtonItemWithPrimaryColor:primaryColor fontName:fontName fontSize:18 contentStyle:contentStyle]; + [[self class] customizeButtonWithPrimaryColor:primaryColor fontName:fontName fontSize:17 contentStyle:contentStyle]; + [[self class] customizeLabelWithPrimaryColor:primaryColor fontName:fontName fontSize:18 withContentStyle:contentStyle]; + [[self class] customizePageControlWithPrimaryColor:primaryColor withContentStyle:contentStyle]; + [[self class] customizeProgressViewWithPrimaryColor:primaryColor andSecondaryColor:secondaryColor]; + [[self class] customizeSearchBarWithPrimaryColor:primaryColor withContentStyle:contentStyle]; + [[self class] customizeSliderWithPrimaryColor:primaryColor andSecondaryColor:secondaryColor]; + [[self class] customizeStepperWithPrimaryColor:primaryColor withContentStyle:contentStyle]; + [[self class] customizeSwitchWithPrimaryColor:primaryColor andSecondaryColor:secondaryColor]; + [[self class] customizeTabBarWithBarTintColor:FlatWhite tintColor:primaryColor fontName:fontName fontSize:11]; + [[self class] customizeToolbarWithPrimaryColor:primaryColor withContentStyle:contentStyle]; + + */ +} + +#pragma mark - UIBarButtonItem + ++ (void)customizeBarButtonItemWithPrimaryColor:(UIColor *)primaryColor + contentStyle:(UIContentStyle)contentStyle { + + UIColor *contentColor; + switch (contentStyle) { + case UIContentStyleContrast: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + case UIContentStyleLight: { + contentColor = [UIColor whiteColor]; + break; + } + case UIContentStyleDark: { + contentColor = FlatBlackDark; + break; + } + default: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + } + + [[UIBarButtonItem appearance] setTintColor:primaryColor]; + [[UIBarButtonItem appearanceWhenContainedIn:[UISearchBar class], nil] setTintColor:contentColor]; + [[UIBarButtonItem appearanceWhenContainedIn:[UINavigationBar class], nil] setTintColor:contentColor]; + [[UIBarButtonItem appearanceWhenContainedIn:[UIToolbar class], nil] setTintColor:contentColor]; + + +} + ++ (void)customizeBarButtonItemWithPrimaryColor:(UIColor *)primaryColor + fontName:(NSString *)fontName + fontSize:(float)fontSize + contentStyle:(UIContentStyle)contentStyle { + + UIColor *contentColor; + switch (contentStyle) { + case UIContentStyleContrast: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + case UIContentStyleLight: { + contentColor = [UIColor whiteColor]; + break; + } + case UIContentStyleDark: { + contentColor = FlatBlackDark; + break; + } + default: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + } + + [[UIBarButtonItem appearance] setTintColor:primaryColor]; + [[UIBarButtonItem appearanceWhenContainedIn:[UISearchBar class], nil] setTintColor:contentColor]; + [[UIBarButtonItem appearanceWhenContainedIn:[UINavigationBar class], nil] setTintColor:contentColor]; + [[UIBarButtonItem appearanceWhenContainedIn:[UIToolbar class], nil] setTintColor:contentColor]; + + + if ([UIFont fontWithName:fontName size:fontSize]) { + [[UIBarButtonItem appearanceWhenContainedIn:[UINavigationBar class], nil] setTitleTextAttributes:@{ NSForegroundColorAttributeName:contentColor, + NSFontAttributeName:[UIFont fontWithName:fontName size:fontSize]} forState:UIControlStateNormal]; + } +} + +#pragma mark - UIButton + ++ (void)customizeButtonWithPrimaryColor:(UIColor *)primaryColor + withContentStyle:(UIContentStyle)contentStyle { + + UIColor *contentColor; + switch (contentStyle) { + case UIContentStyleContrast: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + case UIContentStyleLight: { + contentColor = [UIColor whiteColor]; + break; + } + case UIContentStyleDark: { + contentColor = FlatBlackDark; + break; + } + default: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + } + + [[UIButton appearance] setTintColor:contentColor]; + [[UIButton appearance] setBackgroundColor:primaryColor]; + + [[UIButton appearanceWhenContainedIn:[UISearchBar class], nil] setTintColor:contentColor]; + [[UIButton appearanceWhenContainedIn:[UISearchBar class], nil] setBackgroundColor:ClearColor]; + + [[UIButton appearanceWhenContainedIn:[UINavigationBar class], nil] setTintColor:contentColor]; + [[UIButton appearanceWhenContainedIn:[UINavigationBar class], nil] setBackgroundColor:ClearColor]; + + [[UIButton appearanceWhenContainedIn:[UIToolbar class], nil] setTintColor:contentColor]; + [[UIButton appearanceWhenContainedIn:[UIToolbar class], nil] setBackgroundColor:ClearColor]; + + [[UIButton appearanceWhenContainedIn:[UIStepper class], nil] setTintColor:primaryColor]; + [[UIButton appearanceWhenContainedIn:[UIStepper class], nil] setBackgroundColor:ClearColor]; + + [[UIButton appearance] setTitleShadowColor:ClearColor forState:UIControlStateNormal]; +} + ++ (void)customizeButtonWithPrimaryColor:(UIColor *)primaryColor + secondaryColor:(UIColor *)secondaryColor + withContentStyle:(UIContentStyle)contentStyle { + + UIColor *contentColor; + UIColor *secondaryContentColor; + switch (contentStyle) { + case UIContentStyleContrast: { + contentColor = ContrastColor(primaryColor, NO); + secondaryContentColor = ContrastColor(secondaryColor, NO); + break; + } + case UIContentStyleLight: { + contentColor = [UIColor whiteColor]; + secondaryContentColor = [UIColor whiteColor]; + break; + } + case UIContentStyleDark: { + contentColor = FlatBlackDark; + secondaryContentColor = FlatBlackDark; + break; + } + default: { + contentColor = ContrastColor(primaryColor, NO); + secondaryContentColor = ContrastColor(secondaryColor, NO); + break; + } + } + + [[UIButton appearance] setTintColor:secondaryContentColor]; + [[UIButton appearance] setBackgroundColor:secondaryColor]; + + [[UIButton appearanceWhenContainedIn:[UISearchBar class], nil] setTintColor:contentColor]; + [[UIButton appearanceWhenContainedIn:[UISearchBar class], nil] setBackgroundColor:ClearColor]; + + [[UIButton appearanceWhenContainedIn:[UINavigationBar class], nil] setTintColor:contentColor]; + [[UIButton appearanceWhenContainedIn:[UINavigationBar class], nil] setBackgroundColor:ClearColor]; + + [[UIButton appearanceWhenContainedIn:[UIToolbar class], nil] setTintColor:contentColor]; + [[UIButton appearanceWhenContainedIn:[UIToolbar class], nil] setBackgroundColor:ClearColor]; + + [[UIButton appearanceWhenContainedIn:[UIStepper class], nil] setTintColor:primaryColor]; + [[UIButton appearanceWhenContainedIn:[UIStepper class], nil] setBackgroundColor:ClearColor]; + + [[UIButton appearance] setTitleShadowColor:ClearColor forState:UIControlStateNormal]; +} + +#pragma mark - UIImagePickerController + ++ (void)customizeImagePickerControllerWithPrimaryColor:(UIColor *)primaryColor withContentStyle:(UIContentStyle)contentStyle { + + UIColor *contentColor; + switch (contentStyle) { + case UIContentStyleContrast: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + case UIContentStyleLight: { + contentColor = [UIColor whiteColor]; + break; + } + case UIContentStyleDark: { + contentColor = FlatBlackDark; + break; + } + default: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + } + + //Workaround for Swift http://stackoverflow.com/a/28765193 + [[UIButton appearanceWhenContainedWithin:@[[UIView class],[UIImagePickerController class]]] setBackgroundColor:ClearColor]; + [[UIButton appearanceWhenContainedWithin:@[[UIView class],[UIImagePickerController class]]] setTintColor:ClearColor]; + [[UIButton appearanceWhenContainedWithin:@[[UINavigationBar class],[UIImagePickerController class]]] setBackgroundColor:ClearColor]; + [[UIButton appearanceWhenContainedWithin:@[[UINavigationBar class],[UIImagePickerController class]]] setTintColor:contentColor]; + [[UIButton appearanceWhenContainedWithin:@[[UITableViewCell class],[UIImagePickerController class]]] setBackgroundColor:ClearColor]; + + //[[UIButton appearanceWhenContainedInInstancesOfClasses:@[[UIView class],[UIImagePickerController class]]] setBackgroundColor:ClearColor]; + //[[UIButton appearanceWhenContainedInInstancesOfClasses:@[[UIView class],[UIImagePickerController class]]] setTintColor:contentColor]; + //[[UIButton appearanceWhenContainedInInstancesOfClasses:@[[UINavigationBar class],[UIImagePickerController class]]] setBackgroundColor:ClearColor]; + //[[UIButton appearanceWhenContainedInInstancesOfClasses:@[[UINavigationBar class],[UIImagePickerController class]]] setTintColor:contentColor]; + //[[UIButton appearanceWhenContainedInInstancesOfClasses:@[[UITableViewCell class],[UIImagePickerController class]]] setBackgroundColor:ClearColor]; +} + + +#pragma mark - UILabel + ++ (void)customizeLabelWithPrimaryColor:(UIColor *)primaryColor + fontName:(NSString *)fontName + fontSize:(CGFloat)fontSize + withContentStyle:(UIContentStyle)contentStyle { + + UIColor *contentColor; + switch (contentStyle) { + case UIContentStyleContrast: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + case UIContentStyleLight: { + contentColor = [UIColor whiteColor]; + break; + } + case UIContentStyleDark: { + contentColor = FlatBlackDark; + break; + } + default: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + } + + [[UILabel appearanceWhenContainedIn:[UINavigationBar class], nil] setTextColor:contentColor]; + [[UILabel appearanceWhenContainedIn:[UIToolbar class], nil] setTextColor:contentColor]; + + UIFont *font = [UIFont fontWithName:fontName size:fontSize]; + + if (font) { + [[UILabel appearance] setFont:[UIFont fontWithName:fontName size:fontSize]]; + [[UILabel appearanceWhenContainedIn:[UITextField class], nil] setFont:[UIFont fontWithName:fontName size:14]]; + [[UILabel appearanceWhenContainedIn:[UIButton class], nil] setFont:[UIFont fontWithName:fontName size:18]]; + } +} + +#pragma mark - UINavigationBar + ++ (void)customizeNavigationBarWithPrimaryColor:(UIColor *)primaryColor + withContentStyle:(UIContentStyle)contentStyle { + + UIColor *contentColor; + switch (contentStyle) { + case UIContentStyleContrast: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + case UIContentStyleLight: { + contentColor = [UIColor whiteColor]; + break; + } + case UIContentStyleDark: { + contentColor = FlatBlackDark; + break; + } + default: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + } + + [[UINavigationBar appearance] setBarTintColor:primaryColor]; + [[UINavigationBar appearance] setTintColor:contentColor]; + [[UINavigationBar appearance] setTitleTextAttributes:@{NSForegroundColorAttributeName:contentColor}]; + [[UINavigationBar appearance] setShadowImage:[UIImage new]]; + // [[UINavigationBar appearance] setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault]; +} + ++ (void)customizeNavigationBarWithBarColor:(UIColor *)barColor + textColor:(UIColor *)textColor + buttonColor:(UIColor *)buttonColor { + + [[UINavigationBar appearance] setBarTintColor:barColor]; + [[UINavigationBar appearance] setTintColor:buttonColor]; + [[UINavigationBar appearance] setTitleTextAttributes:@{NSForegroundColorAttributeName:textColor}]; + [[UINavigationBar appearance] setShadowImage:[UIImage new]]; + // [[UINavigationBar appearance] setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault]; +} + ++ (void)customizeNavigationBarWithBarColor:(UIColor *)barColor + textColor:(UIColor *)textColor + fontName:(NSString *)fontName + fontSize:(CGFloat)fontSize + buttonColor:(UIColor *)buttonColor { + + [[UINavigationBar appearance] setBarTintColor:barColor]; + [[UINavigationBar appearance] setTintColor:buttonColor]; + [[UINavigationBar appearance] setShadowImage:[UIImage new]]; + // [[UINavigationBar appearance] setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault]; + + if ([UIFont fontWithName:fontName size:fontSize]) { + [[UINavigationBar appearance] setTitleTextAttributes:@{ NSForegroundColorAttributeName:textColor, NSFontAttributeName:[UIFont fontWithName:fontName size:fontSize] }]; + } +} + +#pragma mark - UIPageControl + ++ (void)customizePageControlWithPrimaryColor:(UIColor *)primaryColor + withContentStyle:(UIContentStyle)contentStyle { + + UIColor *contentColor; + switch (contentStyle) { + case UIContentStyleContrast: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + case UIContentStyleLight: { + contentColor = [UIColor whiteColor]; + break; + } + case UIContentStyleDark: { + contentColor = FlatBlackDark; + break; + } + default: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + } + + [[UIPageControl appearance] setCurrentPageIndicatorTintColor:primaryColor]; + [[UIPageControl appearance] setPageIndicatorTintColor:[primaryColor colorWithAlphaComponent:0.4]]; + [[UIPageControl appearanceWhenContainedIn:[UINavigationBar class], nil] setCurrentPageIndicatorTintColor:contentColor]; + [[UIPageControl appearanceWhenContainedIn:[UINavigationBar class], nil] setPageIndicatorTintColor:[contentColor colorWithAlphaComponent:0.4]]; + [[UIPageControl appearanceWhenContainedIn:[UIToolbar class], nil] setCurrentPageIndicatorTintColor:contentColor]; + [[UIPageControl appearanceWhenContainedIn:[UIToolbar class], nil] setPageIndicatorTintColor:[contentColor colorWithAlphaComponent:0.4]]; +} + +#pragma mark - UIProgressView + ++ (void)customizeProgressViewWithPrimaryColor:(UIColor *)primaryColor + withContentStyle:(UIContentStyle)contentStyle { + + UIColor *contentColor; + switch (contentStyle) { + case UIContentStyleContrast: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + case UIContentStyleLight: { + contentColor = [UIColor whiteColor]; + break; + } + case UIContentStyleDark: { + contentColor = FlatBlackDark; + break; + } + default: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + } + + [[UIProgressView appearance] setProgressTintColor:primaryColor]; + [[UIProgressView appearanceWhenContainedIn:[UINavigationBar class], nil] setProgressTintColor:contentColor]; + [[UIProgressView appearanceWhenContainedIn:[UIToolbar class], nil] setProgressTintColor:contentColor]; + [[UIProgressView appearance] setTrackTintColor:[UIColor lightGrayColor]]; + [[UIProgressView appearanceWhenContainedIn:[UINavigationBar class], nil] setTrackTintColor:[[primaryColor darkenByPercentage:0.25] flatten]]; + [[UIProgressView appearanceWhenContainedIn:[UIToolbar class], nil] setTrackTintColor:[[primaryColor darkenByPercentage:0.25] flatten]]; +} + ++ (void)customizeProgressViewWithPrimaryColor:(UIColor *)primaryColor + andSecondaryColor:(UIColor *)secondaryColor { + + [[UIProgressView appearance] setProgressTintColor:secondaryColor]; + [[UIProgressView appearanceWhenContainedIn:[UINavigationBar class], nil] setProgressTintColor:secondaryColor]; + [[UIProgressView appearanceWhenContainedIn:[UIToolbar class], nil] setProgressTintColor:secondaryColor]; + [[UIProgressView appearance] setTrackTintColor:[UIColor lightGrayColor]]; + [[UIProgressView appearanceWhenContainedIn:[UINavigationBar class], nil] setTrackTintColor:[[primaryColor darkenByPercentage:0.25] flatten]]; + [[UIProgressView appearanceWhenContainedIn:[UIToolbar class], nil] setTrackTintColor:[[primaryColor darkenByPercentage:0.25] flatten]]; +} + +#pragma mark - UISearchBar + ++ (void)customizeSearchBarWithPrimaryColor:(UIColor *)primaryColor withContentStyle:(UIContentStyle)contentStyle { + + UIColor *contentColor; + switch (contentStyle) { + case UIContentStyleContrast: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + case UIContentStyleLight: { + contentColor = [UIColor whiteColor]; + break; + } + case UIContentStyleDark: { + contentColor = FlatBlackDark; + break; + } + default: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + } + + [[UISearchBar appearance] setBarTintColor:primaryColor]; + [[UISearchBar appearance] setBackgroundColor:primaryColor]; + [[UISearchBar appearance] setTintColor:contentColor]; + [[UISearchBar appearance] setBackgroundImage:[UIImage new] forBarPosition:UIBarPositionAny barMetrics:UIBarMetricsDefault]; +} + +#pragma mark - UISegmentedControl + ++ (void)customizeSegmentedControlWithPrimaryColor:(UIColor *)primaryColor + withContentStyle:(UIContentStyle)contentStyle { + + UIColor *contentColor; + switch (contentStyle) { + case UIContentStyleContrast: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + case UIContentStyleLight: { + contentColor = [UIColor whiteColor]; + break; + } + case UIContentStyleDark: { + contentColor = FlatBlackDark; + break; + } + default: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + } + + [[UISegmentedControl appearance] setTintColor:primaryColor]; + [[UISegmentedControl appearanceWhenContainedIn:[UINavigationBar class], nil] + setTintColor:contentColor]; + [[UISegmentedControl appearanceWhenContainedIn:[UIToolbar class], nil] + setTintColor:contentColor]; +} + ++ (void)customizeSegmentedControlWithPrimaryColor:(UIColor *)primaryColor + withFontName:(NSString *)fontName + withFontSize:(CGFloat)fontSize + withContentStyle:(UIContentStyle)contentStyle { + + UIColor *contentColor; + switch (contentStyle) { + case UIContentStyleContrast: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + case UIContentStyleLight: { + contentColor = [UIColor whiteColor]; + break; + } + case UIContentStyleDark: { + contentColor = FlatBlackDark; + break; + } + default: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + } + + [[UISegmentedControl appearance] setTintColor:primaryColor]; + [[UISegmentedControl appearanceWhenContainedIn:[UINavigationBar class], nil] + setTintColor:contentColor]; + [[UISegmentedControl appearanceWhenContainedIn:[UIToolbar class], nil] + setTintColor:contentColor]; + + UIFont *font = [UIFont fontWithName:fontName size:fontSize]; + if (font) { + [[UISegmentedControl appearance] setTitleTextAttributes:@{NSFontAttributeName:font} + forState:UIControlStateNormal]; + } +} + +#pragma mark - UISlider + ++ (void)customizeSliderWithPrimaryColor:(UIColor *)primaryColor + withContentStyle:(UIContentStyle)contentStyle { + + UIColor *contentColor; + switch (contentStyle) { + case UIContentStyleContrast: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + case UIContentStyleLight: { + contentColor = [UIColor whiteColor]; + break; + } + case UIContentStyleDark: { + contentColor = FlatBlackDark; + break; + } + default: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + } + + [[UISlider appearance] setMinimumTrackTintColor:primaryColor]; + [[UISlider appearanceWhenContainedIn:[UINavigationBar class], nil] setMinimumTrackTintColor:contentColor]; + [[UISlider appearanceWhenContainedIn:[UIToolbar class], nil] setMinimumTrackTintColor:contentColor]; + [[UISlider appearance] setMaximumTrackTintColor:[UIColor lightGrayColor]]; + [[UISlider appearanceWhenContainedIn:[UINavigationBar class], nil] setMaximumTrackTintColor:[[primaryColor darkenByPercentage:0.25] flatten]]; + [[UISlider appearanceWhenContainedIn:[UIToolbar class], nil] setMaximumTrackTintColor:[[primaryColor darkenByPercentage:0.25] flatten]]; + + [[UISlider appearance] setThumbTintColor:primaryColor]; + [[UISlider appearanceWhenContainedIn:[UIToolbar class], nil] setThumbTintColor:contentColor]; +} + ++ (void)customizeSliderWithPrimaryColor:(UIColor *)primaryColor + andSecondaryColor:(UIColor *)secondaryColor { + + [[UISlider appearance] setMinimumTrackTintColor:secondaryColor]; + [[UISlider appearanceWhenContainedIn:[UINavigationBar class], nil] setMinimumTrackTintColor:secondaryColor]; + [[UISlider appearanceWhenContainedIn:[UIToolbar class], nil] setMinimumTrackTintColor:secondaryColor]; + [[UISlider appearance] setMaximumTrackTintColor:[UIColor lightGrayColor]]; + [[UISlider appearanceWhenContainedIn:[UINavigationBar class], nil] setMaximumTrackTintColor:[[primaryColor darkenByPercentage:0.25] flatten]]; + [[UISlider appearanceWhenContainedIn:[UIToolbar class], nil] setMaximumTrackTintColor:[[primaryColor darkenByPercentage:0.25] flatten]]; + + [[UISlider appearance] setThumbTintColor:secondaryColor]; + [[UISlider appearanceWhenContainedIn:[UIToolbar class], nil] setThumbTintColor:ContrastColor(primaryColor, NO)]; +} + +#pragma mark - UIStepper + ++ (void)customizeStepperWithPrimaryColor:(UIColor *)primaryColor + withContentStyle:(UIContentStyle)contentStyle { + + UIColor *contentColor; + switch (contentStyle) { + case UIContentStyleContrast: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + case UIContentStyleLight: { + contentColor = [UIColor whiteColor]; + break; + } + case UIContentStyleDark: { + contentColor = FlatBlackDark; + break; + } + default: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + } + + [[UIStepper appearance] setTintColor:primaryColor]; + [[UIStepper appearanceWhenContainedIn:[UINavigationBar class], nil] + setTintColor:contentColor]; + [[UIStepper appearanceWhenContainedIn:[UIToolbar class], nil] + setTintColor:contentColor]; +} + +#pragma mark - UISwitch + ++ (void)customizeSwitchWithPrimaryColor:(UIColor *)primaryColor { + + [[UISwitch appearance] setOnTintColor:primaryColor]; + [[UISwitch appearanceWhenContainedIn:[UINavigationBar class], nil] setOnTintColor:[[primaryColor darkenByPercentage:0.25] flatten]]; + [[UISwitch appearanceWhenContainedIn:[UIToolbar class], nil] setOnTintColor:[[primaryColor darkenByPercentage:0.25] flatten]]; +} + ++ (void)customizeSwitchWithPrimaryColor:(UIColor *)primaryColor + andSecondaryColor:(UIColor *)secondaryColor { + + [[UISwitch appearance] setOnTintColor:secondaryColor]; + [[UISwitch appearanceWhenContainedIn:[UINavigationBar class], nil] setOnTintColor:secondaryColor]; + [[UISwitch appearanceWhenContainedIn:[UIToolbar class], nil] setOnTintColor:secondaryColor]; +} + +#pragma mark - UITabBar + ++ (void)customizeTabBarWithBarTintColor:(UIColor *)barTintColor + andTintColor:(UIColor *)tintColor { + + [[UITabBar appearance] setBarTintColor:barTintColor]; + [[UITabBar appearance] setTintColor:tintColor]; +} + ++ (void)customizeTabBarWithBarTintColor:(UIColor *)barTintColor + tintColor:(UIColor *)tintColor + fontName:(NSString *)fontName + fontSize:(CGFloat)fontSize { + + [[UITabBar appearance] setBarTintColor:barTintColor]; + [[UITabBar appearance] setTintColor:tintColor]; + + UIFont *font = [UIFont fontWithName:fontName size:fontSize]; + if (font) { + [[UITabBarItem appearance] setTitleTextAttributes:@{NSFontAttributeName:font} + forState:UIControlStateNormal]; + } +} + +#pragma mark - UIToolbar + ++ (void)customizeToolbarWithPrimaryColor:(UIColor *)primaryColor + withContentStyle:(UIContentStyle)contentStyle { + + UIColor *contentColor; + switch (contentStyle) { + case UIContentStyleContrast: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + case UIContentStyleLight: { + contentColor = [UIColor whiteColor]; + break; + } + case UIContentStyleDark: { + contentColor = FlatBlackDark; + break; + } + default: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + } + + [[UIToolbar appearance] setTintColor:contentColor]; + [[UIToolbar appearance] setBarTintColor:primaryColor]; + [[UIToolbar appearance] setClipsToBounds:YES]; +} + +#pragma GCC diagnostic pop + +@end diff --git a/Pods/ChameleonFramework/Pod/Classes/Objective-C/NSArray+Chameleon.h b/Pods/ChameleonFramework/Pod/Classes/Objective-C/NSArray+Chameleon.h new file mode 100755 index 00000000..b74c6646 --- /dev/null +++ b/Pods/ChameleonFramework/Pod/Classes/Objective-C/NSArray+Chameleon.h @@ -0,0 +1,112 @@ + +// NSArray+Chameleon.h + +/* + + The MIT License (MIT) + + Copyright (c) 2014-2015 Vicc Alexander. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + + */ + +#import +#import + +#pragma mark - Enums + +/** + * Color schemes with which to select colors using a specified color. + * + * @since 1.0 + */ +typedef NS_ENUM(NSInteger, ColorScheme){ + /** + * Analogous color schemes use colors that are next to each other on the color wheel. They usually match well and create serene and comfortable designs. Analogous color schemes are often found in nature and are harmonious and pleasing to the eye. Make sure you have enough contrast when choosing an analogous color scheme. Choose one color to dominate, a second to support. The third color is used (along with black, white or gray) as an accent. + * + * @since 1.0 + */ + ColorSchemeAnalogous, + /** + * Colors that are opposite each other on the color wheel are considered to be complementary colors (example: red and green). The high contrast of complementary colors creates a vibrant look especially when used at full saturation. This color scheme must be managed well so it is not jarring. Complementary colors are tricky to use in large doses, but work well when you want something to stand out. Complementary colors are really bad for text. + * + * @since 1.0 + */ + ColorSchemeTriadic, + /** + * A triadic color scheme uses colors that are evenly spaced around the color wheel. Triadic color harmonies tend to be quite vibrant, even if you use pale or unsaturated versions of your hues. To use a triadic harmony successfully, the colors should be carefully balanced - let one color dominate and use the two others for accent. + * + * @since 1.0 + */ + ColorSchemeComplementary +}; + +@interface NSArray (Chameleon) + +#pragma mark - Generating Color Schemes + +/** + * Generates and creates an array of 5 color objects in the HSB colorspace from the specified color. + * + * @param colorScheme The color scheme with which to select colors using a specified color. + * @param color The specified color which the color scheme is built around. + * @param isFlatScheme Pass YES to return flat color objects. + * + * @return An array of 5 color objects in the HSB colorspace. + * + * @since 2.0 + */ ++ (NSArray *)arrayOfColorsWithColorScheme:(ColorScheme)colorScheme + usingColor:(UIColor *)color + withFlatScheme:(BOOL)isFlatScheme; + +/** + * Generates and creates an array of 5 color objects in the HSB colorspace that appear most often in a specified image. + * + * @param image The specified image which the color scheme is built around. + * @param isFlatScheme Pass YES to return flat color objects. + * + * @return An array of 5 color objects in the HSB colorspace. + * + * @since 2.0 + */ ++ (NSArray *)arrayOfColorsFromImage:(UIImage *)image + withFlatScheme:(BOOL)isFlatScheme; + +#pragma mark - Deprecated Methods + +/** + * Generates and creates an array of 5 color objects in the HSB colorspace from the specified color. + * + * @param colorScheme The color scheme with which to select colors using a specified color. + * + * @param color The specified color which the color scheme is built around. + * + * @param isFlatScheme Pass YES to return flat color objects. + * + * @return An array of 5 color objects in the HSB colorspace. + * + * @since 1.1.2 + */ ++ (NSArray *)arrayOfColorsWithColorScheme:(ColorScheme)colorScheme + with:(UIColor *)color + flatScheme:(BOOL)isFlatScheme __attribute((deprecated(" Use -arrayOfColorsWithColorScheme:usingColor:withFlatScheme: instead (First deprecated in Chameleon 2.0)."))); + +@end diff --git a/Pods/ChameleonFramework/Pod/Classes/Objective-C/NSArray+Chameleon.m b/Pods/ChameleonFramework/Pod/Classes/Objective-C/NSArray+Chameleon.m new file mode 100755 index 00000000..1e1dbe08 --- /dev/null +++ b/Pods/ChameleonFramework/Pod/Classes/Objective-C/NSArray+Chameleon.m @@ -0,0 +1,736 @@ + +// NSArray+Chameleon.m + +/* + + The MIT License (MIT) + + Copyright (c) 2014-2015 Vicc Alexander. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + + */ + +#import "NSArray+Chameleon.h" +#import "ChameleonMacros.h" +#import "UIColor+ChameleonPrivate.h" +#import "UIImage+ChameleonPrivate.h" + +@interface ChameleonCountedColor : NSObject + +@property (assign) NSUInteger count; +@property (strong) UIColor *color; + +- (id)initWithColor:(UIColor *)color count:(NSUInteger)count; + +@end + +@implementation NSArray (Chameleon) + +#pragma mark - Deprecated 2.0 + ++ (NSArray *)arrayOfColorsWithColorScheme:(ColorScheme)colorScheme with:(UIColor *)color flatScheme:(BOOL)isFlatScheme { + + //Extract HSB values from input color + CGFloat h, s, b, a; + [color getHue:&h saturation:&s brightness:&b alpha:&a]; + + //Multiply our values by the max value to convert + h *= 360; + s *= 100; + b *= 100; + + //Choose Between Schemes + switch (colorScheme) { + case ColorSchemeAnalogous: + return [self analogousColorSchemeFromHue:h Saturation:s Brightness:b flat:isFlatScheme]; + case ColorSchemeComplementary: + return [self complementaryColorSchemeFromHue:h Saturation:s Brightness:b flat:isFlatScheme]; + case ColorSchemeTriadic: + return [self triadicColorSchemeFromHue:h Saturation:s Brightness:b flat:isFlatScheme]; + default: + NSAssert(0, @"Oops! Unrecognized color scheme provided as random color."); + } +} + +#pragma mark - Chameleon - Public Color Scheme Methods + ++ (NSArray *)arrayOfColorsWithColorScheme:(ColorScheme)colorScheme usingColor:(UIColor *)color withFlatScheme:(BOOL)isFlatScheme { + + //Extract HSB values from input color + CGFloat h, s, b, a; + [color getHue:&h saturation:&s brightness:&b alpha:&a]; + + //Multiply our values by the max value to convert + h *= 360; + s *= 100; + b *= 100; + + //Choose Between Schemes + switch (colorScheme) { + case ColorSchemeAnalogous: + if (isFlatScheme) return [self analogousColorSchemeFromHue:h Saturation:s Brightness:b flat:YES]; + else return [self analogousColorSchemeFromHue:h Saturation:s Brightness:b flat:NO]; + case ColorSchemeComplementary: + if (isFlatScheme) return [self complementaryColorSchemeFromHue:h Saturation:s Brightness:b flat:YES]; + else return [self complementaryColorSchemeFromHue:h Saturation:s Brightness:b flat:NO]; + case ColorSchemeTriadic: + if (isFlatScheme) return [self triadicColorSchemeFromHue:h Saturation:s Brightness:b flat:YES]; + else return [self triadicColorSchemeFromHue:h Saturation:s Brightness:b flat:NO]; + default: + NSAssert(0, @"Oops! Unrecognized color scheme provided as random color."); + } +} + ++ (NSArray *)arrayOfColorsFromImage:(UIImage *)image withFlatScheme:(BOOL)isFlatScheme { + + //Quick return in case we don't have an image + if (!image) { + + //Make sure we return some colors to prevent exception + NSMutableArray *emptyColors = [NSMutableArray array]; + while (emptyColors.count < 5) { + [emptyColors addObject:[UIColor whiteColor]]; + } + + return emptyColors; + } + + //Scale image + UIImage *scaledImage = [UIImage imageWithImage:image scaledToSize:CGSizeMake(image.size.width/8, image.size.height/8)]; + NSMutableArray *finalColors = [NSMutableArray array]; + + //Find colors in image ********************************* + + //Get dimensions of image in pixels + size_t width = CGImageGetWidth(scaledImage.CGImage); + size_t height = CGImageGetHeight(scaledImage.CGImage); + + //Initialize a counted set with the correct capacity + NSCountedSet *imageColors = [[NSCountedSet alloc] initWithCapacity:(width * height)]; + + //Loop through each column + for (NSUInteger x = 0; x < width; x++) { + + //Loop through each row + for (NSUInteger y = 0; y < height; y++) { + + //Get color at a specific point + UIColor *color = [UIColor colorFromImage:scaledImage atPoint:CGPointMake(x, y)]; + + //Add color to our list of all pixel colors + [imageColors addObject:color]; + } + } + + //Setup up an enumerator object + NSEnumerator *enumerator = [imageColors objectEnumerator]; + UIColor *currentColor; + NSMutableArray *sortedColors = [NSMutableArray arrayWithCapacity:imageColors.count]; + NSMutableArray *resultColors = [NSMutableArray array]; + + //Enumerate through each object once + while ((currentColor = [enumerator nextObject]) != nil) { + + //Set a minimum allowed saturation + currentColor = [currentColor colorWithMinimumSaturation:0.15f]; + + //Get color count + NSUInteger colorCount = [imageColors countForObject:currentColor]; + + //Add them to our sortedColors array + [sortedColors addObject:[[ChameleonCountedColor alloc] initWithColor:currentColor count:colorCount]]; + } + + //Sort Colors + [sortedColors sortUsingSelector:@selector(compare:)]; + + //Loop through our sorted colors + for (ChameleonCountedColor *countedColor in sortedColors) { + + //Define our current color + currentColor = countedColor.color; + + //Setup a flag to see if we should continue counting + BOOL continueFlag = NO; + + //Loop through our colors + for (UIColor *otherColor in resultColors) { + + //If our current color differs from our last, break the loop + if (![currentColor isDistinct:otherColor]) { + continueFlag = YES; + break; + } + } + + //Continue + if (continueFlag) { + continue; + } + + //If we can still add more colors, do so + if (resultColors.count < 5) { + + //Check if we should flatten our color + if (isFlatScheme) { + [resultColors addObject:[currentColor flatten]]; + } else { + [resultColors addObject:currentColor]; + } + + } else { + break; + } + + } + + //Get colors from image + [finalColors addObjectsFromArray:[NSArray arrayWithArray:resultColors]]; + + // ***************************************************** + + //Make sure we add white colors in case we're missing colors + while (finalColors.count < 5) { + [finalColors addObject:[UIColor whiteColor]]; + } + + //Return array of colors + return [NSArray arrayWithArray:finalColors]; +} + +- (NSArray *)findColorsOfImage:(UIImage *)image imageColors:(NSCountedSet * __autoreleasing *)colors { + + //Get dimensions of image in pixels + size_t width = CGImageGetWidth(image.CGImage); + size_t height = CGImageGetHeight(image.CGImage); + + //Initialize a counted set with the correct capacity + NSCountedSet *imageColors = [[NSCountedSet alloc] initWithCapacity:(width * height)]; + + //Loop through each column + for (NSUInteger x = 0; x < width; x++) { + + //Loop through each row + for (NSUInteger y = 0; y < height; y++) { + + //Get color at a specific point + UIColor *color = [UIColor colorFromImage:image atPoint:CGPointMake(x, y)]; + + //Add color to our list of all pixel colors + [imageColors addObject:color]; + } + } + + //Assign imageColors to colors + *colors = imageColors; + + //Setup up an enumerator object + NSEnumerator *enumerator = [imageColors objectEnumerator]; + UIColor *currentColor; + NSMutableArray *sortedColors = [NSMutableArray arrayWithCapacity:imageColors.count]; + NSMutableArray *resultColors = [NSMutableArray array]; + + //Enumerate through each object once + while ((currentColor = [enumerator nextObject]) != nil) { + + //Set a minimum allowed saturation + currentColor = [currentColor colorWithMinimumSaturation:0.15f]; + + //Get color count + NSUInteger colorCount = [imageColors countForObject:currentColor]; + + //Add them to our sortedColors array + [sortedColors addObject:[[ChameleonCountedColor alloc] initWithColor:currentColor count:colorCount]]; + } + + //Sort Colors + [sortedColors sortUsingSelector:@selector(compare:)]; + + //Loop through our sorted colors + for (ChameleonCountedColor *countedColor in sortedColors) { + + //Define our current color + currentColor = countedColor.color; + + //Setup a flag to see if we should continue counting + BOOL continueFlag = NO; + + //Loop through our colors + for (UIColor *c in resultColors) { + + //If our current color differs from our last, break the loop + if (![currentColor isDistinct:c]) { + continueFlag = YES; + break; + } + } + + //Continue + if (continueFlag) { + continue; + } + + //If we can still add more colors, do so + if (resultColors.count < self.count) { + + [resultColors addObject:currentColor]; + + } else { + break; + } + + } + + //Return our colors + return [NSArray arrayWithArray:resultColors]; +} + + +#pragma mark - Chameleon - Internal Color Scheme Methods + +//Creates an array with 2 analagous colors on each side of the predefined color ++ (NSArray *)analogousColorSchemeFromHue:(CGFloat)h Saturation:(CGFloat)s Brightness:(CGFloat)b flat:(BOOL)isFlat { + + UIColor *firstColor = [UIColor colorWithHue:([[self class] add:-32 to:h])/360 + saturation:(s+5)/100 + brightness:(b+5)/100 + alpha:1.0]; + + UIColor *secondColor = [UIColor colorWithHue:[[self class] add:-16 to:h]/360 + saturation:(s+5)/100 + brightness:(b+9)/100 + alpha:1.0]; + + UIColor *thirdColor = [UIColor colorWithHue:h/360 + saturation:s/100 + brightness:b/100 + alpha:1.0]; + + UIColor *fourthColor = [UIColor colorWithHue:[[self class] add:16 to:h]/360 + saturation:(s+5)/100 + brightness:(b+9)/100 + alpha:1.0]; + + UIColor *fifthColor = [UIColor colorWithHue:[[self class] add:32 to:h]/360 + saturation:(s+5)/100 + brightness:(b+5)/100 + alpha:1.0]; + + if (isFlat) { + + //Flatten colors + firstColor = [firstColor flatten]; + secondColor = [secondColor flatten]; + thirdColor = [thirdColor flatten]; + fourthColor = [fourthColor flatten]; + fifthColor = [fifthColor flatten]; + + //Make sure returned colors are unique + + //Inner Colors + if ([secondColor isEqual:thirdColor]) { + + secondColor = [[UIColor colorWithHue:[[self class] add:-48 to:h]/360 + saturation:(s+5)/100 + brightness:(b+9)/100 + alpha:1.0] flatten]; + } + + if ([thirdColor isEqual:fourthColor]) { + + fourthColor = [[UIColor colorWithHue:[[self class] add:32 to:h]/360 + saturation:(s+5)/100 + brightness:(b+9)/100 + alpha:1.0] flatten]; + } + + //Outer Colors + + if ([firstColor isEqual:secondColor]) { + + firstColor = [[UIColor colorWithHue:[[self class] add:-64 to:h]/360 + saturation:(s+5)/100 + brightness:(b+9)/100 + alpha:1.0] flatten]; + } + + if ([firstColor isEqual:thirdColor]) { + + firstColor = [[UIColor colorWithHue:[[self class] add:-96 to:h]/360 + saturation:(s+5)/100 + brightness:(b+9)/100 + alpha:1.0] darkenByPercentage:0.25]; + } + + if ([fourthColor isEqual:fifthColor]) { + fifthColor = [[UIColor colorWithHue:[[self class] add:64 to:h]/360 + saturation:(s+5)/100 + brightness:(b+9)/100 + alpha:1.0] flatten]; + } + + if ([thirdColor isEqual:fifthColor]) { + fifthColor = [[UIColor colorWithHue:[[self class] add:96 to:h]/360 + saturation:(s+5)/100 + brightness:(b+9)/100 + alpha:1.0] flatten]; + } + + } + + return @[firstColor, secondColor, thirdColor, fourthColor, fifthColor]; +} + +// Creates an array of 5 colors, both 90 degrees and 180 degrees away from the predefined colors on both sides ++ (NSArray *)complementaryColorSchemeFromHue:(CGFloat)h Saturation:(CGFloat)s Brightness:(CGFloat)b flat:(BOOL)isFlat { + + UIColor *firstColor = [UIColor colorWithHue:h/360 + saturation:(s+5)/100 + brightness:(b-30)/100 + alpha:1.0]; + + UIColor *secondColor = [UIColor colorWithHue:h/360 + saturation:(s-10)/100 + brightness:(b+9)/100 + alpha:1.0]; + + UIColor *thirdColor = [UIColor colorWithHue:h/360 + saturation:s/100 + brightness:b/100 + alpha:1.0]; + + UIColor *fourthColor = [UIColor colorWithHue:[[self class] add:180 to:h]/360 + saturation:s/100 + brightness:b/100 + alpha:1.0]; + + UIColor *fifthColor = [UIColor colorWithHue:[[self class] add:180 to:h]/360 + saturation:(s+20)/100 + brightness:(b-30)/100 + alpha:1.0]; + + + if (isFlat) { + + //Flatten colors + firstColor = [firstColor flatten]; + secondColor = [secondColor flatten]; + thirdColor = [thirdColor flatten]; + fourthColor = [fourthColor flatten]; + fifthColor = [fifthColor flatten]; + + //Make sure returned colors are unique + + //Inner Colors + if ([secondColor isEqual:thirdColor]) { + secondColor = [[secondColor darkenByPercentage:0.25] flatten]; + } + + if ([thirdColor isEqual:fourthColor]) { + fourthColor = [[fourthColor darkenByPercentage:0.25] flatten]; + } + + if ([firstColor isEqual:thirdColor]) { + firstColor = [[firstColor darkenByPercentage:0.25] flatten]; + } + + if ([fifthColor isEqual:thirdColor]) { + fifthColor = [[fifthColor darkenByPercentage:0.25] flatten]; + } + + //Outer Colors + + if ([firstColor isEqual:secondColor]) { + firstColor = [[firstColor darkenByPercentage:0.25] flatten]; + } + + + if ([fourthColor isEqual:fifthColor]) { + fifthColor = [[fifthColor darkenByPercentage:0.25] flatten]; + } + + } + + return @[firstColor, secondColor, thirdColor, fourthColor, fifthColor]; + +} + +// Creates an array of 5 colors, both 120 degrees and 240 degrees away from the predefined colors on both sides ++ (NSArray *)triadicColorSchemeFromHue:(CGFloat)h Saturation:(CGFloat)s Brightness:(CGFloat)b flat:(BOOL)isFlat { + + UIColor *firstColor = [UIColor colorWithHue:[[self class] add:120 to:h]/360 + saturation:(7*s/6)/100 + brightness:(b-5)/100 + alpha:1.0]; + + UIColor *secondColor = [UIColor colorWithHue:[[self class] add:120 to:h]/360 + saturation:s/100 + brightness:(b+9)/100 + alpha:1.0]; + + UIColor *thirdColor = [UIColor colorWithHue:h/360 + saturation:s/100 + brightness:b/100 + alpha:1.0]; + + UIColor *fourthColor = [UIColor colorWithHue:[[self class] add:240 to:h]/360 + saturation:(7*s/6)/100 + brightness:(b-5)/100 + alpha:1.0]; + + UIColor *fifthColor = [UIColor colorWithHue:[[self class] add:240 to:h]/360 + saturation:s/100 + brightness:(b-30)/100 + alpha:1.0]; + + if (isFlat) { + + //Flatten colors + firstColor = [firstColor flatten]; + secondColor = [secondColor flatten]; + thirdColor = [thirdColor flatten]; + fourthColor = [fourthColor flatten]; + fifthColor = [fifthColor flatten]; + + //Make sure returned colors are unique + + //Inner Colors + if ([secondColor isEqual:thirdColor]) { + secondColor = [[secondColor darkenByPercentage:0.25] flatten]; + } + + if ([thirdColor isEqual:fourthColor]) { + fourthColor = [[fourthColor darkenByPercentage:0.25] flatten]; + } + + if ([firstColor isEqual:thirdColor]) { + firstColor = [[firstColor darkenByPercentage:0.25] flatten]; + } + + if ([fifthColor isEqual:thirdColor]) { + fifthColor = [[fifthColor darkenByPercentage:0.25] flatten]; + } + + //Outer Colors + + if ([firstColor isEqual:secondColor]) { + firstColor = [[firstColor darkenByPercentage:0.25] flatten]; + } + + + if ([fourthColor isEqual:fifthColor]) { + fifthColor = [[fifthColor darkenByPercentage:0.25] flatten]; + } + + } + + return @[firstColor, secondColor, thirdColor, fourthColor, fifthColor]; +} + +#pragma mark - Helper Methods for Color Schemes + ++ (float)add:(float)newValue to:(float)currentValue { + + currentValue += newValue; + + //Check if currentValue exceeds 360 degrees + if (currentValue > 360) { + float offset = currentValue - 360; + return offset; + } + + else if (currentValue < 0) { + return -1 * currentValue; + } + + else { + return currentValue; + } +} + ++ (UIColor *)colorWithFlatVersionOf:(UIColor *)color { + + //Create CGFloats to hold our color values + CGFloat L, A, B, alpha; + + //Get LAB values for our color + [color getLightness:&L valueForA:&A valueForB:&B alpha:&alpha]; + + //Find the nearest flat color + return [self nearestFlatColorForL:L A:A B:B alpha:1.0]; +} + +//Array of all our colors ++ (NSArray *)flatColors { + + return @[FlatBlack, FlatBlackDark, FlatBlue, FlatBlueDark, FlatBrown, FlatBrownDark, FlatCoffee, FlatCoffeeDark, FlatForestGreen, FlatForestGreenDark, FlatGray, FlatGrayDark, FlatGreen, FlatGreenDark, FlatLime, FlatLimeDark, FlatMagenta, FlatMagentaDark, FlatMaroon, FlatMaroonDark, FlatMint, FlatMintDark, FlatNavyBlue, FlatNavyBlueDark, FlatOrange, FlatOrangeDark, FlatPink, FlatPinkDark, FlatPlum, FlatPlumDark, FlatPowderBlue, FlatPowderBlueDark, FlatPurple, FlatPurpleDark, FlatRed, FlatRedDark, FlatSand, FlatSandDark, FlatSkyBlue, FlatSkyBlueDark, FlatTeal, FlatTealDark, FlatWatermelon, FlatWatermelonDark, FlatWhite, FlatWhiteDark, FlatYellow, FlatYellowDark]; +} + +//Calculate the total sum of differences - Euclidian distance +//Chameleon is now using the CIEDE2000 formula to calculate distances between 2 colors. +//More info: http://en.wikipedia.org/wiki/Color_difference ++ (float)totalSumOfDifferencesFroml1:(CGFloat)L1 l2:(CGFloat)L2 a1:(CGFloat)A1 + a2:(CGFloat)A2 b1:(CGFloat)B1 b2:(CGFloat)B2 { + + //Get C Values in LCH from LAB Values + CGFloat C1 = sqrt(pow(A1, 2) + pow(B1, 2)); + CGFloat C2 = sqrt(pow(A2, 2) + pow(B2, 2)); + + //CIE Weights + CGFloat KL = 1; + CGFloat KC = 1; + CGFloat KH = 1; + + //Variables specifically set for CIE:2000 + CGFloat DeltaPrimeL = L2 - L1; + CGFloat MeanL = ((L1 + L2) / 2); + CGFloat MeanC = ((C1 + C2) / 2); + CGFloat A1Prime = A1 + A1 / 2 * (1 - sqrt(pow(MeanC, 7.0) / (pow(MeanC, 7.0) + pow(25.0, 7.0)))); + CGFloat A2Prime = A2 + A2 / 2 * (1 - sqrt(pow(MeanC, 7.0) / (pow(MeanC, 7.0) + pow(25.0, 7.0)))); + CGFloat C1Prime = sqrt(pow(A1Prime, 2) + pow(B1, 2)); + CGFloat C2Prime = sqrt(pow(A2Prime, 2) + pow(B2, 2)); + CGFloat DeltaPrimeC = C1Prime - C2Prime; + CGFloat DeltaC = C1 - C2; + CGFloat MeanCPrime = (C1Prime + C2Prime) / 2; + CGFloat H1Prime = fmodf(atan2(B1, A1Prime), (360.0 * M_PI/180)); + CGFloat H2Prime = fmodf(atan2(B2, A2Prime), (360.0 * M_PI/180)); + + //Run everything through our △H' Function + CGFloat hDeltaPrime = 0; + if (fabs(H1Prime - H2Prime) <= (180.0 * M_PI/180)) { + + hDeltaPrime = H2Prime - H1Prime; + + } else if (H2Prime <= H1Prime) { + + hDeltaPrime = (H2Prime - H1Prime) + ((360.0 * M_PI/180)); + + } else { + + hDeltaPrime = (H2Prime - H1Prime) - ((360.0 * M_PI/180)); + } + + CGFloat deltaHPrime = 2 * (sqrt(C1Prime*C2Prime)) * sin(hDeltaPrime/2); + + //Get Mean H' Value + CGFloat MeanHPrime = 0; + if (fabs(H1Prime-H2Prime) > (180.0 * M_PI/180)) { + + MeanHPrime = (H1Prime + H2Prime + (360.0 * M_PI/180)) / 2; + + } else { + + MeanHPrime = (H1Prime + H2Prime) / 2; + } + + CGFloat T = 1 - 0.17 * cos(MeanHPrime - (30.0 * M_PI/180)) + 0.24 * cos(2 * MeanHPrime)+0.32 * cos(3 * MeanHPrime + (6.0 * M_PI/180)) - 0.20 * cos(4 * MeanHPrime - (63.0 * M_PI/180)); + + CGFloat SL = 1 + (0.015 * pow((MeanL - 50), 2))/sqrt(20 + pow((MeanL - 50), 2)); + CGFloat SC = 1 + 0.045 * MeanCPrime; + CGFloat SH = 1 + 0.015 * MeanCPrime * T; + + CGFloat RT = -2 * sqrt(pow(MeanCPrime, 7) / (pow(MeanCPrime, 7) + pow(25.0, 7))) * sin((60.0 * M_PI/180)* exp(-1 * pow((MeanCPrime - (275.0 * M_PI/180)) / (25.0 * M_PI/180), 2))); + + + //Get total difference + CGFloat TotalDifference = sqrt(pow((DeltaPrimeL / (KL * SL)), 2) + pow((DeltaPrimeC / (KC * SC)), 2) + pow((deltaHPrime / (KH * SH)), 2) + RT * (DeltaC / (KC * SC)) * (deltaHPrime / (KH * SH))); + + return TotalDifference; +} + ++ (UIColor *)nearestFlatColorForL:(CGFloat)l1 A:(CGFloat)a1 B:(CGFloat)b1 alpha:(CGFloat)alpha{ + + //Keep track of our index + int index = 0; + + //Start with a random big number to make sure the first comparison gets saved. + float smallestDistance = 1000000; + float previousDistance = 1000000; + float currentDistance; + + //Our values + CGFloat l2, a2, b2; + + //We're interested in the color with values returning the smallest sum of total differences so we need to cross reference our input color's values with every flat color's values + for (int i=0; i<[[self flatColors] count]; i++ ) { + + //Check that index is not zero + if (i!=0 ) { + //Extract LAB values from colors in array and store it as the previous index + [[self flatColors][i - 1] getLightness:&l2 valueForA:&a2 valueForB:&b2 alpha:nil]; + + previousDistance = [self totalSumOfDifferencesFroml1:l1 l2:l2 + a1:a1 a2:a2 + b1:b1 b2:b2]; + } + + //Extract LAB values from colors in array and store it as the current index + [[self flatColors][i] getLightness:&l2 valueForA:&a2 valueForB:&b2 alpha:nil]; + + currentDistance = [self totalSumOfDifferencesFroml1:l1 l2:l2 + a1:a1 a2:a2 + b1:b1 b2:b2]; + + //We're only interested in the smallest difference + if (currentDistance < previousDistance) { + if (currentDistance < smallestDistance) { + smallestDistance = currentDistance; + index = i; + } + } + } + + + //Collect the RGB Values of the color where the smallest difference was found + CGFloat red, green, blue; + [[self flatColors][index] getRed:&red green:&green blue:&blue alpha:nil]; + + //Return the closest flat color + return rgba(red*255, green*255, blue*255, alpha); +} + +@end + +@implementation ChameleonCountedColor + +- (id)initWithColor:(UIColor *)color count:(NSUInteger)count { + + if ((self = [super init])) { + self.color = color; + self.count = count; + } + + return self; +} + +- (NSComparisonResult)compare:(ChameleonCountedColor *)object { + + if ([object isKindOfClass:[ChameleonCountedColor class]]) { + if (self.count < object.count) + return NSOrderedDescending; + else if (self.count == object.count) + return NSOrderedSame; + } + + return NSOrderedAscending; +} + + +@end diff --git a/Pods/ChameleonFramework/Pod/Classes/Objective-C/UIAppearance+Swift.h b/Pods/ChameleonFramework/Pod/Classes/Objective-C/UIAppearance+Swift.h new file mode 100755 index 00000000..2d43cebd --- /dev/null +++ b/Pods/ChameleonFramework/Pod/Classes/Objective-C/UIAppearance+Swift.h @@ -0,0 +1,17 @@ +// +// UIAppearance+Swift.h +// Chameleon +// +// Created by Vicc Alexander on 11/26/15. +// Copyright © 2015 Vicc Alexander. All rights reserved. +// + +#import + +@interface UIView (UIViewAppearance_Swift) + +// @param containers An array of Class < UIAppearanceContainer > +// http://stackoverflow.com/a/28765193 ++ (instancetype)appearanceWhenContainedWithin:(NSArray *)containers; + +@end \ No newline at end of file diff --git a/Pods/ChameleonFramework/Pod/Classes/Objective-C/UIAppearance+Swift.m b/Pods/ChameleonFramework/Pod/Classes/Objective-C/UIAppearance+Swift.m new file mode 100755 index 00000000..d0854a1d --- /dev/null +++ b/Pods/ChameleonFramework/Pod/Classes/Objective-C/UIAppearance+Swift.m @@ -0,0 +1,32 @@ +// +// UIAppearance+Swift.m +// Chameleon +// +// Created by Vicc Alexander on 11/26/15. +// Copyright © 2015 Vicc Alexander. All rights reserved. +// + +#import "UIAppearance+Swift.h" + +@implementation UIView (UIViewAppearance_Swift) + ++ (instancetype)appearanceWhenContainedWithin: (NSArray *)containers { + + NSUInteger count = containers.count; + NSAssert(count <= 10, @"The count of containers greater than 10 is not supported."); + + return [self appearanceWhenContainedIn: + count > 0 ? containers[0] : nil, + count > 1 ? containers[1] : nil, + count > 2 ? containers[2] : nil, + count > 3 ? containers[3] : nil, + count > 4 ? containers[4] : nil, + count > 5 ? containers[5] : nil, + count > 6 ? containers[6] : nil, + count > 7 ? containers[7] : nil, + count > 8 ? containers[8] : nil, + count > 9 ? containers[9] : nil, + nil]; +} + +@end diff --git a/Pods/ChameleonFramework/Pod/Classes/Objective-C/UIButton+Chameleon.h b/Pods/ChameleonFramework/Pod/Classes/Objective-C/UIButton+Chameleon.h new file mode 100755 index 00000000..c0feceaa --- /dev/null +++ b/Pods/ChameleonFramework/Pod/Classes/Objective-C/UIButton+Chameleon.h @@ -0,0 +1,15 @@ +// +// UIButton+Chameleon.h +// Chameleon +// +// Created by Vicc Alexander on 9/20/15. +// Copyright © 2015 Vicc Alexander. All rights reserved. +// + +#import + +@interface UIButton (Chameleon) + +- (void)setSubstituteFontName:(NSString *)name UI_APPEARANCE_SELECTOR; + +@end diff --git a/Pods/ChameleonFramework/Pod/Classes/Objective-C/UIButton+Chameleon.m b/Pods/ChameleonFramework/Pod/Classes/Objective-C/UIButton+Chameleon.m new file mode 100755 index 00000000..a1e896f4 --- /dev/null +++ b/Pods/ChameleonFramework/Pod/Classes/Objective-C/UIButton+Chameleon.m @@ -0,0 +1,23 @@ +// +// UIButton+Chameleon.m +// Chameleon +// +// Created by Vicc Alexander on 9/20/15. +// Copyright © 2015 Vicc Alexander. All rights reserved. +// + +#import "UIButton+Chameleon.h" + +@implementation UIButton (Chameleon) + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + +- (void)setSubstituteFontName:(NSString *)name UI_APPEARANCE_SELECTOR { + + self.font = [UIFont fontWithName:name size:self.font.pointSize]; +} + +#pragma GCC diagnostic pop + +@end diff --git a/Pods/ChameleonFramework/Pod/Classes/Objective-C/UIColor+Chameleon.h b/Pods/ChameleonFramework/Pod/Classes/Objective-C/UIColor+Chameleon.h new file mode 100755 index 00000000..22d9b7ca --- /dev/null +++ b/Pods/ChameleonFramework/Pod/Classes/Objective-C/UIColor+Chameleon.h @@ -0,0 +1,685 @@ + +// UIColor+Chameleon.h + +/* + + The MIT License (MIT) + + Copyright (c) 2014-2015 Vicc Alexander. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + + */ + +#import +#import + +#pragma mark - Enums + +/** + * Defines the gradient style and direction of the gradient color. + * + * @since 1.0 + */ +typedef NS_ENUM (NSUInteger, UIGradientStyle) { + /** + * Returns a gradual blend between colors originating at the leftmost point of an object's frame, and ending at the rightmost point of the object's frame. + * + * @since 1.0 + */ + UIGradientStyleLeftToRight, + /** + * Returns a gradual blend between colors originating at the center of an object's frame, and ending at all edges of the object's frame. NOTE: Supports a Maximum of 2 Colors. + * + * @since 1.0 + */ + UIGradientStyleRadial, + /** + * Returns a gradual blend between colors originating at the topmost point of an object's frame, and ending at the bottommost point of the object's frame. + * + * @since 1.0 + */ + UIGradientStyleTopToBottom +}; + +/** + * Defines the shade of a any flat color. + * + * @since 1.0 + */ +typedef NS_ENUM (NSInteger, UIShadeStyle) { + /** + * Returns the light shade version of a flat color. + * + * @since 1.0 + */ + UIShadeStyleLight, + /** + * Returns the dark shade version of a flat color. + * + * @since 1.0 + */ + UIShadeStyleDark +}; + + +@interface UIColor (Chameleon) + +#pragma mark - Instance Variables + +/** + * Stores an object's UIColor image if the UIColor was created using colorWithPatternImage. + * + * @since 1.0 + */ + +@property (nonatomic, strong) UIImage *gradientImage; + +#pragma mark - Quick Shorthand Macros + +// Quick & Easy Shorthand for RGB x HSB Colors +// The reason we don't import our Macro file is to prevent naming conflicts. +#define rgba(r,g,b,a) [UIColor colorWithRed:r/255.0f green:g/255.0f blue:b/255.0f alpha:a] +#define rgb(r,g,b) [UIColor colorWithRed:r/255.0f green:g/255.0f blue:b/255.0f alpha:1.0] +#define hsba(h,s,b,a) [UIColor colorWithHue:h/360.0f saturation:s/100.0f brightness:b/100.0f alpha:a] +#define hsb(h,s,b) [UIColor colorWithHue:h/360.0f saturation:s/100.0f brightness:b/100.0f alpha:1.0] + +#pragma mark - Light Shades + +/** + * Returns a flat color object whose HSB values are 0.0, 0.0, 0.17 and whose alpha value is 1.0. + * + * @return A flat UIColor object in the HSB colorspace. + */ ++ (UIColor *)flatBlackColor; + +/** + * Returns a flat color object whose HSB values are 0.62, 0.50, 0.63 and whose alpha value is 1.0. + * + * @return A flat UIColor object in the HSB colorspace. + */ ++ (UIColor *)flatBlueColor; + +/** + * Returns a flat color object whose HSB values are 0.07, 0.45, 0.37 and whose alpha value is 1.0. + * + * @return A flat UIColor object in the HSB colorspace. + */ ++ (UIColor *)flatBrownColor; + +/** + * Returns a flat color object whose HSB values are 0.07, 0.31, 0.64 and whose alpha value is 1.0. + * + * @return A flat UIColor object in the HSB colorspace. + */ ++ (UIColor *)flatCoffeeColor; + +/** + * Returns a flat color object whose HSB values are 0.38, 0.45, 0.37 and whose alpha value is 1.0. + * + * @return A flat UIColor object in the HSB colorspace. + */ ++ (UIColor *)flatForestGreenColor; + +/** + * Returns a flat color object whose HSB values are 0.51, 0.10, 0.65 and whose alpha value is 1.0. + * + * @return A flat UIColor object in the HSB colorspace. + */ ++ (UIColor *)flatGrayColor; + +/** + * Returns a flat color object whose HSB values are 0.40, 0.77, 0.80 and whose alpha value is 1.0. + * + * @return A flat UIColor object in the HSB colorspace. + */ ++ (UIColor *)flatGreenColor; + +/** + * Returns a flat color object whose HSB values are 0.21, 0.70, 0.78 and whose alpha value is 1.0. + * + * @return A flat UIColor object in the HSB colorspace. + */ ++ (UIColor *)flatLimeColor; + +/** + * Returns a flat color object whose HSB values are 0.79, 0.51, 0.71 and whose alpha value is 1.0. + * + * @return A flat UIColor object in the HSB colorspace. + */ ++ (UIColor *)flatMagentaColor; + +/** + * Returns a flat color object whose HSB values are 0.01, 0.65, 0.47 and whose alpha value is 1.0. + * + * @return A flat UIColor object in the HSB colorspace. + */ ++ (UIColor *)flatMaroonColor; + +/** + * Returns a flat color object whose HSB values are 0.47, 0.86, 0.74 and whose alpha value is 1.0. + * + * @return A flat UIColor object in the HSB colorspace. + */ ++ (UIColor *)flatMintColor; + +/** + * Returns a flat color object whose HSB values are 0.58, 0.45, 0.37 and whose alpha value is 1.0. + * + * @return A flat UIColor object in the HSB colorspace. + */ ++ (UIColor *)flatNavyBlueColor; + +/** + * Returns a flat color object whose HSB values are 0.08, 0.85, 0.90 and whose alpha value is 1.0. + * + * @return A flat UIColor object in the HSB colorspace. + */ ++ (UIColor *)flatOrangeColor; + +/** + * Returns a flat color object whose HSB values are 0.90, 0.49, 0.96 and whose alpha value is 1.0. + * + * @return A flat UIColor object in the HSB colorspace. + */ ++ (UIColor *)flatPinkColor; + +/** + * Returns a flat color object whose HSB values are 0.83, 0.45, 0.37 and whose alpha value is 1.0. + * + * @return A flat UIColor object in the HSB colorspace. + */ ++ (UIColor *)flatPlumColor; + +/** + * Returns a flat color object whose HSB values are 0.62, 0.24, 0.95 and whose alpha value is 1.0. + * + * @return A flat UIColor object in the HSB colorspace. + */ ++ (UIColor *)flatPowderBlueColor; + +/** + * Returns a flat color object whose HSB values are 0.70, 0.52, 0.77 and whose alpha value is 1.0. + * + * @return A flat UIColor object in the HSB colorspace. + */ ++ (UIColor *)flatPurpleColor; + +/** + * Returns a flat color object whose HSB values are 0.02, 0.74, 0.91 and whose alpha value is 1.0. + * + * @return A flat UIColor object in the HSB colorspace. + */ ++ (UIColor *)flatRedColor; + +/** + * Returns a flat color object whose HSB values are 0.12, 0.25, 0.94 and whose alpha value is 1.0. + * + * @return A flat UIColor object in the HSB colorspace. + */ ++ (UIColor *)flatSandColor; + +/** + * Returns a flat color object whose HSB values are 0.57, 0.76, 0.86 and whose alpha value is 1.0. + * + * @return A flat UIColor object in the HSB colorspace. + */ ++ (UIColor *)flatSkyBlueColor; + +/** + * Returns a flat color object whose HSB values are 0.54, 0.55, 0.51 and whose alpha value is 1.0. + * + * @return A flat UIColor object in the HSB colorspace. + */ ++ (UIColor *)flatTealColor; + +/** + * Returns a flat color object whose HSB values are 0.99, 0.53, 0.94 and whose alpha value is 1.0. + * + * @return A flat UIColor object in the HSB colorspace. + */ ++ (UIColor *)flatWatermelonColor; + +/** + * Returns a flat color object whose HSB values are 0.53, 0.02, 0.95 and whose alpha value is 1.0. + * + * @return A flat UIColor object in the HSB colorspace. + */ ++ (UIColor *)flatWhiteColor; + +/** + * Returns a flat color object whose HSB values are 0.13, 0.99, 1.00 and whose alpha value is 1.0. + * + * @return A flat UIColor object in the HSB colorspace. + */ ++ (UIColor *)flatYellowColor; + +#pragma mark - Dark Shades + +/** + * Returns a flat color object whose HSB values are 0.00, 0.00, 0.15 and whose alpha value is 1.0. + * + * @return A flat @c UIColor object in the HSB colorspace. + */ ++ (UIColor *)flatBlackColorDark; + +/** + * Returns a flat color object whose HSB values are 0.62, 0.56, 0.51 and whose alpha value is 1.0. + * + * @return A flat @c UIColor object in the HSB colorspace. + */ ++ (UIColor *)flatBlueColorDark; + +/** + * Returns a flat color object whose HSB values are 0.07, 0.45, 0.31 and whose alpha value is 1.0. + * + * @return A flat @c UIColor object in the HSB colorspace. + */ ++ (UIColor *)flatBrownColorDark; + +/** + * Returns a flat color object whose HSB values are 0.07, 0.34, 0.56 and whose alpha value is 1.0. + * + * @return A flat @c UIColor object in the HSB colorspace. + */ ++ (UIColor *)flatCoffeeColorDark; + +/** + * Returns a flat color object whose HSB values are 0.38, 0.44, 0.31 and whose alpha value is 1.0. + * + * @return A flat @c UIColor object in the HSB colorspace. + */ ++ (UIColor *)flatForestGreenColorDark; + +/** + * Returns a flat color object whose HSB values are 0.51, 0.10, 0.55 and whose alpha value is 1.0. + * + * @return A flat @c UIColor object in the HSB colorspace. + */ ++ (UIColor *)flatGrayColorDark; + +/** + * Returns a flat color object whose HSB values are 0.40, 0.78, 0.68 and whose alpha value is 1.0. + * + * @return A flat @c UIColor object in the HSB colorspace. + */ ++ (UIColor *)flatGreenColorDark; + +/** + * Returns a flat color object whose HSB values are 0.21, 0.81, 0.69 and whose alpha value is 1.0. + * + * @return A flat @c UIColor object in the HSB colorspace. + */ ++ (UIColor *)flatLimeColorDark; + +/** + * Returns a flat color object whose HSB values are 0.78, 0.61, 0.68 and whose alpha value is 1.0. + * + * @return A flat @c UIColor object in the HSB colorspace. + */ ++ (UIColor *)flatMagentaColorDark; + +/** + * Returns a flat color object whose HSB values are 0.01, 0.68, 0.40 and whose alpha value is 1.0. + * + * @return A flat @c UIColor object in the HSB colorspace. + */ ++ (UIColor *)flatMaroonColorDark; + +/** + * Returns a flat color object whose HSB values are 0.47, 0.86, 0.63 and whose alpha value is 1.0. + * + * @return A flat @c UIColor object in the HSB colorspace. + */ ++ (UIColor *)flatMintColorDark; + +/** + * Returns a flat color object whose HSB values are 0.58, 0.45, 0.31 and whose alpha value is 1.0. + * + * @return A flat @c UIColor object in the HSB colorspace. + */ ++ (UIColor *)flatNavyBlueColorDark; + +/** + * Returns a flat color object whose HSB values are 0.07, 1.00, 0.83 and whose alpha value is 1.0. + * + * @return A flat @c UIColor object in the HSB colorspace. + */ ++ (UIColor *)flatOrangeColorDark; + +/** + * Returns a flat color object whose HSB values are 0.91, 0.57, 0.83 and whose alpha value is 1.0. + * + * @return A flat @c UIColor object in the HSB colorspace. + */ ++ (UIColor *)flatPinkColorDark; + +/** + * Returns a flat color object whose HSB values are 0.83, 0.46, 0.31 and whose alpha value is 1.0. + * + * @return A flat @c UIColor object in the HSB colorspace. + */ ++ (UIColor *)flatPlumColorDark; + +/** + * Returns a flat color object whose HSB values are 0.62, 0.28, 0.84 and whose alpha value is 1.0. + * + * @return A flat @c UIColor object in the HSB colorspace. + */ ++ (UIColor *)flatPowderBlueColorDark; + +/** + * Returns a flat color object whose HSB values are 0.70, 0.56, 0.64 and whose alpha value is 1.0. + * + * @return A flat @c UIColor object in the HSB colorspace. + */ ++ (UIColor *)flatPurpleColorDark; + +/** + * Returns a flat color object whose HSB values are 0.02, 0.78, 0.75 and whose alpha value is 1.0. + * + * @return A flat @c UIColor object in the HSB colorspace. + */ ++ (UIColor *)flatRedColorDark; + +/** + * Returns a flat color object whose HSB values are 0.12, 0.30, 0.84 and whose alpha value is 1.0. + * + * @return A flat @c UIColor object in the HSB colorspace. + */ ++ (UIColor *)flatSandColorDark; + +/** + * Returns a flat color object whose HSB values are 0.57, 0.78, 0.73 and whose alpha value is 1.0. + * + * @return A flat @c UIColor object in the HSB colorspace. + */ ++ (UIColor *)flatSkyBlueColorDark; + +/** + * Returns a flat color object whose HSB values are 0.54, 0.54, 0.45 and whose alpha value is 1.0. + * + * @return A flat @c UIColor object in the HSB colorspace. + */ ++ (UIColor *)flatTealColorDark; + +/** + * Returns a flat color object whose HSB values are 0.99, 0.61, 0.85 and whose alpha value is 1.0. + * + * @return A flat @c UIColor object in the HSB colorspace. + */ ++ (UIColor *)flatWatermelonColorDark; + +/** + * Returns a flat color object whose HSB values are 0.57, 0.05, 0.78 and whose alpha value is 1.0. + * + * @return A flat @c UIColor object in the HSB colorspace. + */ ++ (UIColor *)flatWhiteColorDark; + +/** + * Returns a flat color object whose HSB values are 0.11, 1.00, 1.00 and whose alpha value is 1.0. + * + * @return A flat @c UIColor object in the HSB colorspace. + */ ++ (UIColor *)flatYellowColorDark; + +#pragma mark - Randomizing Colors + +/** + * Returns a randomly generated flat color object whose alpha value is 1.0. + * + * @return A flat @c UIColor object in the HSB colorspace. + * + * @since 1.0 + */ + ++ (UIColor *)randomFlatColor; + +/** + * @author Vicc Alexander + * + * Returns a randomly generated flat color object NOT found in the specified array. + * + * @param excludedColors An array specifying which colors NOT to return. + * + * @return A flat @c UIColor object in the HSB colorspace. + * + * @since 2.1.0 + */ ++ (UIColor *)colorWithRandomFlatColorExcludingColorsInArray:(NSArray *)colors; + +/** + * @author Vicc Alexander + * + * Returns a randomly generated color object found in the specified array. + * + * @param colors An array specifying which colors to return. + * + * @return A flat @c UIColor object in the HSB colorspace. + * + * @since 2.1.0 + */ ++ (UIColor *)colorWithRandomColorInArray:(NSArray *)colors; + +/** + * Returns a randomly generated flat color object with an alpha value of 1.0 in either a light or dark shade. + * + * @param shadeStyle Specifies whether the randomly generated flat color should be a light or dark shade. + * + * @return A flat @c UIColor object in the HSB colorspace. + * + * @since 1.0 + */ ++ (UIColor *)colorWithRandomFlatColorOfShadeStyle:(UIShadeStyle)shadeStyle; + +/** + * Returns a randomly generated flat color object in either a light or dark shade. + * + * @param shadeStyle Specifies whether the randomly generated flat color should be a light or dark shade. + * @param alpha The opacity. + * + * @return A flat @c UIColor object in the HSB colorspace. + * + * @since 2.0 + */ ++ (UIColor *)colorWithRandomFlatColorOfShadeStyle:(UIShadeStyle)shadeStyle withAlpha:(CGFloat)alpha; + +#pragma mark - Averaging a Color + +/** + * Returns the average color generated by averaging the colors of a specified image. + * + * @param image A specified @c UIImage. + * + * @return A flat @c UIColor object in the HSB colorspace. + * + * @since 2.0 + */ ++ (UIColor *)colorWithAverageColorFromImage:(UIImage *)image; + +/** + * Returns the average color generated by averaging the colors of a specified image. + * + * @param image A specified @c UIImage. + * @param alpha The opacity. + * + * @return A flat @c UIColor object in the HSB colorspace. + * + * @since 2.0 + */ ++ (UIColor *)colorWithAverageColorFromImage:(UIImage *)image withAlpha:(CGFloat)alpha; + +#pragma mark - Complementary Colors + +/** + * Creates and returns a complementary flat color object 180 degrees away in the HSB colorspace from the specified color. + * + * @param color The color whose complementary color is being requested. + * + * @return A flat UIColor object in the HSB colorspace. + * + * @since 1.0 + */ + ++ (UIColor *)colorWithComplementaryFlatColorOf:(UIColor *)color; + +/** + * Creates and returns a complementary flat color object 180 degrees away in the HSB colorspace from the specified color. + * + * @param color The color whose complementary color is being requested. + * @param alpha The opacity. + * + * @return A flat UIColor object in the HSB colorspace. + * + * @since 2.0 + */ + ++ (UIColor *)colorWithComplementaryFlatColorOf:(UIColor *)color withAlpha:(CGFloat)alpha; + +#pragma mark - Contrasting Colors + +/** + * Creates and returns either a black or white color object depending on which contrasts more with a specified color. + * + * @param color The specified color of the contrast color that is being requested. + * @param isFlat Pass YES to return flat color objects. + * + * @return A UIColor object in the HSB colorspace. + * + * @since 1.0 + */ + ++ (UIColor *)colorWithContrastingBlackOrWhiteColorOn:(UIColor *)backgroundColor isFlat:(BOOL)flat; + +/** + * Creates and returns either a black or white color object depending on which contrasts more with a specified color. + * + * @param color The specified color of the contrast color that is being requested. + * @param isFlat Pass YES to return flat color objects. + * @param alpha The opacity. + * + * @return A UIColor object in the HSB colorspace. + * + * @since 2.0 + */ ++ (UIColor *)colorWithContrastingBlackOrWhiteColorOn:(UIColor *)backgroundColor isFlat:(BOOL)flat alpha:(CGFloat)alpha; + +#pragma mark - Gradient Colors + +/** + * Creates and returns a gradient as a color object with an alpha value of 1.0 + * + * @param gradientStyle Specifies the style and direction of the gradual blend between colors. + * @param frame The frame rectangle, which describes the view’s location and size in its superview’s coordinate system. + * @param colors An array of color objects used to create a gradient. + * + * @return A @c UIColor object using colorWithPattern. + * + * @since 2.0 + */ ++ (UIColor *)colorWithGradientStyle:(UIGradientStyle)gradientStyle withFrame:(CGRect)frame andColors:(NSArray *)colors; + +#pragma mark - Colors from Hex Strings + +/** + * Creates and returns a @c UIColor object based on the specified hex string. + * + * @param string The hex string. + * + * @return A @c UIColor object in the RGB colorspace. + * + * + * @since 2.0 + */ ++ (UIColor *)colorWithHexString:(NSString *)string; + +/** + * Creates and returns a @c UIColor object based on the specified hex string. + * + * @param string The hex string. + * @param alpha The opacity. + * + * @return A @c UIColor object in the RGB colorspace. + * + * + * @since 2.0 + */ ++ (UIColor *)colorWithHexString:(NSString *)string withAlpha:(CGFloat)alpha; + +#pragma mark - Instance Methods + +/** + * Creates and returns a flat color object closest to the specified color in the LAB colorspace. + * + * @return A flat version of the specified @c UIColor. + * + * @since 2.0 + */ +- (UIColor *)flatten; + +/** + * Creates and returns a darker shade of a specified color in the HSB space. + * + * @param percentage The value with which to darken a specified color. + * + * @return A @c UIColor object in the HSB space. + * + * @since 2.0 + */ +- (UIColor *)darkenByPercentage:(CGFloat)percentage; + +/** + * @author Vicc Alexander + * + * Returns the hex string value for the specified color. + * + * @return An @NSString object. + * + * @since 2.1.0 + */ +- (NSString *)hexValue; + +/** + * Creates and returns a lighter shade of a specified color in the HSB space. + * + * @param percentage The value with which to lighten a specified color. + * + * @return A @c UIColor object in the HSB space. + * + * @since 2.0 + */ +- (UIColor *)lightenByPercentage:(CGFloat)percentage; + +#pragma mark - Deprecated Methods + +/** + * Creates and returns a flat color object closest to the specified color in the LAB colorspace. + * + * @param color The specified color of the flat color that is being requested. + * + * @return A flat UIColor object in the RGB colorspace. + * + * @since 1.0 + */ ++ (UIColor *)colorWithFlatVersionOf:(UIColor *)color __attribute((deprecated(" Use -flatten: instead (First deprecated in Chameleon 2.0)."))); + + +@end + diff --git a/Pods/ChameleonFramework/Pod/Classes/Objective-C/UIColor+Chameleon.m b/Pods/ChameleonFramework/Pod/Classes/Objective-C/UIColor+Chameleon.m new file mode 100755 index 00000000..934f760f --- /dev/null +++ b/Pods/ChameleonFramework/Pod/Classes/Objective-C/UIColor+Chameleon.m @@ -0,0 +1,1027 @@ + +// UIColor+Chameleon.m + +/* + + The MIT License (MIT) + + Copyright (c) 2014-2015 Vicc Alexander. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + + */ + +#import "UIColor+Chameleon.h" +#import "UIColor+ChameleonPrivate.h" +#import "ChameleonMacros.h" +#import + +@implementation UIColor (Chameleon) + +@dynamic gradientImage; + +#pragma mark - Chameleon - Getter & Setter Methods for Instance Variables + ++ (void)setGradientImage:(UIImage *)gradientImage { + + objc_setAssociatedObject(self, @selector(gradientImage), gradientImage, OBJC_ASSOCIATION_RETAIN_NONATOMIC); +} + ++ (UIImage *)gradientImage { + + return objc_getAssociatedObject(self, @selector(gradientImage)); +} + +#pragma mark - Chameleon - Light Shades + ++ (UIColor *)flatBlackColor { + return hsb(0, 0, 17); +} + ++ (UIColor *)flatBlueColor { + return hsb(224, 50, 63); +} + ++ (UIColor *)flatBrownColor { + return hsb(24, 45, 37); +} + ++ (UIColor *)flatCoffeeColor { + return hsb(25, 31, 64); +} + ++ (UIColor *)flatForestGreenColor { + return hsb(138, 45, 37); +} + ++ (UIColor *)flatGrayColor { + return hsb(184, 10, 65); +} + ++ (UIColor *)flatGreenColor { + return hsb(145, 77, 80); +} + ++ (UIColor *)flatLimeColor { + return hsb(74, 70, 78); +} + ++ (UIColor *)flatMagentaColor { + return hsb(283, 51, 71); +} + ++ (UIColor *)flatMaroonColor { + return hsb(5, 65, 47); +} + ++ (UIColor *)flatMintColor { + return hsb(168, 86, 74); +} + ++ (UIColor *)flatNavyBlueColor { + return hsb(210, 45, 37); +} + ++ (UIColor *)flatOrangeColor { + return hsb(28, 85, 90); +} + ++ (UIColor *)flatPinkColor { + return hsb(324, 49, 96); +} + ++ (UIColor *)flatPlumColor { + return hsb(300, 45, 37); +} + ++ (UIColor *)flatPowderBlueColor { + return hsb(222, 24, 95); +} + ++ (UIColor *)flatPurpleColor { + return hsb(253, 52, 77); +} + ++ (UIColor *)flatRedColor { + return hsb(6, 74, 91); +} + ++ (UIColor *)flatSandColor { + return hsb(42, 25, 94); +} + ++ (UIColor *)flatSkyBlueColor { + return hsb(204, 76, 86); +} + ++ (UIColor *)flatTealColor { + return hsb(195, 55, 51); +} + ++ (UIColor *)flatWatermelonColor { + return hsb(356, 53, 94); +} + ++ (UIColor *)flatWhiteColor { + return hsb(192, 2, 95); +} + ++ (UIColor *)flatYellowColor { + return hsb(48, 99, 100); +} + +#pragma mark - Chameleon - Dark Shades + ++ (UIColor *)flatBlackColorDark { + return hsb(0, 0, 15); +} + ++ (UIColor *)flatBlueColorDark { + return hsb(224, 56, 51); +} + ++ (UIColor *)flatBrownColorDark { + return hsb(25, 45, 31); +} + ++ (UIColor *)flatCoffeeColorDark { + return hsb(25, 34, 56); +} + ++ (UIColor *)flatForestGreenColorDark { + return hsb(135, 44, 31); +} + ++ (UIColor *)flatGrayColorDark { + return hsb(184, 10, 55); +} + ++ (UIColor *)flatGreenColorDark { + return hsb(145, 78, 68); +} + ++ (UIColor *)flatLimeColorDark { + return hsb(74, 81, 69); +} + ++ (UIColor *)flatMagentaColorDark { + return hsb(282, 61, 68); +} + ++ (UIColor *)flatMaroonColorDark { + return hsb(4, 68, 40); +} + ++ (UIColor *)flatMintColorDark { + return hsb(168, 86, 63); +} + ++ (UIColor *)flatNavyBlueColorDark { + return hsb(210, 45, 31); +} + ++ (UIColor *)flatOrangeColorDark { + return hsb(24, 100, 83); +} + ++ (UIColor *)flatPinkColorDark { + return hsb(327, 57, 83); +} + ++ (UIColor *)flatPlumColorDark { + return hsb(300, 46, 31); +} + ++ (UIColor *)flatPowderBlueColorDark { + return hsb(222, 28, 84); +} + ++ (UIColor *)flatPurpleColorDark { + return hsb(253, 56, 64); +} + ++ (UIColor *)flatRedColorDark { + return hsb(6, 78, 75); +} + ++ (UIColor *)flatSandColorDark { + return hsb(42, 30, 84); +} + ++ (UIColor *)flatSkyBlueColorDark { + return hsb(204, 78, 73); +} + ++ (UIColor *)flatTealColorDark { + return hsb(196, 54, 45); +} + ++ (UIColor *)flatWatermelonColorDark { + return hsb(358, 61, 85); +} + ++ (UIColor *)flatWhiteColorDark { + return hsb(204, 5, 78); +} + ++ (UIColor *)flatYellowColorDark { + return hsb(40, 100, 100); +} + +#pragma mark - Chameleon - "Color With" Methods + ++ (UIColor *)colorWithAverageColorFromImage:(UIImage *)image { + + return [self colorWithAverageColorFromImage:image withAlpha:1.0]; +} + ++ (UIColor *)colorWithAverageColorFromImage:(UIImage *)image withAlpha:(CGFloat)alpha { + + //Work within the RGB colorspoace + CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); + unsigned char rgba[4]; + CGContextRef context = CGBitmapContextCreate(rgba, 1, 1, 8, 4, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); + + //Draw our image down to 1x1 pixels + CGContextDrawImage(context, CGRectMake(0, 0, 1, 1), image.CGImage); + CGColorSpaceRelease(colorSpace); + CGContextRelease(context); + + //Check if image alpha is 0 + if (rgba[3] == 0) { + + CGFloat imageAlpha = ((CGFloat)rgba[3])/255.0; + CGFloat multiplier = imageAlpha/255.0; + + UIColor *averageColor = [UIColor colorWithRed:((CGFloat)rgba[0])*multiplier green:((CGFloat)rgba[1])*multiplier blue:((CGFloat)rgba[2])*multiplier alpha:imageAlpha]; + + //Improve color + averageColor = [averageColor colorWithMinimumSaturation:0.15]; + + //Return average color + return averageColor; + } + + else { + + //Get average + UIColor *averageColor = [UIColor colorWithRed:((CGFloat)rgba[0])/255.0 green:((CGFloat)rgba[1])/255.0 blue:((CGFloat)rgba[2])/255.0 alpha:alpha]; + + //Improve color + averageColor = [averageColor colorWithMinimumSaturation:0.15]; + + //Return average color + return averageColor; + } +} + ++ (UIColor *)colorWithComplementaryFlatColorOf:(UIColor *)color { + + return [[self class] colorWithComplementaryFlatColorOf:color withAlpha:1.0]; +} + ++ (UIColor *)colorWithComplementaryFlatColorOf:(UIColor *)color withAlpha:(CGFloat)alpha { + + //Check if input UIColor is a gradient aka a pattern + if (CGColorGetPattern(color.CGColor)) { + + //Let's find the average color of the image and contrast against that. + CGSize size = {1, 1}; + + //Create a 1x1 bitmap context + UIGraphicsBeginImageContext(size); + CGContextRef ctx = UIGraphicsGetCurrentContext(); + + //Set the interpolation quality to medium + CGContextSetInterpolationQuality(ctx, kCGInterpolationMedium); + + //Draw image scaled down to this 1x1 pixel + [[self gradientImage] drawInRect:(CGRect){.size = size} blendMode:kCGBlendModeCopy alpha:1]; + + //Read the RGB values from the context's buffer + uint8_t *data = CGBitmapContextGetData(ctx); + color = [UIColor colorWithRed:data[2] / 255.0f + green:data[1] / 255.0f + blue:data[0] / 255.0f + alpha:1]; + UIGraphicsEndImageContext(); + } + + //Extract & Check to make sure we have an actual color to work with (Clear returns clear) + CGFloat hue, saturation, brightness, alpha1; + [color getHue:&hue saturation:&saturation brightness:&brightness alpha:&alpha1]; + + //Check if color is transparent + if (alpha1 == 0) { + return [UIColor clearColor]; + } + + //Multiply our value by their max values to convert + hue *= 360; + saturation *= 100; + brightness *= 100; + + //Select a color with a hue 180 degrees away on the colorwheel (i.e. for 50 it would be 230). + hue += 180.0f; + if (hue > 360.f) { + hue -= 360.0f; + } + + //Round to the nearest whole number after multiplying + hue = roundf(hue); + saturation = roundf(saturation); + brightness = roundf(brightness); + + //Store complimentary nonflat color + UIColor *complimentaryNonFlatColor = [UIColor colorWithHue:hue/360.0 + saturation:saturation/100.0 + brightness:brightness/100.0 + alpha:alpha]; + + //Retrieve LAB values from our complimentary nonflat color & return nearest flat color + return [self colorWithFlatVersionOf:complimentaryNonFlatColor withAlpha:alpha]; +} + + ++ (UIColor *)colorWithFlatVersionOf:(UIColor *)color { + + //Return flat version with default alpha of 1.0 + return [[self class] colorWithFlatVersionOf:color withAlpha:1.0]; +} + ++ (UIColor *)colorWithFlatVersionFrom:(UIColor *)color { + CGFloat colorAlpha = 0; + [color getLightness:nil valueForA:nil valueForB:nil alpha:&colorAlpha]; + colorAlpha = colorAlpha > 0.0 ? colorAlpha : 1.0; + //Return flat version with default alpha of 1.0 + return [[self class] colorWithFlatVersionOf:color withAlpha:colorAlpha]; +} + ++ (UIColor *)colorWithFlatVersionOf:(UIColor *)color withAlpha:(CGFloat)alpha { + + //Check if input UIColor is a gradient aka a pattern + if (CGColorGetPattern(color.CGColor)) { + + //Let's find the average color of the image and contrast against that. + CGSize size = {1, 1}; + + //Create a 1x1 bitmap context + UIGraphicsBeginImageContext(size); + CGContextRef ctx = UIGraphicsGetCurrentContext(); + + //Set the interpolation quality to medium + CGContextSetInterpolationQuality(ctx, kCGInterpolationMedium); + + //Draw image scaled down to this 1x1 pixel + [[self gradientImage] drawInRect:(CGRect){.size = size} blendMode:kCGBlendModeCopy alpha:1]; + + //Read the RGB values from the context's buffer + uint8_t *data = CGBitmapContextGetData(ctx); + color = [UIColor colorWithRed:data[2] / 255.0f + green:data[1] / 255.0f + blue:data[0] / 255.0f + alpha:1]; + UIGraphicsEndImageContext(); + } + + //Create CGFloats to hold our color values + CGFloat L, A, B, alpha1; + + //Get LAB values for our color + [color getLightness:&L valueForA:&A valueForB:&B alpha:&alpha1]; + + if (![color getLightness:&L valueForA:&A valueForB:&B alpha:&alpha1]) { + return nil; + } + + //Find the nearest flat color + return [self nearestFlatColorForL:L A:A B:B alpha:alpha]; +} + ++ (UIColor *)colorWithContrastingBlackOrWhiteColorOn:(UIColor *)backgroundColor isFlat:(BOOL)flat { + + //Return color with default alpha value of 1.0 + return [[self class] colorWithContrastingBlackOrWhiteColorOn:backgroundColor isFlat:flat alpha:1.0]; +} + ++ (UIColor *)colorWithContrastingBlackOrWhiteColorOn:(UIColor *)backgroundColor + isFlat:(BOOL)flat + alpha:(CGFloat)alpha { + + //Check if UIColor is a gradient aka a pattern + if (CGColorGetPattern(backgroundColor.CGColor)) { + + //Let's find the average color of the image and contrast against that. + CGSize size = {1, 1}; + + //Create a 1x1 bitmap context + UIGraphicsBeginImageContext(size); + CGContextRef ctx = UIGraphicsGetCurrentContext(); + + //Set the interpolation quality to medium + CGContextSetInterpolationQuality(ctx, kCGInterpolationMedium); + + //Draw image scaled down to this 1x1 pixel + [[self gradientImage] drawInRect:(CGRect){.size = size} blendMode:kCGBlendModeCopy alpha:1]; + + //Read the RGB values from the context's buffer + uint8_t *data = CGBitmapContextGetData(ctx); + backgroundColor = [UIColor colorWithRed:data[2] / 255.0f + green:data[1] / 255.0f + blue:data[0] / 255.0f + alpha:1]; + UIGraphicsEndImageContext(); + } + + //Calculate Luminance + CGFloat luminance; + CGFloat red = 0.0, green = 0.0, blue = 0.0, alpha1 = 0.0; + [backgroundColor getRed:&red green:&green blue:&blue alpha:&alpha1]; + + //Check if color is transparent + if (alpha == 0) { + return [UIColor clearColor]; + } + + // Relative luminance in colorimetric spaces - http://en.wikipedia.org/wiki/Luminance_(relative) + red *= 0.2126f; green *= 0.7152f; blue *= 0.0722f; + luminance = red + green + blue; + + if (flat == NO) { + return (luminance > 0.6f) ? rgba(0, 0, 0, alpha) : rgba(255, 255, 255, alpha); + } else { + return (luminance > 0.6f) ? hsba(0, 0, 15, alpha) : hsba(192, 2, 95, alpha); + } +} + ++ (UIColor *)colorWithGradientStyle:(UIGradientStyle)gradientStyle withFrame:(CGRect)frame andColors:(NSArray *)colors; { + + //Create our background gradient layer + CAGradientLayer *backgroundGradientLayer = [CAGradientLayer layer]; + + //Set the frame to our object's bounds + backgroundGradientLayer.frame = frame; + + //To simplfy formatting, we'll iterate through our colors array and create a mutable array with their CG counterparts + NSMutableArray *cgColors = [[NSMutableArray alloc] init]; + for (UIColor *color in colors) { + [cgColors addObject:(id)[color CGColor]]; + } + + switch (gradientStyle) { + case UIGradientStyleLeftToRight: { + + //Set out gradient's colors + backgroundGradientLayer.colors = cgColors; + + //Specify the direction our gradient will take + [backgroundGradientLayer setStartPoint:CGPointMake(0.0, 0.5)]; + [backgroundGradientLayer setEndPoint:CGPointMake(1.0, 0.5)]; + + //Convert our CALayer to a UIImage object + UIGraphicsBeginImageContextWithOptions(backgroundGradientLayer.bounds.size,NO, [UIScreen mainScreen].scale); + [backgroundGradientLayer renderInContext:UIGraphicsGetCurrentContext()]; + UIImage *backgroundColorImage = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + + [self setGradientImage:backgroundColorImage]; + return [UIColor colorWithPatternImage:backgroundColorImage]; + } + + case UIGradientStyleRadial: { + UIGraphicsBeginImageContextWithOptions(frame.size,NO, [UIScreen mainScreen].scale); + + //Specific the spread of the gradient (For now this gradient only takes 2 locations) + CGFloat locations[2] = {0.0, 1.0}; + + //Default to the RGB Colorspace + CGColorSpaceRef myColorspace = CGColorSpaceCreateDeviceRGB(); + CFArrayRef arrayRef = (__bridge CFArrayRef)cgColors; + + //Create our Fradient + CGGradientRef myGradient = CGGradientCreateWithColors(myColorspace, arrayRef, locations); + + + // Normalise the 0-1 ranged inputs to the width of the image + CGPoint myCentrePoint = CGPointMake(0.5 * frame.size.width, 0.5 * frame.size.height); + float myRadius = MIN(frame.size.width, frame.size.height) * 1.0; + + // Draw our Gradient + CGContextDrawRadialGradient (UIGraphicsGetCurrentContext(), myGradient, myCentrePoint, + 0, myCentrePoint, myRadius, + kCGGradientDrawsAfterEndLocation); + + // Grab it as an Image + UIImage *backgroundColorImage = UIGraphicsGetImageFromCurrentImageContext(); + + // Clean up + CGColorSpaceRelease(myColorspace); // Necessary? + CGGradientRelease(myGradient); // Necessary? + UIGraphicsEndImageContext(); + + [self setGradientImage:backgroundColorImage]; + return [UIColor colorWithPatternImage:backgroundColorImage]; + } + + case UIGradientStyleTopToBottom: + default: { + + //Set out gradient's colors + backgroundGradientLayer.colors = cgColors; + + //Convert our CALayer to a UIImage object + UIGraphicsBeginImageContextWithOptions(backgroundGradientLayer.bounds.size,NO, [UIScreen mainScreen].scale); + [backgroundGradientLayer renderInContext:UIGraphicsGetCurrentContext()]; + UIImage *backgroundColorImage = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + + [self setGradientImage:backgroundColorImage]; + return [UIColor colorWithPatternImage:backgroundColorImage]; + } + + } +} + ++ (UIColor *)colorWithHexString:(NSString *)string { + + //Color with string and a defualt alpha value of 1.0 + return [self colorWithHexString:string withAlpha:1.0]; +} + ++ (UIColor *)colorWithHexString:(NSString *)string withAlpha:(CGFloat)alpha { + + //Quick return in case string is empty + if (string.length == 0) { + return nil; + } + + //Check to see if we need to add a hashtag + if('#' != [string characterAtIndex:0]) { + string = [NSString stringWithFormat:@"#%@", string]; + } + + //Make sure we have a working string length + if (string.length != 7 && string.length != 4) { + + #ifdef DEBUG + NSLog(@"Unsupported string format: %@", string); + #endif + + return nil; + } + + //Check for short hex strings + if(string.length == 4) { + + //Convert to full length hex string + string = [NSString stringWithFormat:@"#%@%@%@%@%@%@", + [string substringWithRange:NSMakeRange(1, 1)],[string substringWithRange:NSMakeRange(1, 1)], + [string substringWithRange:NSMakeRange(2, 1)],[string substringWithRange:NSMakeRange(2, 1)], + [string substringWithRange:NSMakeRange(3, 1)],[string substringWithRange:NSMakeRange(3, 1)]]; + } + + NSString *redHex = [NSString stringWithFormat:@"0x%@", [string substringWithRange:NSMakeRange(1, 2)]]; + unsigned red = [[self class] hexValueToUnsigned:redHex]; + + NSString *greenHex = [NSString stringWithFormat:@"0x%@", [string substringWithRange:NSMakeRange(3, 2)]]; + unsigned green = [[self class] hexValueToUnsigned:greenHex]; + + NSString *blueHex = [NSString stringWithFormat:@"0x%@", [string substringWithRange:NSMakeRange(5, 2)]]; + unsigned blue = [[self class] hexValueToUnsigned:blueHex]; + + return [UIColor colorWithRed:(float)red/255 green:(float)green/255 blue:(float)blue/255 alpha:alpha]; +} + ++ (unsigned)hexValueToUnsigned:(NSString *)hexValue { + + //Define default unsigned value + unsigned value = 0; + + //Scan unsigned value + NSScanner *hexValueScanner = [NSScanner scannerWithString:hexValue]; + [hexValueScanner scanHexInt:&value]; + + //Return found value + return value; +} + +#pragma mark - Chameleon - Random Color Methods + ++ (NSInteger)generateRandomNumberWithMax:(NSInteger)max { + + //Choose a random number between 0 and our number of available colors + return arc4random_uniform((UInt32)max); +} + ++ (UIColor *)randomFlatColor { + + //Number of colors to choose from + const uint32_t numberOfPossibleColors = 48; + + //Chose one of those colors at random + NSInteger randomColorChosen = [[self class] generateRandomNumberWithMax:numberOfPossibleColors]; + + //Check if a previous random number exists + if (![[NSUserDefaults standardUserDefaults] integerForKey:@"previousRandomNumber"]) { + + //If no previous number exists, save it as such and find the matching color + [[NSUserDefaults standardUserDefaults] setInteger:randomColorChosen forKey:@"previousRandomNumber"]; + [[NSUserDefaults standardUserDefaults] synchronize]; + + } else { + + //Keep generating a random number until it is different than the one generated last time + while (randomColorChosen == [[NSUserDefaults standardUserDefaults] integerForKey:@"previousRandomNumber"]) { + randomColorChosen = [[self class] generateRandomNumberWithMax:numberOfPossibleColors]; + } + + //Once a new number has been generated then store it as the previous number for next time and proceed + [[NSUserDefaults standardUserDefaults] setInteger:randomColorChosen forKey:@"previousRandomNumber"]; + [[NSUserDefaults standardUserDefaults] synchronize]; + } + + return [self flatColors][randomColorChosen]; +} + ++ (UIColor *)colorWithRandomColorInArray:(NSArray *)colors { + + UIColor *randomColor; + if (colors.count) { + + //Pick a random index + NSInteger randomIndex = arc4random() % colors.count; + + //Return the color at the random index + randomColor = colors[randomIndex]; + + } else { + return nil; + } + + NSAssert([randomColor isKindOfClass:[UIColor class]], @"Hmm... one of your objects in your 'colors' array is not a UIColor object."); + + //Return + return randomColor; +} + ++ (UIColor *)colorWithRandomFlatColorExcludingColorsInArray:(NSArray *)colors { + + //Set random flat color + UIColor *randomColor = [[self class] randomFlatColor]; + + //If the selected color is blacklisted select a new color + while ([colors containsObject:randomColor]) { + randomColor = [[self class] randomFlatColor]; + } + + //Return + return randomColor; +} + ++ (UIColor *)colorWithRandomFlatColorOfShadeStyle:(UIShadeStyle)shadeStyle { + + //Return color with default alpha value of 1.0 + return [[self class] colorWithRandomFlatColorOfShadeStyle:shadeStyle withAlpha:1.0]; +} + ++ (UIColor *)colorWithRandomFlatColorOfShadeStyle:(UIShadeStyle)shadeStyle withAlpha:(CGFloat)alpha { + + //Number of colors to choose from + const NSInteger numberOfPossibleColors = 24; + + //Chose one of those colors at random + NSInteger randomColorChosen = [[self class] generateRandomNumberWithMax:numberOfPossibleColors]; + + //Check if a previous random number exists + if (![[NSUserDefaults standardUserDefaults] integerForKey:@"previousRandomNumber"]) { + + //If no previous number exists, save it as such and find the matching color + [[NSUserDefaults standardUserDefaults] setInteger:randomColorChosen forKey:@"previousRandomNumber"]; + [[NSUserDefaults standardUserDefaults] synchronize]; + + } else { + + //Keep generating a random number until it is different than the one generated last time + while (randomColorChosen == [[NSUserDefaults standardUserDefaults] integerForKey:@"previousRandomNumber"]) { + randomColorChosen = [[self class] generateRandomNumberWithMax:numberOfPossibleColors]; + } + + //Once a new number has been generated then store it as the previous number for next time and proceed + [[NSUserDefaults standardUserDefaults] setInteger:randomColorChosen forKey:@"previousRandomNumber"]; + [[NSUserDefaults standardUserDefaults] synchronize]; + } + + //Assign a random color based on randomColorChosen + UIColor *randomColor; + + //Return a color depending on the specified shade + switch (shadeStyle) { + case UIShadeStyleDark: { + + NSArray *darkColors = @[FlatBlackDark, FlatBlueDark, FlatBrownDark, FlatCoffeeDark, FlatForestGreenDark, FlatGrayDark, FlatGreenDark, FlatLimeDark, FlatMagentaDark, FlatMaroonDark, FlatMintDark, FlatNavyBlueDark, FlatOrangeDark, FlatPinkDark, FlatPlumDark, FlatPowderBlueDark, FlatPurpleDark, FlatRedDark, FlatSandDark, FlatSkyBlueDark, FlatTealDark, FlatWatermelonDark, FlatWhiteDark, FlatYellowDark]; + + randomColor = darkColors[randomColorChosen]; + break; + } + + case UIShadeStyleLight: + default: { + + NSArray *lightColors = @[FlatBlack, FlatBlue, FlatBrown, FlatCoffee, FlatForestGreen, FlatGray, FlatGreen, FlatLime, FlatMagenta, FlatMaroon, FlatMint, FlatNavyBlue, FlatOrange, FlatPink, FlatPlum, FlatPowderBlue, FlatPurple, FlatRed, FlatSand, FlatSkyBlue, FlatTeal, FlatWatermelon, FlatWhite, FlatYellow]; + + randomColor = lightColors[randomColorChosen]; + break; + } + } + + //Return color with correct alpha value + randomColor = [randomColor colorWithAlphaComponent:alpha]; + + return randomColor; +} + +#pragma mark - Chameleon Instance Methods + +- (UIColor *)flatten { + + return [UIColor colorWithFlatVersionFrom:self]; +} + +- (UIColor *)darkenByPercentage:(CGFloat)percentage { + + //Define HSBA values + CGFloat h, s, b, a; + + //Check if HSBA values exist + if ([self getHue:&h saturation:&s brightness:&b alpha:&a]) { + + //Make sure our percentage is greater than 0 + if (percentage > 0) { + b = MIN(b - percentage, 1.0); + } + + //Return darker color + return [UIColor colorWithHue:h saturation:s brightness:b alpha:a]; + } + + return nil; +} + +- (NSString *)hexValue { + + UIColor *currentColor = self; + if (CGColorGetNumberOfComponents(self.CGColor) < 4) { + const CGFloat *components = CGColorGetComponents(self.CGColor); + currentColor = [UIColor colorWithRed:components[0] green:components[0] blue:components[0] alpha:components[1]]; + } + + if (CGColorSpaceGetModel(CGColorGetColorSpace(currentColor.CGColor)) != kCGColorSpaceModelRGB) { + return [NSString stringWithFormat:@"#FFFFFF"]; + } + + return [NSString stringWithFormat:@"#%02X%02X%02X", (int)((CGColorGetComponents(currentColor.CGColor))[0]*255.0), (int)((CGColorGetComponents(currentColor.CGColor))[1]*255.0), (int)((CGColorGetComponents(currentColor.CGColor))[2]*255.0)]; + +} + +- (UIColor *)lightenByPercentage:(CGFloat)percentage { + + //Define HSBA values + CGFloat h, s, b, a; + + //Check if HSBA values exist + if ([self getHue:&h saturation:&s brightness:&b alpha:&a]) { + + //Make sure our percentage is greater than 0 + if (percentage > 0) { + b = MIN(b + percentage, 1.0); + } + + //Return lighter color + return [UIColor colorWithHue:h saturation:s brightness:b alpha:a]; + } + + return nil; +} + +- (BOOL)isEqualToColor:(UIColor *)color { + + //Check if both colors are in the Monochrome / RGB color space + if ([self isMonochromeOrRGB] && [color isMonochromeOrRGB]) { + + //Return comparison + return self.RGBAValue == color.RGBAValue; + } + + //Return comparison + return [self isEqual:color]; +} + +#pragma mark - Chameleon Internal Methods + +//Array of all our colors ++ (NSArray *)flatColors { + + return @[FlatBlack, FlatBlackDark, FlatBlue, FlatBlueDark, FlatBrown, FlatBrownDark, FlatCoffee, FlatCoffeeDark, FlatForestGreen, FlatForestGreenDark, FlatGray, FlatGrayDark, FlatGreen, FlatGreenDark, FlatLime, FlatLimeDark, FlatMagenta, FlatMagentaDark, FlatMaroon, FlatMaroonDark, FlatMint, FlatMintDark, FlatNavyBlue, FlatNavyBlueDark, FlatOrange, FlatOrangeDark, FlatPink, FlatPinkDark, FlatPlum, FlatPlumDark, FlatPowderBlue, FlatPowderBlueDark, FlatPurple, FlatPurpleDark, FlatRed, FlatRedDark, FlatSand, FlatSandDark, FlatSkyBlue, FlatSkyBlueDark, FlatTeal, FlatTealDark, FlatWatermelon, FlatWatermelonDark, FlatWhite, FlatWhiteDark, FlatYellow, FlatYellowDark]; +} + +- (uint32_t)RGBAValue { + + CGFloat rgba[4]; + [self getRGBAComponents:rgba]; + uint8_t red = rgba[0]*255; + uint8_t green = rgba[1]*255; + uint8_t blue = rgba[2]*255; + uint8_t alpha = rgba[3]*255; + + return (red << 24) + (green << 16) + (blue << 8) + alpha; +} + +- (void)getRGBAComponents:(CGFloat[4])rgba { + + CGColorSpaceModel model = CGColorSpaceGetModel(CGColorGetColorSpace(self.CGColor)); + const CGFloat *components = CGColorGetComponents(self.CGColor); + switch (model) { + + case kCGColorSpaceModelMonochrome: { + rgba[0] = components[0]; + rgba[1] = components[0]; + rgba[2] = components[0]; + rgba[3] = components[1]; + break; + } + + case kCGColorSpaceModelRGB: { + rgba[0] = components[0]; + rgba[1] = components[1]; + rgba[2] = components[2]; + rgba[3] = components[3]; + break; + } + + case kCGColorSpaceModelCMYK: + case kCGColorSpaceModelDeviceN: + case kCGColorSpaceModelIndexed: + case kCGColorSpaceModelLab: + case kCGColorSpaceModelPattern: + case kCGColorSpaceModelUnknown: { + + #ifdef DEBUG + NSLog(@"Unsupported color model: %i", model); + #endif + + rgba[0] = 0.0f; + rgba[1] = 0.0f; + rgba[2] = 0.0f; + rgba[3] = 1.0f; + break; + } + } +} + +//Check if color is in the monochrome or rgb color space +- (BOOL)isMonochromeOrRGB { + + CGColorSpaceModel model = CGColorSpaceGetModel(CGColorGetColorSpace(self.CGColor)); + return model == kCGColorSpaceModelMonochrome || model == kCGColorSpaceModelRGB; +} + +//Calculate the total sum of differences - Euclidian distance +//Chameleon is now using the CIEDE2000 formula to calculate distances between 2 colors. +//More info: http://en.wikipedia.org/wiki/Color_difference ++ (float)totalSumOfDifferencesFroml1:(CGFloat)L1 l2:(CGFloat)L2 a1:(CGFloat)A1 + a2:(CGFloat)A2 b1:(CGFloat)B1 b2:(CGFloat)B2 { + + //Get C Values in LCH from LAB Values + CGFloat C1 = sqrt(pow(A1, 2) + pow(B1, 2)); + CGFloat C2 = sqrt(pow(A2, 2) + pow(B2, 2)); + + //CIE Weights + CGFloat KL = 1; + CGFloat KC = 1; + CGFloat KH = 1; + + //Variables specifically set for CIE:2000 + CGFloat DeltaPrimeL = L2 - L1; + CGFloat MeanL = ((L1 + L2) / 2); + CGFloat MeanC = ((C1 + C2) / 2); + CGFloat A1Prime = A1 + A1 / 2 * (1 - sqrt(pow(MeanC, 7.0) / (pow(MeanC, 7.0) + pow(25.0, 7.0)))); + CGFloat A2Prime = A2 + A2 / 2 * (1 - sqrt(pow(MeanC, 7.0) / (pow(MeanC, 7.0) + pow(25.0, 7.0)))); + CGFloat C1Prime = sqrt(pow(A1Prime, 2) + pow(B1, 2)); + CGFloat C2Prime = sqrt(pow(A2Prime, 2) + pow(B2, 2)); + CGFloat DeltaPrimeC = C1Prime - C2Prime; + CGFloat DeltaC = C1 - C2; + CGFloat MeanCPrime = (C1Prime + C2Prime) / 2; + CGFloat H1Prime = fmodf(atan2(B1, A1Prime), (360.0 * M_PI/180)); + CGFloat H2Prime = fmodf(atan2(B2, A2Prime), (360.0 * M_PI/180)); + + //Run everything through our △H' Function + CGFloat hDeltaPrime = 0; + if (fabs(H1Prime - H2Prime) <= (180.0 * M_PI/180)) { + + hDeltaPrime = H2Prime - H1Prime; + + } else if (H2Prime <= H1Prime) { + + hDeltaPrime = (H2Prime - H1Prime) + ((360.0 * M_PI/180)); + + } else { + + hDeltaPrime = (H2Prime - H1Prime) - ((360.0 * M_PI/180)); + } + + CGFloat deltaHPrime = 2 * (sqrt(C1Prime*C2Prime)) * sin(hDeltaPrime/2); + + //Get Mean H' Value + CGFloat MeanHPrime = 0; + if (fabs(H1Prime-H2Prime) > (180.0 * M_PI/180)) { + + MeanHPrime = (H1Prime + H2Prime + (360.0 * M_PI/180)) / 2; + + } else { + + MeanHPrime = (H1Prime + H2Prime) / 2; + } + + CGFloat T = 1 - 0.17 * cos(MeanHPrime - (30.0 * M_PI/180)) + 0.24 * cos(2 * MeanHPrime)+0.32 * cos(3 * MeanHPrime + (6.0 * M_PI/180)) - 0.20 * cos(4 * MeanHPrime - (63.0 * M_PI/180)); + + CGFloat SL = 1 + (0.015 * pow((MeanL - 50), 2))/sqrt(20 + pow((MeanL - 50), 2)); + CGFloat SC = 1 + 0.045 * MeanCPrime; + CGFloat SH = 1 + 0.015 * MeanCPrime * T; + + CGFloat RT = -2 * sqrt(pow(MeanCPrime, 7) / (pow(MeanCPrime, 7) + pow(25.0, 7))) * sin((60.0 * M_PI/180)* exp(-1 * pow((MeanCPrime - (275.0 * M_PI/180)) / (25.0 * M_PI/180), 2))); + + + //Get total difference + CGFloat TotalDifference = sqrt(pow((DeltaPrimeL / (KL * SL)), 2) + pow((DeltaPrimeC / (KC * SC)), 2) + pow((deltaHPrime / (KH * SH)), 2) + RT * (DeltaC / (KC * SC)) * (deltaHPrime / (KH * SH))); + + return TotalDifference; +} + ++ (UIColor *)nearestFlatColorForL:(CGFloat)l1 A:(CGFloat)a1 B:(CGFloat)b1 alpha:(CGFloat)alpha{ + + //Keep track of our index + int index = 0; + + //Start with a random big number to make sure the first comparison gets saved. + float smallestDistance = 1000000; + float previousDistance = 1000000; + float currentDistance; + + //Our values + CGFloat l2, a2, b2; + + //We're interested in the color with values returning the smallest sum of total differences so we need to cross reference our input color's values with every flat color's values + for (int i=0; i<[[self flatColors] count]; i++ ) { + + //Check that index is not zero + if (i!=0 ) { + //Extract LAB values from colors in array and store it as the previous index + [[self flatColors][i - 1] getLightness:&l2 valueForA:&a2 valueForB:&b2 alpha:nil]; + + previousDistance = [self totalSumOfDifferencesFroml1:l1 l2:l2 + a1:a1 a2:a2 + b1:b1 b2:b2]; + } + + //Extract LAB values from colors in array and store it as the current index + [[self flatColors][i] getLightness:&l2 valueForA:&a2 valueForB:&b2 alpha:nil]; + + currentDistance = [self totalSumOfDifferencesFroml1:l1 l2:l2 + a1:a1 a2:a2 + b1:b1 b2:b2]; + + //We're only interested in the smallest difference + if (currentDistance < previousDistance) { + if (currentDistance < smallestDistance) { + smallestDistance = currentDistance; + index = i; + } + } + } + + + //Collect the RGB Values of the color where the smallest difference was found + CGFloat red, green, blue; + [[self flatColors][index] getRed:&red green:&green blue:&blue alpha:nil]; + + //Return the closest flat color + return rgba(red * 255, green * 255, blue * 255, alpha); +} + +@end diff --git a/Pods/ChameleonFramework/Pod/Classes/Objective-C/UIColor+ChameleonPrivate.h b/Pods/ChameleonFramework/Pod/Classes/Objective-C/UIColor+ChameleonPrivate.h new file mode 100755 index 00000000..f81e69aa --- /dev/null +++ b/Pods/ChameleonFramework/Pod/Classes/Objective-C/UIColor+ChameleonPrivate.h @@ -0,0 +1,36 @@ +// +// UIColor+ChameleonPrivate.h +// Chameleon +// +// Created by Vicc Alexander on 6/6/15. +// Copyright (c) 2015 Vicc Alexander. All rights reserved. +// + +#import +#import + +@interface UIColor (ChameleonPrivate) + +@property (nonatomic, readwrite) NSUInteger count; + +#pragma mark - Class Methods + ++ (UIColor *)colorFromImage:(UIImage *)image atPoint:(CGPoint)point; + +- (UIColor *)colorWithMinimumSaturation:(CGFloat)saturation; + +#pragma mark - Instance Methods + +- (BOOL)isDistinct:(UIColor *)color; + +- (BOOL)getValueForX:(CGFloat *)X + valueForY:(CGFloat *)Y + valueForZ:(CGFloat *)Z + alpha:(CGFloat *)alpha; + +- (BOOL)getLightness:(CGFloat *)L + valueForA:(CGFloat *)A + valueForB:(CGFloat *)B + alpha:(CGFloat *)alpha; + +@end diff --git a/Pods/ChameleonFramework/Pod/Classes/Objective-C/UIColor+ChameleonPrivate.m b/Pods/ChameleonFramework/Pod/Classes/Objective-C/UIColor+ChameleonPrivate.m new file mode 100755 index 00000000..c5c7d473 --- /dev/null +++ b/Pods/ChameleonFramework/Pod/Classes/Objective-C/UIColor+ChameleonPrivate.m @@ -0,0 +1,251 @@ +// +// UIColor+ChameleonPrivate.m +// Chameleon +// +// Created by Vicc Alexander on 6/6/15. +// Copyright (c) 2015 Vicc Alexander. All rights reserved. +// + +#import "UIColor+ChameleonPrivate.h" + +@implementation UIColor (ChameleonPrivate) + +@dynamic count; + +#pragma mark - Associated Objects Methods + +- (void)setCount:(NSUInteger)count { + objc_setAssociatedObject(self, @selector(count), [NSNumber numberWithUnsignedInteger:count], OBJC_ASSOCIATION_RETAIN_NONATOMIC); +} + +- (NSUInteger)count { + NSNumber *number = objc_getAssociatedObject(self, @selector(count)); + return [number unsignedIntegerValue]; +} + +#pragma mark - Class Methods + +// Would not have been possible without - http://stackoverflow.com/a/1262893 ++ (UIColor *)colorFromImage:(UIImage *)image atPoint:(CGPoint)point { + + //Encapsulate our image + CGImageRef imageRef = image.CGImage; + NSUInteger width = CGImageGetWidth(imageRef); + NSUInteger height = CGImageGetHeight(imageRef); + + //Specify the colorspace we're in + CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); + + //Extract the data we need + unsigned char *rawData = calloc(height * width * 4, sizeof(unsigned char)); + NSUInteger bytesPerPixel = 4; + NSUInteger bytesPerRow = bytesPerPixel * width; + NSUInteger bitsPerComponent = 8; + CGContextRef context = CGBitmapContextCreate(rawData, width, height, bitsPerComponent, bytesPerRow, + colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); + //Release colorspace + CGColorSpaceRelease(colorSpace); + + //Draw and release image + CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef); + CGContextRelease(context); + + //rawData now contains the image data in RGBA8888 + NSInteger byteIndex = (bytesPerRow * point.y) + (point.x * bytesPerPixel); + + //Define our RGBA values + CGFloat red = (rawData[byteIndex] * 1.f) / 255.f; + CGFloat green = (rawData[byteIndex + 1] * 1.f) / 255.f; + CGFloat blue = (rawData[byteIndex + 2] * 1.f) / 255.f; + CGFloat alpha = (rawData[byteIndex + 3] * 1.0) / 255.f; + + //Free our rawData + free(rawData); + + //Return color + return [UIColor colorWithRed:red green:green blue:blue alpha:alpha]; +} + +- (UIColor *)colorWithMinimumSaturation:(CGFloat)saturation { + if (!self) + return nil; + + CGFloat h, s, b, a; + [self getHue:&h saturation:&s brightness:&b alpha:&a]; + + if (s < saturation) + return [UIColor colorWithHue:h saturation:saturation brightness:b alpha:a]; + + return self; +} + +#pragma mark - Instance Methods + +- (BOOL)isDistinct:(UIColor *)color { + + if (!self || !color) { + return NO; + } + + CGFloat r, g, b, a; + CGFloat rc, gc, bc, ac; + + [self getRed:&r green:&g blue:&b alpha:&a]; + [color getRed:&rc green:&gc blue:&bc alpha:&ac]; + + CGFloat threshold = 0.25f; + + if (fabs(r - rc) > threshold || fabs(g - gc) > threshold || + + fabs(b - bc) > threshold || fabs(a - ac) > threshold) { + + // Check for grays + if (fabs(r - g) < 0.03f && fabs(r - b) < 0.03f) { + + if (fabs(rc - gc) < 0.03f && (fabs(rc - bc) < 0.03f)) { + return NO; + } + + } + + return YES; + } + + return NO; +} + +- (BOOL)getValueForX:(CGFloat *)X valueForY:(CGFloat *)Y valueForZ:(CGFloat *)Z alpha:(CGFloat *)alpha{ + + if ([self respondsToSelector:@selector(getRed:green:blue:alpha:)]) { + + //Get RGB values from the input color + CGFloat red = 0, green = 0, blue = 0, alpha1 = 0; + [self getRed:&red green:&green blue:&blue alpha:&alpha1]; + + //Run our input color's RGB values through the XYZ algorithm to convert them into XYZ values + NSArray *XYZValues = [self arrayOfXYZValuesForR:red G:green B:blue A:alpha1]; + *X = [XYZValues[0] floatValue]; + *Y = [XYZValues[1] floatValue]; + *Z = [XYZValues[2] floatValue]; + *alpha = [XYZValues[3] floatValue]; + + return YES; + } + + return NO; +} + +- (BOOL)getLightness:(CGFloat *)L valueForA:(CGFloat *)A valueForB:(CGFloat *)B alpha:(CGFloat *)alpha { + + if ([self respondsToSelector:@selector(getRed:green:blue:alpha:)]) { + + //Get RGB values from the input color + CGFloat red = 0, green = 0, blue = 0, alpha1 = 0; + [self getRed:&red green:&green blue:&blue alpha:&alpha1]; + + //Run our input color's RGB values through the XYZ algorithm to convert them into XYZ values + NSArray *XYZValues = [self arrayOfXYZValuesForR:red G:green B:blue A:alpha1]; + CGFloat X = [XYZValues[0] floatValue]; + CGFloat Y = [XYZValues[1] floatValue]; + CGFloat Z = [XYZValues[2] floatValue]; + + if (L != nil && A != nil && B != nil) { + //Run our new XYZ values through our LAB algorithm to convert them into LAB values + NSArray *LABValues = [self arrayOfLABValuesForX:X Y:Y Z:Z alpha:alpha1]; + *L = [LABValues[0] floatValue]; + *A = [LABValues[1] floatValue]; + *B = [LABValues[2] floatValue]; + } + + return YES; + } + + return NO; +} + +#pragma mark - Internal Helper Methods + +- (NSArray *)arrayOfXYZValuesForR:(CGFloat)red G:(CGFloat)green B:(CGFloat)blue A:(CGFloat)alpha { + + /* + Let's begin by converting from RGB to sRGB. + We're going to use the Reverse Transformation Equation. + http://en.wikipedia.org/wiki/SRGB + */ + + void (^sRGB)(CGFloat *C); + sRGB = ^(CGFloat *C) { + if (*C > 0.04045) { + *C = pow(((*C + 0.055)/ (1 + 0.055)), 2.40); + } else { + *C /= 12.92; + } + }; + + sRGB(&red); + sRGB(&green); + sRGB(&blue); + + /* + Now we're going to convert to XYZ values, using a matrix multiplication of the linear values + http://upload.wikimedia.org/math/4/3/3/433376fc18cccd887758beffb7e7c625.png + */ + + CGFloat X = (red * 0.4124) + (green * 0.3576) + (blue * 0.1805); + CGFloat Y = (red * 0.2126) + (green * 0.7152) + (blue * 0.0722); + CGFloat Z = (red * 0.0193) + (green * 0.1192) + (blue * 0.9505); + + X *= 100; + Y *= 100; + Z *= 100; + + return @[@(X), @(Y), @(Z), @(alpha)]; +} + +- (NSArray *)arrayOfLABValuesForX:(CGFloat)X Y:(CGFloat)Y Z:(CGFloat)Z alpha:(CGFloat)alpha { + + /* + The corresponding original XYZ values are such that white is D65 with unit luminance (X,Y,Z = 0.9505, 1.0000, 1.0890). + Calculations are also to assume the 2° standard colorimetric observer. + D65: http://en.wikipedia.org/wiki/CIE_Standard_Illuminant_D65 + Standard Colorimetric Observer: http://en.wikipedia.org/wiki/Standard_colorimetric_observer#CIE_standard_observer + + Since we mutiplied our XYZ values by 100 to produce a percentage we should also multiply our unit luminance values by 100. + */ + + X /= (0.9505 * 100); + Y /= (1.0000 * 100); + Z /= (1.0890 * 100); + + /* + Next we need to use the forward transformation function for CIELAB-CIEXYZ conversions + Function: http://upload.wikimedia.org/math/e/5/1/e513d25d50d406bfffb6ed3c854bd8a4.png + */ + + void (^XYZtoLAB)(CGFloat *f); + XYZtoLAB = ^(CGFloat *f) { + if ((*f > pow((6.0/29.0), 3.0)) ) { + *f = pow(*f, 1.0/3.0); + } else { + *f = (1/3)*pow((29.0/6.0), 2.0) * *f + 4/29.0; + } + }; + + XYZtoLAB(&X); + XYZtoLAB(&Y); + XYZtoLAB(&Z); + + /* + Next we get our LAB values using the following equations and the results from the function above + http://upload.wikimedia.org/math/0/0/6/006164b74314e2fdcdc34ac9d0aa6fe4.png + */ + + CGFloat L = (116 * Y) - 16; + CGFloat A = 500 * (X - Y); + CGFloat B = 200 * (Y - Z); + + + return @[@(L), @(A), @(B), @(alpha)]; +} + +@end diff --git a/Pods/ChameleonFramework/Pod/Classes/Objective-C/UIImage+ChameleonPrivate.h b/Pods/ChameleonFramework/Pod/Classes/Objective-C/UIImage+ChameleonPrivate.h new file mode 100755 index 00000000..91fdc45d --- /dev/null +++ b/Pods/ChameleonFramework/Pod/Classes/Objective-C/UIImage+ChameleonPrivate.h @@ -0,0 +1,21 @@ +// +// UIImage+ChameleonPrivate.h +// Chameleon +// +// Created by Vicc Alexander on 6/8/15. +// Copyright (c) 2015 Vicc Alexander. All rights reserved. +// + +#import + +@interface UIImage (ChameleonPrivate) + +#pragma mark - Class Methods + ++ (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize; + +#pragma mark - Instance Methods + +- (UIImage *)imageScaledToSize:(CGSize)newSize; + +@end diff --git a/Pods/ChameleonFramework/Pod/Classes/Objective-C/UIImage+ChameleonPrivate.m b/Pods/ChameleonFramework/Pod/Classes/Objective-C/UIImage+ChameleonPrivate.m new file mode 100755 index 00000000..707c64aa --- /dev/null +++ b/Pods/ChameleonFramework/Pod/Classes/Objective-C/UIImage+ChameleonPrivate.m @@ -0,0 +1,74 @@ +// +// UIImage+ChameleonPrivate.m +// Chameleon +// +// Created by Vicc Alexander on 6/8/15. +// Copyright (c) 2015 Vicc Alexander. All rights reserved. +// + +#import "UIImage+ChameleonPrivate.h" + +@implementation UIImage (ChameleonPrivate) + +// Would not have been possible without - http://stackoverflow.com/a/1262893 ++ (UIColor *)colorFromImage:(UIImage *)image atPoint:(CGPoint)point { + + //Encapsulate our image + CGImageRef imageRef = image.CGImage; + NSUInteger width = CGImageGetWidth(imageRef); + NSUInteger height = CGImageGetHeight(imageRef); + + //Specify the colorspace we're in + CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); + + //Extract the data we need + unsigned char *rawData = calloc(height * width * 4, sizeof(unsigned char)); + NSUInteger bytesPerPixel = 4; + NSUInteger bytesPerRow = bytesPerPixel * width; + NSUInteger bitsPerComponent = 8; + CGContextRef context = CGBitmapContextCreate(rawData, width, height, bitsPerComponent, bytesPerRow, + colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); + //Release colorspace + CGColorSpaceRelease(colorSpace); + + //Draw and release image + CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef); + CGContextRelease(context); + + //rawData now contains the image data in RGBA8888 + NSInteger byteIndex = (bytesPerRow * point.y) + (point.x * bytesPerPixel); + + //Define our RGBA values + CGFloat red = (rawData[byteIndex] * 1.f) / 255.f; + CGFloat green = (rawData[byteIndex + 1] * 1.f) / 255.f; + CGFloat blue = (rawData[byteIndex + 2] * 1.f) / 255.f; + CGFloat alpha = (rawData[byteIndex + 3] * 1.0) / 255.f; + + //Free our rawData + free(rawData); + + //Return color + return [UIColor colorWithRed:red green:green blue:blue alpha:alpha]; +} + ++ (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize { + + UIGraphicsBeginImageContextWithOptions(newSize, NO, 1.0); + [image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)]; + UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + return newImage; +} + +#pragma mark - Instance Methods + +- (UIImage *)imageScaledToSize:(CGSize)newSize { + + UIGraphicsBeginImageContextWithOptions(newSize, NO, 1.0); + [self drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)]; + UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + return newImage; +} + +@end diff --git a/Pods/ChameleonFramework/Pod/Classes/Objective-C/UILabel+Chameleon.h b/Pods/ChameleonFramework/Pod/Classes/Objective-C/UILabel+Chameleon.h new file mode 100755 index 00000000..6bc8e224 --- /dev/null +++ b/Pods/ChameleonFramework/Pod/Classes/Objective-C/UILabel+Chameleon.h @@ -0,0 +1,15 @@ +// +// UILabel+Chameleon.h +// Chameleon +// +// Created by Vicc Alexander on 9/20/15. +// Copyright © 2015 Vicc Alexander. All rights reserved. +// + +#import + +@interface UILabel (Chameleon) + +- (void)setSubstituteFontName:(NSString *)name UI_APPEARANCE_SELECTOR; + +@end diff --git a/Pods/ChameleonFramework/Pod/Classes/Objective-C/UILabel+Chameleon.m b/Pods/ChameleonFramework/Pod/Classes/Objective-C/UILabel+Chameleon.m new file mode 100755 index 00000000..bb28af02 --- /dev/null +++ b/Pods/ChameleonFramework/Pod/Classes/Objective-C/UILabel+Chameleon.m @@ -0,0 +1,18 @@ +// +// UILabel+Chameleon.m +// Chameleon +// +// Created by Vicc Alexander on 9/20/15. +// Copyright © 2015 Vicc Alexander. All rights reserved. +// + +#import "UILabel+Chameleon.h" + +@implementation UILabel (Chameleon) + +- (void)setSubstituteFontName:(NSString *)name UI_APPEARANCE_SELECTOR { + + self.font = [UIFont fontWithName:name size:self.font.pointSize]; +} + +@end diff --git a/Pods/ChameleonFramework/Pod/Classes/Objective-C/UINavigationController+Chameleon.h b/Pods/ChameleonFramework/Pod/Classes/Objective-C/UINavigationController+Chameleon.h new file mode 100755 index 00000000..6913d49e --- /dev/null +++ b/Pods/ChameleonFramework/Pod/Classes/Objective-C/UINavigationController+Chameleon.h @@ -0,0 +1,32 @@ +// +// UINavigationController+Chameleon.h +// ChameleonDemo +// +// Created by Vicc Alexander on 6/4/15. +// Copyright (c) 2015 Vicc Alexander. All rights reserved. +// + +#import +#import "ChameleonEnums.h" + +@interface UINavigationController (Chameleon) + +/** + * Sets the status bar style for the specified @c UINavigationController and all its child controllers. + * + * @param statusBarStyle The style of the device's status bar. + * + * @note Chameleon introduces a new @c statusBarStyle called @c UIStatusBarStyleContrast. + * + * @since 2.0 + */ +- (void)setStatusBarStyle:(UIStatusBarStyle)statusBarStyle; + +/** + * Hides the hairline view at the bottom of a navigation bar. The default value is @c NO. + * + * @since 2.0.3 + */ +@property (nonatomic, assign) BOOL hidesNavigationBarHairline; + +@end diff --git a/Pods/ChameleonFramework/Pod/Classes/Objective-C/UINavigationController+Chameleon.m b/Pods/ChameleonFramework/Pod/Classes/Objective-C/UINavigationController+Chameleon.m new file mode 100755 index 00000000..15998152 --- /dev/null +++ b/Pods/ChameleonFramework/Pod/Classes/Objective-C/UINavigationController+Chameleon.m @@ -0,0 +1,214 @@ +// +// UINavigationController+Chameleon.m +// ChameleonDemo +// +// Created by Vicc Alexander on 6/4/15. +// Copyright (c) 2015 Vicc Alexander. All rights reserved. +// + +#import "UINavigationController+Chameleon.h" +#import + +#import "ChameleonConstants.h" +#import "ChameleonEnums.h" +#import "ChameleonMacros.h" + +#import "NSArray+Chameleon.h" +#import "UIColor+Chameleon.h" +#import "UIViewController+Chameleon.h" + +@interface UINavigationController () + +@property (readwrite) BOOL shouldContrast; +@property (readwrite) BOOL shouldUseLightContent; + +@end + +@implementation UINavigationController (Chameleon) + +@dynamic hidesNavigationBarHairline; + +#pragma mark - Swizzling + ++ (void)load { + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + + Class class = [self class]; + + SEL originalSelector = @selector(viewDidLoad); + SEL swizzledSelector = @selector(chameleon_viewDidLoad); + + Method originalMethod = class_getInstanceMethod(class, originalSelector); + Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector); + + BOOL didAddMethod = + class_addMethod(class, + originalSelector, + method_getImplementation(swizzledMethod), + method_getTypeEncoding(swizzledMethod)); + + if (didAddMethod) { + class_replaceMethod(class, + swizzledSelector, + method_getImplementation(originalMethod), + method_getTypeEncoding(originalMethod)); + + } else { + method_exchangeImplementations(originalMethod, swizzledMethod); + } + }); +} + +- (void)chameleon_viewDidLoad { + + [self chameleon_viewDidLoad]; + + UIView *hairlineImageView = [self findHairlineImageViewUnder:self.navigationBar]; + + if (hairlineImageView) { + + if (self.hidesNavigationBarHairline) { + hairlineImageView.hidden = YES; + + } else { + hairlineImageView.hidden = NO; + } + } +} + +- (UIImageView *)findHairlineImageViewUnder:(UIView *)view { + + if ([view isKindOfClass:UIImageView.class] && view.bounds.size.height <= 1.0) { + return (UIImageView *)view; + } + + for (UIView *subview in view.subviews) { + UIImageView *imageView = [self findHairlineImageViewUnder:subview]; + if (imageView) { + return imageView; + } + } + + return nil; +} + +#pragma mark - Runtime + +- (void)setShouldContrast:(BOOL)contrast { + + NSNumber *number = [NSNumber numberWithBool:contrast]; + objc_setAssociatedObject(self, @selector(shouldContrast), number, OBJC_ASSOCIATION_RETAIN); +} + +- (BOOL)shouldContrast { + + NSNumber *number = objc_getAssociatedObject(self, @selector(shouldContrast)); + return [number boolValue]; +} + +- (void)setShouldUseLightContent:(BOOL)shouldUseLightContent { + + NSNumber *number = [NSNumber numberWithBool:shouldUseLightContent]; + objc_setAssociatedObject(self, @selector(shouldUseLightContent), number, OBJC_ASSOCIATION_RETAIN); +} + +- (BOOL)shouldUseLightContent { + + NSNumber *number = objc_getAssociatedObject(self, @selector(shouldUseLightContent)); + return [number boolValue]; +} + +- (void)setHidesNavigationBarHairline:(BOOL)hidesNavigationBarHairline { + + NSNumber *number = [NSNumber numberWithBool:hidesNavigationBarHairline]; + objc_setAssociatedObject(self, @selector(hidesNavigationBarHairline), number, OBJC_ASSOCIATION_RETAIN); + + //Find Hairline Image + UIView *hairlineImageView = [self findHairlineImageViewUnder:self.navigationBar]; + + //Check if it exists + if (hairlineImageView) { + + //Check if we should hide it or not + if (hidesNavigationBarHairline) { + hairlineImageView.hidden = YES; + + } else { + hairlineImageView.hidden = NO; + } + } +} + +- (BOOL)hidesNavigationBarHairline { + + NSNumber *number = objc_getAssociatedObject(self, @selector(hidesNavigationBarHairline)); + return [number boolValue]; +} + + +#pragma mark - Public Methods + +- (void)setStatusBarStyle:(UIStatusBarStyle)statusBarStyle { + + if (statusBarStyle == UIStatusBarStyleContrast) { + + self.shouldContrast = YES; + + } else { + + if (statusBarStyle == UIStatusBarStyleLightContent) { + + self.shouldUseLightContent = YES; + + } else { + + self.shouldUseLightContent = NO; + } + + } +} + +#pragma mark - Private Methods + +- (UIStatusBarStyle)preferredStatusBarStyle { + + [super preferredStatusBarStyle]; + + if (self.shouldContrast) { + + return [self contrastingStatusBarStyleForColor:self.navigationBar.barTintColor]; + + } else { + + if (self.shouldUseLightContent) { + + return UIStatusBarStyleLightContent; + + } else { + + return UIStatusBarStyleDefault; + } + } +} + +- (UIStatusBarStyle)contrastingStatusBarStyleForColor:(UIColor *)backgroundColor { + + //Calculate Luminance + CGFloat luminance; + CGFloat red, green, blue; + + //Check for clear or uncalculatable color and assume white + if (![backgroundColor getRed:&red green:&green blue:&blue alpha:nil]) { + return UIStatusBarStyleDefault; + } + + //Relative luminance in colorimetric spaces - http://en.wikipedia.org/wiki/Luminance_(relative) + red *= 0.2126f; green *= 0.7152f; blue *= 0.0722f; + luminance = red + green + blue; + + return (luminance > 0.6f) ? UIStatusBarStyleDefault : UIStatusBarStyleLightContent; +} + +@end diff --git a/Pods/ChameleonFramework/Pod/Classes/Objective-C/UIView+ChameleonPrivate.h b/Pods/ChameleonFramework/Pod/Classes/Objective-C/UIView+ChameleonPrivate.h new file mode 100755 index 00000000..cc3b6cec --- /dev/null +++ b/Pods/ChameleonFramework/Pod/Classes/Objective-C/UIView+ChameleonPrivate.h @@ -0,0 +1,16 @@ +// +// UIView+ChameleonPrivate.h +// Chameleon +// +// Created by Vicc Alexander on 6/4/15. +// Copyright (c) 2015 Vicc Alexander. All rights reserved. +// + +#import + +@interface UIView (ChameleonPrivate) + +- (BOOL)isTopViewInWindow; +- (UIView *)findTopMostViewForPoint:(CGPoint)point; + +@end diff --git a/Pods/ChameleonFramework/Pod/Classes/Objective-C/UIView+ChameleonPrivate.m b/Pods/ChameleonFramework/Pod/Classes/Objective-C/UIView+ChameleonPrivate.m new file mode 100755 index 00000000..bc5203d2 --- /dev/null +++ b/Pods/ChameleonFramework/Pod/Classes/Objective-C/UIView+ChameleonPrivate.m @@ -0,0 +1,46 @@ +// +// UIView+ChameleonPrivate.m +// Chameleon +// +// Created by Vicc Alexander on 6/4/15. +// Copyright (c) 2015 Vicc Alexander. All rights reserved. +// + +#import "UIView+ChameleonPrivate.h" + +@implementation UIView (ChameleonPrivate) + +- (BOOL)isTopViewInWindow { + + if (!self.window) { + return NO; + } + + CGPoint centerPointInSelf = CGPointMake(CGRectGetMidX(self.bounds), + CGRectGetMidY(self.bounds)); + + CGPoint centerPointOfSelfInWindow = [self convertPoint:centerPointInSelf + toView:self.window]; + + UIView *view = [self.window findTopMostViewForPoint:centerPointOfSelfInWindow]; + BOOL isTopMost = view == self || [view isDescendantOfView:self]; + + return isTopMost; +} + +- (UIView *)findTopMostViewForPoint:(CGPoint)point { + + for (int i = (int)self.subviews.count - 1; i >= 0; i--) { + + UIView *subview = self.subviews[i]; + + if (!subview.hidden && CGRectContainsPoint(subview.frame, point) && subview.alpha > 0.01) { + CGPoint pointConverted = [self convertPoint:point toView:subview]; + return [subview findTopMostViewForPoint:pointConverted]; + } + } + + return self; +} + +@end diff --git a/Pods/ChameleonFramework/Pod/Classes/Objective-C/UIViewController+Chameleon.h b/Pods/ChameleonFramework/Pod/Classes/Objective-C/UIViewController+Chameleon.h new file mode 100755 index 00000000..f84b9456 --- /dev/null +++ b/Pods/ChameleonFramework/Pod/Classes/Objective-C/UIViewController+Chameleon.h @@ -0,0 +1,64 @@ +// +// UIViewController+Chameleon.h +// Chameleon +// +// Created by Vicc Alexander on 6/4/15. +// Copyright (c) 2015 Vicc Alexander. All rights reserved. +// + +#import +#import "ChameleonEnums.h" + +@interface UIViewController (Chameleon) + +/** + * Sets the color theme for the specified view controller using a primary color and the specified content style. + * + * @param primaryColor The primary color. + * @param contentStyle The contentStyle. + * + * @since 2.0 + */ +- (void)setThemeUsingPrimaryColor:(UIColor *)primaryColor + withContentStyle:(UIContentStyle)contentStyle; + +/** + * Sets the color theme for the specified view controller using a primary color, secondary color, and the specified content style. + * + * @param primaryColor The primary color. + * @param secondaryColor The secondary color. + * @param contentStyle The contentStyle. + * + * @since 2.0 + */ +- (void)setThemeUsingPrimaryColor:(UIColor *)primaryColor + withSecondaryColor:(UIColor *)secondaryColor + andContentStyle:(UIContentStyle)contentStyle; + +/** + * Sets the color theme for the specified view controller using a primary color, secondary color, font name, and the specified content style. + * + * @param primaryColor The primary color. + * @param secondaryColor The secondary color. + * @param fontName The main font to use for all text-based elements. + * @param contentStyle The contentStyle. + * + * @since 2.0 + */ +- (void)setThemeUsingPrimaryColor:(UIColor *)primaryColor + withSecondaryColor:(UIColor *)secondaryColor + usingFontName:(NSString *)fontName + andContentStyle:(UIContentStyle)contentStyle; + +/** + * Sets the status bar style for the specified @c UIViewController and all its child controllers. + * + * @param statusBarStyle The style of the device's status bar. + * + * @note Chameleon introduces a new @c statusBarStyle called @c UIStatusBarStyleContrast. + * + * @since 2.0 + */ +- (void)setStatusBarStyle:(UIStatusBarStyle)statusBarStyle; + +@end diff --git a/Pods/ChameleonFramework/Pod/Classes/Objective-C/UIViewController+Chameleon.m b/Pods/ChameleonFramework/Pod/Classes/Objective-C/UIViewController+Chameleon.m new file mode 100755 index 00000000..b6b4691f --- /dev/null +++ b/Pods/ChameleonFramework/Pod/Classes/Objective-C/UIViewController+Chameleon.m @@ -0,0 +1,900 @@ +// +// UIViewController+Chameleon.m +// Chameleon +// +// Created by Vicc Alexander on 6/4/15. +// Copyright (c) 2015 Vicc Alexander. All rights reserved. +// + +#import "UIViewController+Chameleon.h" +#import + +#import "ChameleonConstants.h" +#import "ChameleonEnums.h" +#import "ChameleonMacros.h" + +#import "NSArray+Chameleon.h" +#import "UIColor+Chameleon.h" +#import "UIViewController+Chameleon.h" +#import "UIView+ChameleonPrivate.h" +#import "UILabel+Chameleon.h" +#import "UIButton+Chameleon.h" +#import "UIAppearance+Swift.h" + +@interface UIViewController () + +@property (readwrite) BOOL shouldContrast; +@property (readwrite) BOOL shouldUseLightContent; + +@end + +@implementation UIViewController (Chameleon) + + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + +#pragma mark - Runtime + +- (void)setShouldContrast:(BOOL)contrast { + + NSNumber *number = [NSNumber numberWithBool:contrast]; + objc_setAssociatedObject(self, @selector(shouldContrast), number, OBJC_ASSOCIATION_RETAIN); +} + +- (BOOL)shouldContrast { + + NSNumber *number = objc_getAssociatedObject(self, @selector(shouldContrast)); + return [number boolValue]; +} + +- (void)setShouldUseLightContent:(BOOL)shouldUseLightContent { + + NSNumber *number = [NSNumber numberWithBool:shouldUseLightContent]; + objc_setAssociatedObject(self, @selector(shouldUseLightContent), number, OBJC_ASSOCIATION_RETAIN); +} + +- (BOOL)shouldUseLightContent { + + NSNumber *number = objc_getAssociatedObject(self, @selector(shouldUseLightContent)); + return [number boolValue]; +} + +#pragma mark - Swizzling + ++ (void)load { + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + + Class class = [self class]; + + SEL originalSelector = @selector(preferredStatusBarStyle); + SEL swizzledSelector = @selector(chameleon_preferredStatusBarStyle); + + Method originalMethod = class_getInstanceMethod(class, originalSelector); + Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector); + + BOOL didAddMethod = + class_addMethod(class, + originalSelector, + method_getImplementation(swizzledMethod), + method_getTypeEncoding(swizzledMethod)); + + if (didAddMethod) { + class_replaceMethod(class, + swizzledSelector, + method_getImplementation(originalMethod), + method_getTypeEncoding(originalMethod)); + + } else { + method_exchangeImplementations(originalMethod, swizzledMethod); + } + }); +} + +#pragma mark - Methods + + +- (void)setStatusBarStyle:(UIStatusBarStyle)statusBarStyle { + + if (statusBarStyle == UIStatusBarStyleContrast) { + + [self performSelector:@selector(setNeedsStatusBarAppearanceUpdate) withObject:nil afterDelay:0.01]; + self.shouldContrast = YES; + + } else { + + if (statusBarStyle == UIStatusBarStyleLightContent) { + + [self performSelector:@selector(setNeedsStatusBarAppearanceUpdate) withObject:nil afterDelay:0.01]; + self.shouldUseLightContent = YES; + + } else { + + [self performSelector:@selector(setNeedsStatusBarAppearanceUpdate) withObject:nil afterDelay:0.01]; + self.shouldUseLightContent = NO; + } + } + + [self preferredStatusBarStyle]; +} + +- (UIStatusBarStyle)chameleon_preferredStatusBarStyle { + + [self chameleon_preferredStatusBarStyle]; + + if (self.shouldContrast) { + + CGRect statusBarFrame = [UIApplication sharedApplication].statusBarFrame; + UIView *topView = [self.view findTopMostViewForPoint:CGPointMake(CGRectGetMidX(statusBarFrame), 2)]; + + return [self contrastingStatusBarStyleForColor:topView.backgroundColor]; + + } else { + + if (self.shouldUseLightContent) { + return UIStatusBarStyleLightContent; + + } else { + return [self chameleon_preferredStatusBarStyle]; + } + } +} + +- (void)setThemeUsingPrimaryColor:(UIColor *)primaryColor + withContentStyle:(UIContentStyle)contentStyle { + + if (contentStyle == UIContentStyleContrast) { + + if ([ContrastColor(primaryColor, YES) isEqual:FlatWhite]) { + [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent]; + } else { + [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault]; + } + + } else if (contentStyle == UIContentStyleLight) { + + [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent]; + + } else { + + [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault]; + } + + [[self class] customizeBarButtonItemWithPrimaryColor:primaryColor contentStyle:contentStyle]; + [[self class] customizeButtonWithPrimaryColor:primaryColor withContentStyle:contentStyle]; + [[self class] customizeNavigationBarWithPrimaryColor:primaryColor withContentStyle:contentStyle]; + [[self class] customizePageControlWithPrimaryColor:primaryColor withContentStyle:contentStyle]; + [[self class] customizeProgressViewWithPrimaryColor:primaryColor withContentStyle:contentStyle]; + [[self class] customizeSearchBarWithPrimaryColor:primaryColor withContentStyle:contentStyle]; + [[self class] customizeSegmentedControlWithPrimaryColor:primaryColor withContentStyle:contentStyle]; + [[self class] customizeSliderWithPrimaryColor:primaryColor withContentStyle:contentStyle]; + [[self class] customizeStepperWithPrimaryColor:primaryColor withContentStyle:contentStyle]; + [[self class] customizeSwitchWithPrimaryColor:primaryColor]; + [[self class] customizeTabBarWithBarTintColor:FlatWhite andTintColor:primaryColor]; + [[self class] customizeToolbarWithPrimaryColor:primaryColor withContentStyle:contentStyle]; + [[self class] customizeImagePickerControllerWithPrimaryColor:primaryColor withContentStyle:contentStyle]; +} + +- (void)setThemeUsingPrimaryColor:(UIColor *)primaryColor + withSecondaryColor:(UIColor *)secondaryColor + andContentStyle:(UIContentStyle)contentStyle { + + if (contentStyle == UIContentStyleContrast) { + + if ([ContrastColor(primaryColor, YES) isEqual:FlatWhite]) { + [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent]; + } else { + [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault]; + } + + } else if (contentStyle == UIContentStyleLight) { + + [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent]; + + } else { + + [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault]; + } + + [[self class] customizeBarButtonItemWithPrimaryColor:primaryColor contentStyle:contentStyle]; + [[self class] customizeButtonWithPrimaryColor:primaryColor secondaryColor:secondaryColor withContentStyle:contentStyle]; + [[self class] customizeNavigationBarWithPrimaryColor:primaryColor withContentStyle:contentStyle]; + [[self class] customizePageControlWithPrimaryColor:primaryColor withContentStyle:contentStyle]; + [[self class] customizeProgressViewWithPrimaryColor:primaryColor andSecondaryColor:secondaryColor]; + [[self class] customizeSearchBarWithPrimaryColor:primaryColor withContentStyle:contentStyle]; + [[self class] customizeSegmentedControlWithPrimaryColor:primaryColor withContentStyle:contentStyle]; + [[self class] customizeSliderWithPrimaryColor:primaryColor andSecondaryColor:secondaryColor]; + [[self class] customizeStepperWithPrimaryColor:primaryColor withContentStyle:contentStyle]; + [[self class] customizeSwitchWithPrimaryColor:primaryColor andSecondaryColor:secondaryColor]; + [[self class] customizeTabBarWithBarTintColor:FlatWhite andTintColor:primaryColor]; + [[self class] customizeToolbarWithPrimaryColor:primaryColor withContentStyle:contentStyle]; + [[self class] customizeImagePickerControllerWithPrimaryColor:primaryColor withContentStyle:contentStyle]; +} + +- (void)setThemeUsingPrimaryColor:(UIColor *)primaryColor + withSecondaryColor:(UIColor *)secondaryColor + usingFontName:(NSString *)fontName + andContentStyle:(UIContentStyle)contentStyle { + + if (contentStyle == UIContentStyleContrast) { + + if ([ContrastColor(primaryColor, YES) isEqual:FlatWhite]) { + [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent]; + } else { + [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault]; + } + + } else if (contentStyle == UIContentStyleLight) { + + [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent]; + + } else { + + [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault]; + } + + [[UILabel appearance] setSubstituteFontName:fontName]; + [[UIButton appearance] setSubstituteFontName:fontName]; + + [[self class] customizeButtonWithPrimaryColor:primaryColor secondaryColor:secondaryColor withContentStyle:contentStyle]; + [[self class] customizeBarButtonItemWithPrimaryColor:primaryColor fontName:fontName fontSize:18 contentStyle:contentStyle]; + [[self class] customizeNavigationBarWithBarColor:primaryColor textColor:ContrastColor(primaryColor, YES) fontName:fontName fontSize:20 buttonColor:ContrastColor(primaryColor, YES)]; + [[self class] customizePageControlWithPrimaryColor:primaryColor withContentStyle:contentStyle]; + [[self class] customizeProgressViewWithPrimaryColor:primaryColor andSecondaryColor:secondaryColor]; + [[self class] customizeSearchBarWithPrimaryColor:primaryColor withContentStyle:contentStyle]; + [[self class] customizeSegmentedControlWithPrimaryColor:primaryColor withFontName:fontName withFontSize:14 withContentStyle:contentStyle]; + [[self class] customizeSliderWithPrimaryColor:primaryColor andSecondaryColor:secondaryColor]; + [[self class] customizeStepperWithPrimaryColor:primaryColor withContentStyle:contentStyle]; + [[self class] customizeSwitchWithPrimaryColor:primaryColor andSecondaryColor:secondaryColor]; + [[self class] customizeTabBarWithBarTintColor:FlatWhite andTintColor:primaryColor]; + [[self class] customizeToolbarWithPrimaryColor:primaryColor withContentStyle:contentStyle]; + [[self class] customizeImagePickerControllerWithPrimaryColor:primaryColor withContentStyle:contentStyle]; +} + +#pragma mark - UIBarButtonItem + ++ (void)customizeBarButtonItemWithPrimaryColor:(UIColor *)primaryColor + contentStyle:(UIContentStyle)contentStyle { + + UIColor *contentColor; + switch (contentStyle) { + case UIContentStyleContrast: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + case UIContentStyleLight: { + contentColor = [UIColor whiteColor]; + break; + } + case UIContentStyleDark: { + contentColor = FlatBlackDark; + break; + } + default: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + } + + [[UIBarButtonItem appearance] setTintColor:primaryColor]; + [[UIBarButtonItem appearanceWhenContainedIn:[UISearchBar class], nil] setTintColor:contentColor]; + [[UIBarButtonItem appearanceWhenContainedIn:[UINavigationBar class], nil] setTintColor:contentColor]; + [[UIBarButtonItem appearanceWhenContainedIn:[UIToolbar class], nil] setTintColor:contentColor]; +} + ++ (void)customizeBarButtonItemWithPrimaryColor:(UIColor *)primaryColor + fontName:(NSString *)fontName + fontSize:(float)fontSize + contentStyle:(UIContentStyle)contentStyle { + + UIColor *contentColor; + switch (contentStyle) { + case UIContentStyleContrast: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + case UIContentStyleLight: { + contentColor = [UIColor whiteColor]; + break; + } + case UIContentStyleDark: { + contentColor = FlatBlackDark; + break; + } + default: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + } + + [[UIBarButtonItem appearance] setTintColor:primaryColor]; + [[UIBarButtonItem appearanceWhenContainedIn:[UISearchBar class], nil] setTintColor:contentColor]; + [[UIBarButtonItem appearanceWhenContainedIn:[UINavigationBar class], nil] setTintColor:contentColor]; + [[UIBarButtonItem appearanceWhenContainedIn:[UIToolbar class], nil] setTintColor:contentColor]; + + + if ([UIFont fontWithName:fontName size:fontSize]) { + [[UIBarButtonItem appearance] setTitleTextAttributes:@{ NSForegroundColorAttributeName:contentColor, NSFontAttributeName:[UIFont fontWithName:fontName size:fontSize]} forState:UIControlStateNormal]; + } +} + +#pragma mark - UIButton + ++ (void)customizeButtonWithPrimaryColor:(UIColor *)primaryColor + withContentStyle:(UIContentStyle)contentStyle { + + UIColor *contentColor; + switch (contentStyle) { + case UIContentStyleContrast: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + case UIContentStyleLight: { + contentColor = [UIColor whiteColor]; + break; + } + case UIContentStyleDark: { + contentColor = FlatBlackDark; + break; + } + default: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + } + + [[UIButton appearance] setTintColor:contentColor]; + [[UIButton appearance] setBackgroundColor:primaryColor]; + + + [[UIButton appearanceWhenContainedIn:[UISearchBar class], nil] setTintColor:contentColor]; + [[UIButton appearanceWhenContainedIn:[UISearchBar class], nil] setBackgroundColor:ClearColor]; + + [[UIButton appearanceWhenContainedIn:[UINavigationBar class], nil] setTintColor:contentColor]; + [[UIButton appearanceWhenContainedIn:[UINavigationBar class], nil] setBackgroundColor:ClearColor]; + + [[UIButton appearanceWhenContainedIn:[UIToolbar class], nil] setTintColor:contentColor]; + [[UIButton appearanceWhenContainedIn:[UIToolbar class], nil] setBackgroundColor:ClearColor]; + + [[UIButton appearanceWhenContainedIn:[UIStepper class], nil] setTintColor:primaryColor]; + [[UIButton appearanceWhenContainedIn:[UIStepper class], nil] setBackgroundColor:ClearColor]; + + [[UIButton appearance] setTitleShadowColor:ClearColor forState:UIControlStateNormal]; + +} + ++ (void)customizeButtonWithPrimaryColor:(UIColor *)primaryColor + secondaryColor:(UIColor *)secondaryColor + withContentStyle:(UIContentStyle)contentStyle { + + UIColor *contentColor; + UIColor *secondaryContentColor; + switch (contentStyle) { + case UIContentStyleContrast: { + contentColor = ContrastColor(primaryColor, NO); + secondaryContentColor = ContrastColor(secondaryColor, NO); + break; + } + case UIContentStyleLight: { + contentColor = [UIColor whiteColor]; + secondaryContentColor = [UIColor whiteColor]; + break; + } + case UIContentStyleDark: { + contentColor = FlatBlackDark; + secondaryContentColor = FlatBlackDark; + break; + } + default: { + contentColor = ContrastColor(primaryColor, NO); + secondaryContentColor = ContrastColor(secondaryColor, NO); + break; + } + } + + [[UIButton appearance] setTintColor:secondaryContentColor]; + [[UIButton appearance] setBackgroundColor:secondaryColor]; + + + [[UIButton appearanceWhenContainedIn:[UISearchBar class], nil] setTintColor:contentColor]; + [[UIButton appearanceWhenContainedIn:[UISearchBar class], nil] setBackgroundColor:ClearColor]; + + [[UIButton appearanceWhenContainedIn:[UINavigationBar class], nil] setTintColor:contentColor]; + [[UIButton appearanceWhenContainedIn:[UINavigationBar class], nil] setBackgroundColor:ClearColor]; + + [[UIButton appearanceWhenContainedIn:[UIToolbar class], nil] setTintColor:contentColor]; + [[UIButton appearanceWhenContainedIn:[UIToolbar class], nil] setBackgroundColor:ClearColor]; + + [[UIButton appearanceWhenContainedIn:[UIStepper class], nil] setTintColor:primaryColor]; + [[UIButton appearanceWhenContainedIn:[UIStepper class], nil] setBackgroundColor:ClearColor]; + + [[UIButton appearance] setTitleShadowColor:ClearColor forState:UIControlStateNormal]; + +} + +#pragma mark - UIImagePickerController + ++ (void)customizeImagePickerControllerWithPrimaryColor:(UIColor *)primaryColor withContentStyle:(UIContentStyle)contentStyle { + + UIColor *contentColor; + switch (contentStyle) { + case UIContentStyleContrast: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + case UIContentStyleLight: { + contentColor = [UIColor whiteColor]; + break; + } + case UIContentStyleDark: { + contentColor = FlatBlackDark; + break; + } + default: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + } + + //Workaround for Swift http://stackoverflow.com/a/28765193 + [[UIButton appearanceWhenContainedWithin:@[[UIView class],[UIImagePickerController class]]] setBackgroundColor:ClearColor]; + [[UIButton appearanceWhenContainedWithin:@[[UIView class],[UIImagePickerController class]]] setTintColor:ClearColor]; + [[UIButton appearanceWhenContainedWithin:@[[UINavigationBar class],[UIImagePickerController class]]] setBackgroundColor:ClearColor]; + [[UIButton appearanceWhenContainedWithin:@[[UINavigationBar class],[UIImagePickerController class]]] setTintColor:contentColor]; + [[UIButton appearanceWhenContainedWithin:@[[UITableViewCell class],[UIImagePickerController class]]] setBackgroundColor:ClearColor]; + + //[[UIButton appearanceWhenContainedInInstancesOfClasses:@[[UIView class],[UIImagePickerController class]]] setBackgroundColor:ClearColor]; + //[[UIButton appearanceWhenContainedInInstancesOfClasses:@[[UIView class],[UIImagePickerController class]]] setTintColor:contentColor]; + //[[UIButton appearanceWhenContainedInInstancesOfClasses:@[[UINavigationBar class],[UIImagePickerController class]]] setBackgroundColor:ClearColor]; + //[[UIButton appearanceWhenContainedInInstancesOfClasses:@[[UINavigationBar class],[UIImagePickerController class]]] setTintColor:contentColor]; + //[[UIButton appearanceWhenContainedInInstancesOfClasses:@[[UITableViewCell class],[UIImagePickerController class]]] setBackgroundColor:ClearColor]; +} + +#pragma mark - UILabel + ++ (void)customizeLabelWithPrimaryColor:(UIColor *)primaryColor + fontName:(NSString *)fontName + fontSize:(CGFloat)fontSize + withContentStyle:(UIContentStyle)contentStyle { + + UIColor *contentColor; + switch (contentStyle) { + case UIContentStyleContrast: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + case UIContentStyleLight: { + contentColor = [UIColor whiteColor]; + break; + } + case UIContentStyleDark: { + contentColor = FlatBlackDark; + break; + } + default: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + } + + [[UILabel appearanceWhenContainedIn:[self class], [UINavigationBar class], nil] setTextColor:contentColor]; + [[UILabel appearanceWhenContainedIn:[self class], [UIToolbar class], nil] setTextColor:contentColor]; + + UIFont *font = [UIFont fontWithName:fontName size:fontSize]; + + if (font) { + [[UILabel appearanceWhenContainedIn:[self class], nil] setFont:[UIFont fontWithName:fontName size:fontSize]]; + [[UILabel appearanceWhenContainedIn:[self class], [UITextField class], nil] setFont:[UIFont fontWithName:fontName size:14]]; + [[UILabel appearanceWhenContainedIn:[self class], [UIButton class], nil] setFont:[UIFont fontWithName:fontName size:18]]; + } +} + +#pragma mark - UINavigationBar + ++ (void)customizeNavigationBarWithPrimaryColor:(UIColor *)primaryColor + withContentStyle:(UIContentStyle)contentStyle { + + UIColor *contentColor; + switch (contentStyle) { + case UIContentStyleContrast: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + case UIContentStyleLight: { + contentColor = [UIColor whiteColor]; + break; + } + case UIContentStyleDark: { + contentColor = FlatBlackDark; + break; + } + default: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + } + + [[UINavigationBar appearanceWhenContainedIn:[self class], nil] setBarTintColor:primaryColor]; + [[UINavigationBar appearanceWhenContainedIn:[self class], nil] setTintColor:contentColor]; + [[UINavigationBar appearanceWhenContainedIn:[self class], nil] setTitleTextAttributes:@{NSForegroundColorAttributeName:contentColor}]; + [[UINavigationBar appearanceWhenContainedIn:[self class], nil] setShadowImage:[UIImage new]]; +// [[UINavigationBar appearanceWhenContainedIn:[self class], nil] setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault]; +} + ++ (void)customizeNavigationBarWithBarColor:(UIColor *)barColor + textColor:(UIColor *)textColor + buttonColor:(UIColor *)buttonColor { + + [[UINavigationBar appearanceWhenContainedIn:[self class], nil] setBarTintColor:barColor]; + [[UINavigationBar appearanceWhenContainedIn:[self class], nil] setTintColor:buttonColor]; + [[UINavigationBar appearanceWhenContainedIn:[self class], nil] setTitleTextAttributes:@{NSForegroundColorAttributeName:textColor}]; + [[UINavigationBar appearanceWhenContainedIn:[self class], nil] setShadowImage:[UIImage new]]; +// [[UINavigationBar appearanceWhenContainedIn:[self class], nil] setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault]; +} + ++ (void)customizeNavigationBarWithBarColor:(UIColor *)barColor + textColor:(UIColor *)textColor + fontName:(NSString *)fontName + fontSize:(CGFloat)fontSize + buttonColor:(UIColor *)buttonColor { + + [[UINavigationBar appearanceWhenContainedIn:[self class], nil] setBarTintColor:barColor]; + [[UINavigationBar appearanceWhenContainedIn:[self class], nil] setTintColor:buttonColor]; + [[UINavigationBar appearanceWhenContainedIn:[self class], nil] setShadowImage:[UIImage new]]; +// [[UINavigationBar appearanceWhenContainedIn:[self class], nil] setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault]; + + if ([UIFont fontWithName:fontName size:fontSize]) { + [[UINavigationBar appearanceWhenContainedIn:[self class], nil] setTitleTextAttributes:@{ NSForegroundColorAttributeName:textColor, NSFontAttributeName:[UIFont fontWithName:fontName size:fontSize] }]; + } +} + +#pragma mark - UIPageControl + ++ (void)customizePageControlWithPrimaryColor:(UIColor *)primaryColor + withContentStyle:(UIContentStyle)contentStyle { + + UIColor *contentColor; + switch (contentStyle) { + case UIContentStyleContrast: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + case UIContentStyleLight: { + contentColor = [UIColor whiteColor]; + break; + } + case UIContentStyleDark: { + contentColor = FlatBlackDark; + break; + } + default: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + } + + [[UIPageControl appearanceWhenContainedIn:[self class], nil] setCurrentPageIndicatorTintColor:primaryColor]; + [[UIPageControl appearanceWhenContainedIn:[self class], nil] setPageIndicatorTintColor:[primaryColor colorWithAlphaComponent:0.4]]; + [[UIPageControl appearanceWhenContainedIn:[self class], [UINavigationBar class], nil] setCurrentPageIndicatorTintColor:contentColor]; + [[UIPageControl appearanceWhenContainedIn:[self class], [UINavigationBar class], nil] setPageIndicatorTintColor:[contentColor colorWithAlphaComponent:0.4]]; + [[UIPageControl appearanceWhenContainedIn:[self class], [UIToolbar class], nil] setCurrentPageIndicatorTintColor:contentColor]; + [[UIPageControl appearanceWhenContainedIn:[self class], [UIToolbar class], nil] setPageIndicatorTintColor:[contentColor colorWithAlphaComponent:0.4]]; +} + +#pragma mark - UIProgressView + ++ (void)customizeProgressViewWithPrimaryColor:(UIColor *)primaryColor + withContentStyle:(UIContentStyle)contentStyle { + + UIColor *contentColor; + switch (contentStyle) { + case UIContentStyleContrast: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + case UIContentStyleLight: { + contentColor = [UIColor whiteColor]; + break; + } + case UIContentStyleDark: { + contentColor = FlatBlackDark; + break; + } + default: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + } + + [[UIProgressView appearanceWhenContainedIn:[self class], nil] setProgressTintColor:primaryColor]; + [[UIProgressView appearanceWhenContainedIn:[self class], [UINavigationBar class], nil] setProgressTintColor:contentColor]; + [[UIProgressView appearanceWhenContainedIn:[self class], [UIToolbar class], nil] setProgressTintColor:contentColor]; + [[UIProgressView appearanceWhenContainedIn:[self class], nil] setTrackTintColor:[UIColor lightGrayColor]]; + [[UIProgressView appearanceWhenContainedIn:[self class], [UINavigationBar class], nil] setTrackTintColor:[[primaryColor darkenByPercentage:0.25] flatten]]; + [[UIProgressView appearanceWhenContainedIn:[self class], [UIToolbar class], nil] setTrackTintColor:[[primaryColor darkenByPercentage:0.25] flatten]]; +} + ++ (void)customizeProgressViewWithPrimaryColor:(UIColor *)primaryColor + andSecondaryColor:(UIColor *)secondaryColor { + + [[UIProgressView appearanceWhenContainedIn:[self class], nil] setProgressTintColor:secondaryColor]; + [[UIProgressView appearanceWhenContainedIn:[self class], [UINavigationBar class], nil] setProgressTintColor:secondaryColor]; + [[UIProgressView appearanceWhenContainedIn:[self class], [UIToolbar class], nil] setProgressTintColor:secondaryColor]; + [[UIProgressView appearanceWhenContainedIn:[self class], nil] setTrackTintColor:[UIColor lightGrayColor]]; + [[UIProgressView appearanceWhenContainedIn:[self class], [UINavigationBar class], nil] setTrackTintColor:[[primaryColor darkenByPercentage:0.25] flatten]]; + [[UIProgressView appearanceWhenContainedIn:[self class], [UIToolbar class], nil] setTrackTintColor:[[primaryColor darkenByPercentage:0.25] flatten]]; +} + +#pragma mark - UISearchBar + ++ (void)customizeSearchBarWithPrimaryColor:(UIColor *)primaryColor withContentStyle:(UIContentStyle)contentStyle { + + UIColor *contentColor; + switch (contentStyle) { + case UIContentStyleContrast: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + case UIContentStyleLight: { + contentColor = [UIColor whiteColor]; + break; + } + case UIContentStyleDark: { + contentColor = FlatBlackDark; + break; + } + default: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + } + + [[UISearchBar appearanceWhenContainedIn:[self class], nil] setBarTintColor:primaryColor]; + [[UISearchBar appearanceWhenContainedIn:[self class], nil] setBackgroundColor:primaryColor]; + [[UISearchBar appearanceWhenContainedIn:[self class], nil] setTintColor:contentColor]; + [[UISearchBar appearanceWhenContainedIn:[self class], nil] setBackgroundImage:[UIImage new] forBarPosition:UIBarPositionAny barMetrics:UIBarMetricsDefault]; +} + +#pragma mark - UISegmentedControl + ++ (void)customizeSegmentedControlWithPrimaryColor:(UIColor *)primaryColor + withContentStyle:(UIContentStyle)contentStyle { + + UIColor *contentColor; + switch (contentStyle) { + case UIContentStyleContrast: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + case UIContentStyleLight: { + contentColor = [UIColor whiteColor]; + break; + } + case UIContentStyleDark: { + contentColor = FlatBlackDark; + break; + } + default: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + } + + [[UISegmentedControl appearanceWhenContainedIn:[self class], nil] setTintColor:primaryColor]; + [[UISegmentedControl appearanceWhenContainedIn:[self class], [UINavigationBar class], nil] + setTintColor:contentColor]; + [[UISegmentedControl appearanceWhenContainedIn:[self class], [UIToolbar class], nil] + setTintColor:contentColor]; +} + ++ (void)customizeSegmentedControlWithPrimaryColor:(UIColor *)primaryColor + withFontName:(NSString *)fontName + withFontSize:(CGFloat)fontSize + withContentStyle:(UIContentStyle)contentStyle { + + UIColor *contentColor; + switch (contentStyle) { + case UIContentStyleContrast: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + case UIContentStyleLight: { + contentColor = [UIColor whiteColor]; + break; + } + case UIContentStyleDark: { + contentColor = FlatBlackDark; + break; + } + default: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + } + + [[UISegmentedControl appearanceWhenContainedIn:[self class], nil] setTintColor:primaryColor]; + [[UISegmentedControl appearanceWhenContainedIn:[self class], [UINavigationBar class], nil] + setTintColor:contentColor]; + [[UISegmentedControl appearanceWhenContainedIn:[self class], [UIToolbar class], nil] + setTintColor:contentColor]; + + UIFont *font = [UIFont fontWithName:fontName size:fontSize]; + if (font) { + [[UISegmentedControl appearanceWhenContainedIn:[self class], nil] setTitleTextAttributes:@{NSFontAttributeName:font} + forState:UIControlStateNormal]; + } +} + +#pragma mark - UISlider + ++ (void)customizeSliderWithPrimaryColor:(UIColor *)primaryColor + withContentStyle:(UIContentStyle)contentStyle { + + UIColor *contentColor; + switch (contentStyle) { + case UIContentStyleContrast: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + case UIContentStyleLight: { + contentColor = [UIColor whiteColor]; + break; + } + case UIContentStyleDark: { + contentColor = FlatBlackDark; + break; + } + default: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + } + + [[UISlider appearanceWhenContainedIn:[self class], nil] setMinimumTrackTintColor:primaryColor]; + [[UISlider appearanceWhenContainedIn:[self class], [UINavigationBar class], nil] setMinimumTrackTintColor:contentColor]; + [[UISlider appearanceWhenContainedIn:[self class], [UIToolbar class], nil] setMinimumTrackTintColor:contentColor]; + [[UISlider appearanceWhenContainedIn:[self class], nil] setMaximumTrackTintColor:[UIColor lightGrayColor]]; + [[UISlider appearanceWhenContainedIn:[self class], [UINavigationBar class], nil] setMaximumTrackTintColor:[[primaryColor darkenByPercentage:0.25] flatten]]; + [[UISlider appearanceWhenContainedIn:[self class], [UIToolbar class], nil] setMaximumTrackTintColor:[[primaryColor darkenByPercentage:0.25] flatten]]; +} + ++ (void)customizeSliderWithPrimaryColor:(UIColor *)primaryColor + andSecondaryColor:(UIColor *)secondaryColor { + + [[UISlider appearanceWhenContainedIn:[self class], nil] setMinimumTrackTintColor:secondaryColor]; + [[UISlider appearanceWhenContainedIn:[self class], [UINavigationBar class], nil] setMinimumTrackTintColor:secondaryColor]; + [[UISlider appearanceWhenContainedIn:[self class], [UIToolbar class], nil] setMinimumTrackTintColor:secondaryColor]; + [[UISlider appearanceWhenContainedIn:[self class], nil] setMaximumTrackTintColor:[UIColor lightGrayColor]]; + [[UISlider appearanceWhenContainedIn:[self class], [UINavigationBar class], nil] setMaximumTrackTintColor:[[primaryColor darkenByPercentage:0.25] flatten]]; + [[UISlider appearanceWhenContainedIn:[self class], [UIToolbar class], nil] setMaximumTrackTintColor:[[primaryColor darkenByPercentage:0.25] flatten]]; +} + +#pragma mark - UIStepper + ++ (void)customizeStepperWithPrimaryColor:(UIColor *)primaryColor + withContentStyle:(UIContentStyle)contentStyle { + + UIColor *contentColor; + switch (contentStyle) { + case UIContentStyleContrast: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + case UIContentStyleLight: { + contentColor = [UIColor whiteColor]; + break; + } + case UIContentStyleDark: { + contentColor = FlatBlackDark; + break; + } + default: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + } + + [[UIStepper appearanceWhenContainedIn:[self class], nil] setTintColor:primaryColor]; + [[UIStepper appearanceWhenContainedIn:[self class], [UINavigationBar class], nil] + setTintColor:contentColor]; + [[UIStepper appearanceWhenContainedIn:[self class], [UIToolbar class], nil] + setTintColor:contentColor]; +} + +#pragma mark - UISwitch + ++ (void)customizeSwitchWithPrimaryColor:(UIColor *)primaryColor { + + [[UISwitch appearanceWhenContainedIn:[self class], nil] setOnTintColor:primaryColor]; + [[UISwitch appearanceWhenContainedIn:[self class], [UINavigationBar class], nil] setOnTintColor:[[primaryColor darkenByPercentage:0.25] flatten]]; + [[UISwitch appearanceWhenContainedIn:[self class], [UIToolbar class], nil] setOnTintColor:[[primaryColor darkenByPercentage:0.25] flatten]]; +} + ++ (void)customizeSwitchWithPrimaryColor:(UIColor *)primaryColor + andSecondaryColor:(UIColor *)secondaryColor { + + [[UISwitch appearanceWhenContainedIn:[self class], nil] setOnTintColor:secondaryColor]; + [[UISwitch appearanceWhenContainedIn:[self class], [UINavigationBar class], nil] setOnTintColor:secondaryColor]; + [[UISwitch appearanceWhenContainedIn:[self class], [UIToolbar class], nil] setOnTintColor:secondaryColor]; +} + +#pragma mark - UITabBar + ++ (void)customizeTabBarWithBarTintColor:(UIColor *)barTintColor + andTintColor:(UIColor *)tintColor { + + [[UITabBar appearanceWhenContainedIn:[self class], nil] setBarTintColor:barTintColor]; + [[UITabBar appearanceWhenContainedIn:[self class], nil] setTintColor:tintColor]; +} + ++ (void)customizeTabBarWithBarTintColor:(UIColor *)barTintColor + tintColor:(UIColor *)tintColor + fontName:(NSString *)fontName + fontSize:(CGFloat)fontSize { + + [[UITabBar appearanceWhenContainedIn:[self class], nil] setBarTintColor:barTintColor]; + [[UITabBar appearanceWhenContainedIn:[self class], nil] setTintColor:tintColor]; + + UIFont *font = [UIFont fontWithName:fontName size:fontSize]; + if (font) { + [[UITabBarItem appearanceWhenContainedIn:[self class], nil] setTitleTextAttributes:@{NSFontAttributeName:font} + forState:UIControlStateNormal]; + } +} + +#pragma mark - UIToolbar + ++ (void)customizeToolbarWithPrimaryColor:(UIColor *)primaryColor + withContentStyle:(UIContentStyle)contentStyle { + + UIColor *contentColor; + switch (contentStyle) { + case UIContentStyleContrast: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + case UIContentStyleLight: { + contentColor = [UIColor whiteColor]; + break; + } + case UIContentStyleDark: { + contentColor = FlatBlackDark; + break; + } + default: { + contentColor = ContrastColor(primaryColor, NO); + break; + } + } + + [[UIToolbar appearanceWhenContainedIn:[self class], nil] setTintColor:contentColor]; + [[UIToolbar appearanceWhenContainedIn:[self class], nil] setBarTintColor:primaryColor]; + [[UIToolbar appearanceWhenContainedIn:[self class], nil] setClipsToBounds:YES]; +} + + +#pragma mark - Private Methods + +- (UIStatusBarStyle)contrastingStatusBarStyleForColor:(UIColor *)backgroundColor { + + //Calculate Luminance + CGFloat luminance; + CGFloat red, green, blue; + + //Check for clear or uncalculatable color and assume white + if (![backgroundColor getRed:&red green:&green blue:&blue alpha:nil]) { + return UIStatusBarStyleDefault; + } + + //Relative luminance in colorimetric spaces - http://en.wikipedia.org/wiki/Luminance_(relative) + red *= 0.2126f; green *= 0.7152f; blue *= 0.0722f; + luminance = red + green + blue; + + return (luminance > 0.6f) ? UIStatusBarStyleDefault : UIStatusBarStyleLightContent; +} + +#pragma GCC diagnostic pop + +@end diff --git a/Pods/ChameleonFramework/README.md b/Pods/ChameleonFramework/README.md new file mode 100644 index 00000000..2dbbdf0d --- /dev/null +++ b/Pods/ChameleonFramework/README.md @@ -0,0 +1,768 @@ +

+ Chameleon by Vicc Alexander +

+ +

+ Downloads + Platform: iOS 8+ + Language: Swift 2 + Carthage compatible + Cocoapods compatible + License: MIT

+ Donate +

+ +## Introduction + +**Chameleon** is a lightweight, yet powerful, color framework for iOS (Objective-C & Swift). It is built on the idea that software applications should function effortlessly while simultaneously maintaining their beautiful interfaces. + +With Chameleon, you can easily stop tinkering with RGB values, wasting hours figuring out the right color combinations to use in your app, and worrying about whether your text will be readable on the various background colors of your app. + +### Features + +

+ Features +

+ +### App Showcase ![New](http://i.imgur.com/BX3b9ES.png) + +###### In an upcoming update we'll begin showcasing some of the best apps and companies making use of Chameleon. If you'd like to see your app featured in this section, make sure to add it [here](https://airtable.com/shrr1WK6dLQBZfXV0). + +## Table of Contents +[● Product Features](https://github.com/ViccAlexander/Chameleon#-product-features) +[● Requirements](https://github.com/ViccAlexander/Chameleon#%EF%B8%8F-requirements) +[● License](https://github.com/ViccAlexander/Chameleon#-license) +[● Contributions](https://github.com/ViccAlexander/Chameleon#-contributions) +[● Documentation](https://github.com/ViccAlexander/Chameleon#-documentation) +[● Storyboard Add-On](https://github.com/ViccAlexander/Chameleon#storyboard-add-on) +[● Author](https://github.com/ViccAlexander/Chameleon#-author) +[● Special Thanks](https://github.com/ViccAlexander/Chameleon#-special-thanks) +[● To Do List](https://github.com/ViccAlexander/Chameleon#-to-do-list) +[● Change Log](https://github.com/ViccAlexander/Chameleon#-change-log) + + + +## 🌟 Product Features + +### 100% Flat & Gorgeous + +Chameleon features over 24 hand-picked colors that come in both light and dark shades. + +

+ Swatches +

+ +### Flat Color Schemes + +Chameleon equips you with 3 different classes of flat color schemes that can be generated from a flat or non-flat color. *In the examples below, the white stars indicate the color used to generate the schemes.* + +###### Analogous Flat Color Scheme + +

+ Analogous Scheme +

+ +###### Complementary Flat Color Scheme +

+ Complementary Scheme +

+ +###### Triadic Flat Color Scheme +

+ Triadic Scheme +

+ +### Contrasting Text +With a plethora of color choices available for text, it's difficult to choose one that all users will appreciate and be able to read. Whether you're in doubt of your text and tint color choices, or afraid to let users customize their profile colors because it may disturb the legibility or usability of the app, you no longer have to worry. With Chameleon, you can ensure that all text stands out independent of the background color. + +Oh... Chameleon works with the status bar as well. : ) + +

+ Status Bar +

+ +### Themes ![Beta](http://i.imgur.com/JyYiUJq.png) + +Chameleon now allows you easily theme your app with as little as **one line of code**. You can set a theme for all your views, and for specific views as well. + +

+ Themes +

+ +### Colors From Images + +Chameleon allows you to seamlessly extract non-flat or flat color schemes from images without hassle. You can also generate the average color from an image with ease. You can now mold the UI colors of a profile, or product based on an image! + +

+ Colors from images +

+ +### Gradient Colors +With iOS 7 & 8, Apple mainstreamed flat colors. Now, with the release of iOS 9, Chameleon strives to elevate the game once more. Say hello to gradient colors. Using one line of code, you can easily set any object's color properties to a gradient (background colors, text colors, tint colors, etc). Other features, like Chameleon's contrasting feature, can also be applied to create a seamless product. Experimentation is encouraged, and gutsiness is applauded! + +

+ Gradients +

+ +![](http://i.imgur.com/2jN72eh.png) + +### Xcode Quick Help Documentation + +Chameleon's documentation, while written as clearly and concisely as possible may still render some slightly confused. But don't fret! Staying true to our vision of simplifying the entire color process, we added Xcode Quick Help's Documentation Support! Simply highlight a Chameleon method or tap it with three fingers to find out more about what it is and what it does! + +

+ Xcode Quick Help Documentation +

+ +### Storyboard Palette + +If you're like me and love to use storyboard, Chameleon's got you covered. We've provided you with a quick and easy way to access Chameleon colors right from Storyboard, and any other app that uses the color picker (i.e. TextEdit). + +

+ Chameleon Palette +

+ +## ⚠️ Requirements + +* Objective-C or Swift +* Requires a minimum of iOS 7.0 for Objective-C (No active development for anything earlier, but may work with 6.0) and a minimum of iOS 8.0 for Swift. +* Requires Xcode 6.3 for use in any iOS Project + +## 🔑 License +Chameleon is released and distributed under the terms and conditions of the [MIT license](https://github.com/ViccAlexander/Chameleon/blob/master/LICENSE.md). + +## 👥 Contributions +If you run into problems, please open up an issue. We also actively welcome pull requests. By contributing to Chameleon you agree that your contributions will be licensed under its MIT license. + +If you use Chameleon in your app we would love to hear about it! Drop Vicc a line on [twitter](http://twitter.com/viccsmind). + +## 📗 Documentation +All methods, properties, and types available in Chameleon are documented below. + +#####Documentation Table of Contents +[● Installation](https://github.com/ViccAlexander/Chameleon#installation) +[● Storyboard-Add On](https://github.com/ViccAlexander/Chameleon#storyboard-add-on-) +[● Usage](https://github.com/ViccAlexander/Chameleon#usage) +[● UIColor Methods](https://github.com/ViccAlexander/Chameleon#uicolor-methods) +[● Colors From Images](https://github.com/ViccAlexander/Chameleon#colors-from-images--1) +[● UIStatusBarStyle Methods](https://github.com/ViccAlexander/Chameleon#uistatusbarstyle-methods) +[● Color Scheme Methods](https://github.com/ViccAlexander/Chameleon#color-schemes-methods) +[● Theme Methods](https://github.com/ViccAlexander/Chameleon#theme-methods-) + +###Installation +####CocoaPods Installation +Chameleon is now available on [CocoaPods](http://cocoapods.org). Simply add the following to your project Podfile, and you'll be good to go. + +######Objective-C +```ruby +use_frameworks! + +pod 'ChameleonFramework' +``` +######Swift +```ruby +use_frameworks! + +pod 'ChameleonFramework/Swift' +``` + +###### **Note:** Swift support for Chameleon 2.0 is almost complete. + +======= +####Carthage Installation +Add this to your Cartfile: +```ruby +github "ViccAlexander/Chameleon" +``` + +======= +####Manual Installation +If you rather install this framework manually, just drag and drop the Chameleon folder into your project, and make sure you check the following boxes. Note: Don't forget to manually import the *QuartzCore* & *CoreGraphics* framework if you plan on using gradient colors! + +

+ Manual Installation +

+ +If you're working with Swift and are manually installing Chameleon, there's an additional step. Make sure to download and drag the following file, [ChameleonShorthand.swift](https://github.com/ViccAlexander/Chameleon/blob/master/Pod/Classes/Swift/ChameleonShorthand.swift), into your project, and you'll be good to go. + +####Storyboard Add-On +Using Chameleon's awesome palette in Storyboard is easy! Simply download and install [Chameleon Palette](https://github.com/ViccAlexander/Chameleon/blob/master/Extras/Chameleon.dmg?raw=true). + +Once installed, make sure to restart XCode. You'll find all of Chameleon's colors in the Palette Color Picker whenever they're needed! :) + +

+ Chameleon Palette +

+ +

+ Chameleon Palette +

+ +###Usage +To use the myriad of features in Chameleon, include the following import: + +###### If you installed Chameleon using cocoapods: + +######Objective-C + +``` objective-c +#import +``` + +######Swift: +``` swift +import ChameleonFramework +``` + +###### If you installed Chameleon manually: +``` objective-c +#import "Chameleon.h" +``` +###UIColor Methods +[● Flat Colors](https://github.com/ViccAlexander/Chameleon#flat-colors) +[● Random Colors](https://github.com/ViccAlexander/Chameleon#random-colors) +[● Complementary Colors](https://github.com/ViccAlexander/Chameleon#complementary-colors) +[● Contrasting Colors](https://github.com/ViccAlexander/Chameleon#contrasting-colors) +[● Flattening Non-Flat Colors](https://github.com/ViccAlexander/Chameleon#flattening-non-flat-colors) +[● Gradient Colors](https://github.com/ViccAlexander/Chameleon#gradient-colors-1) +[● Hex Colors](https://github.com/ViccAlexander/Chameleon#hex-colors-) +[● Lighter & Darker Colors](https://github.com/ViccAlexander/Chameleon#lighter-and-darker-colors-) + +####Flat Colors +Using a flat color is as easy as adding any other color in your app (if not easier). For example, to set a view's background property to a flat color with a dark shade, you simply have to do the following: + +#####Normal Convention: + +######Objective-C +``` objective-c +self.view.backgroundColor = [UIColor flatGreenColorDark]; +``` +######Swift +``` swift +view.backgroundColor = UIColor.flatGreenColorDark() +``` + +#####Chameleon Shorthand: + +######Objective-C +``` objective-c +self.view.backgroundColor = FlatGreenDark; +``` +######Swift +``` swift +view.backgroundColor = FlatGreenDark() +``` + +Setting the color for a light shade is the same, except without adding the *Dark* suffix. (By default, all colors without a *Dark* suffix are light shades). For example: + +#####Normal Convention: +######Objective-C +``` objective-c +self.view.backgroundColor = [UIColor flatGreenColor]; +``` +######Swift +``` swift +view.backgroundColor = UIColor.flatGreenColor() +``` + +#####Chameleon Shorthand: + +######Objective-C +``` objective-c +self.view.backgroundColor = FlatGreen; +``` +######Swift +``` swift +view.backgroundColor = FlatGreen() +``` + +####Random Colors +There are four ways to generate a random flat color. If you have no preference as to whether you want a light shade or a dark shade, you can do the following: + +#####Normal Convention: +######Objective-C +``` objective-c +self.view.backgroundColor = [UIColor randomFlatColor]; +``` +######Swift +``` swift +view.backgroundColor = UIColor.randomFlatColor() +``` + +#####Chameleon Shorthand: +###### Objective-C +``` objective-c +self.view.backgroundColor = RandomFlatColor; +``` + +######Swift +``` swift +view.backgroundColor = RandomFlatColor() +``` + +Otherwise, you can perform the following method call to specify whether it should return either a light or dark shade: + +#####Normal Convention: +######Objective-C +``` objective-c +[UIColor colorWithRandomFlatColorOfShadeStyle:UIShadeStyleLight]; +``` + +######Swift +``` swift +UIColor(randomFlatColorOfShadeStyle:.Light) +``` + +#####Chameleon Shorthand: +######Objective-C +``` objective-c +RandomFlatColorWithShade(UIShadeStyleLight); +``` +######Swift +``` swift +RandomFlatColorWithShade(.Light) +``` + +**UIShadeStyles:** +- `UIShadeStyleLight` (`UIShadeStyle.Light` in Swift) +- `UIShadeStyleDark` (`UIShadeStyle.Dark` in Swift) + +##### Choosing A Random Color From a List of Colors ![New](http://i.imgur.com/BX3b9ES.png) + +If you need to be a bit more selective and only display a random color from a set list of colors, you can use the following method: + +#####Normal Convention: +######Objective-C +``` objective-c +[UIColor colorWithRandomColorInArray:@[FlatWhite, FlatRed, FlatBlue]]; +``` + +######Swift +``` swift +TBA +``` + +#####Chameleon Shorthand: +######Objective-C +``` objective-c +RandomFlatColorInArray(@[FlatWhite, FlatRed, FlatBlue]) +``` +######Swift +``` swift +TBA +``` + +##### Choosing A Random Flat Color But Excluding A Few ![New](http://i.imgur.com/BX3b9ES.png) + +Last but certainly not least, you can also choose form the list of random colors and exclude the ones you don't want. For example say you want to randomly select a flat color for a user's profile, but don't want to use any blacks, grays, or whites. You can simply do: + +#####Normal Convention: +######Objective-C +``` objective-c +[UIColor colorWithRandomFlatColorExcludingColorsInArray:@[FlatBlack, FlatBlackDark, FlatGray, FlatGrayDark, FlatWhite, FlatWhiteDark]]; +``` + +######Swift +``` swift +TBA +``` + +#####Chameleon Shorthand: +######Objective-C +``` objective-c +RandomFlatColorExcluding(@[FlatBlack, FlatBlackDark, FlatGray, FlatGrayDark, FlatWhite, FlatWhiteDark]) +``` +######Swift +``` swift +TBA +``` + +####Complementary Colors +To generate a complementary color, perform the following method call, remembering to specify the color whose complement you want: + +#####Normal Convention: +######Objective-C +``` objective-c +[UIColor colorWithComplementaryFlatColorOf:(UIColor *)someUIColor]; +``` + +######Swift +``` swift +UIColor(complementaryFlatColorOf:someUIColor) +``` + +#####Chameleon Shorthand: +######Objective-C +``` objective-c +ComplementaryFlatColorOf(color); +``` + +######Swift +``` swift +ComplementaryFlatColorOf(color) +``` + +####Contrasting Colors +The contrasting color feature returns either a dark color a light color depending on what the Chameleon algorithm believes is a better choice. You can specify whether the dark or light colors are flat: *`([UIColor flatWhiteColor]` & `[UIColor flatBlackColorDark]`)* or non-flat *(`[UIColor whiteColor]` & `[UIColor blackColor]`).* + +If you're trying to set a `UILabel's textColor` property, make sure you provide the `UILabel's backgroundColor`. If your label has a clear `backgroundColor`, just provide the `backgroundColor` property of the object directly behind the `UILabel`. + +Here's an example: + +#####Normal Convention: +######Objective-C +``` objective-c +[UIColor colorWithContrastingBlackOrWhiteColorOn:(UIColor *)backgroundColor isFlat:(BOOL)flat]; +``` + +######Swift +``` swift +UIColor(contrastingBlackOrWhiteColorOn:UIColor!, isFlat:Bool) +``` + +#####Chameleon Shorthand: +######Objective-C +``` objective-c +ContrastColor(backgroundColor, isFlat); +``` + +######Swift +``` swift +ContrastColor(backgroundColor, isFlat) +``` + +####Flattening Non-Flat Colors +As mentioned previously, this feature is unique to Chameleon. While this feature is in its early stages of operation and can be improved, it is accurate in finding the nearest flat version of any color in the spectrum, and very simple to use: + +#####Normal Convention: +######Objective-C +``` objective-c +[(UIColor *)color flatten]; +``` + +######Swift +``` swift +UIColor.pinkColor().flatten() +``` + +#### Gradient Colors +Using a gradient to color an object usually requires a couple of lines of code plus many more lines to superimpose smart contrasting text. Thankfully, Chameleon takes care of that for you. We've introduced a new way to have multicolored objects, and that's with gradients! + +#####Gradient Styles +Chameleon provides three simple gradient styles. Gradients can be created from any number of colors you desire as long as at least two colors are provided. Don't forget that the contrasting text feature is also compatible with gradient colors! + +**UIGradientStyles:** +* `UIGradientStyleLeftToRight` (UIGradientStyle.LeftToRight in Swift) +* `UIGradientStyleTopToBottom` (UIGradientStyle.TopToBottom in Swift) +* `UIGradientStyleRadial` (UIGradientStyle.Radial in Swift) + +#####Normal Convention: +######Objective-C +``` objective-c +[UIColor colorWithGradientStyle:(UIGradientStyle)gradientStyle withFrame:(CGRect)frame andColors:(NSArray *)colors]; +``` + +######Swift +``` swift +UIColor(gradientStyle:UIGradientStyle, withFrame:CGRect, andColors:[UIColor]) +``` + +#####Chameleon Shorthand: +######Objective-C +``` objective-c +GradientColor(gradientStyle, frame, colors); +``` + +######Swift +``` swift +GradientColor(gradientStyle, frame, colors) +``` + +**Objective-C Note**: If you use the Chameleon Shorthand, and use the `NSArray` literal ```@[]``` to set the array of colors, make sure you add parenthesis around it, or else you'll get an error. + +Note: `UIGradientStyleRadial` only uses a maximum of 2 colors at the moment. So if more colors are provided, they will not show. + +#### Hex Colors + +One of the most requested features, *hex colors*, is now available. You can simply provide a hex string with or without a *#* sign: + +#####Normal Convention: +######Objective-C +``` objective-c +[UIColor colorWithHexString:(NSString *)string]; +``` + +######Swift +``` swift +UIColor(hexString:string) +``` + +#####Chameleon Shorthand: +######Objective-C +``` objective-c +HexColor(hexString) +``` + +######Swift +``` swift +HexColor(hexString) +``` +#### Hex Values ![New](http://i.imgur.com/BX3b9ES.png) + +Retrieving the `hexValue` of a UIColor is just as easy. + +######Objective-C +``` objective-c +[FlatGreen hexValue]; //Returns @"2ecc71" +``` + +######Swift +``` swift +FlatGreen.hexValue //Returns @"2ecc71" +``` + +#### Lighter and Darker Colors + +Sometimes all you need is a color a shade lighter or a shade darker. Well for those rare, but crucial moments, Chameleon's got you covered. You can now lighten any color the following way: + +#####Normal Convention: +######Objective-C +``` objective-c +[color lightenByPercentage:(CGFloat)percentage]; +``` + +######Swift +``` swift +color.lightenByPercentage(percentage: CGFloat) +``` + +You can also generate a darker version of a color: + +#####Normal Convention: +######Objective-C +``` objective-c +[color darkenByPercentage:(CGFloat)percentage]; +``` + +######Swift +``` swift +color.darkenByPercentage(percentage: CGFloat) +``` + +### Colors From Images + +Chameleon now supports the extraction of colors from images. You can either generate both flat and non-flat color schemes from an image, or easily extract the average color. + +To generate a color scheme simply do the following: +#####Normal Convention: +######Objective-C +``` objective-c +[NSArray arrayOfColorsFromImage:(UIImage *)image withFlatScheme:(BOOL)flatScheme]; +``` + +######Swift (**Array extension missing**) +``` swift +NSArray(ofColorsFromImage: UIImage, withFlatScheme: Bool) +``` + +#####Chameleon Shorthand: +######Objective-C +``` objective-c +ColorsFromImage(image, isFlatScheme) +``` + +######Swift +``` swift +ColorsFromImage(image, isFlatScheme) +``` + +To extract the average color from an image, you can also do: +#####Normal Convention: +######Objective-C +``` objective-c +[UIColor colorWithAverageColorFromImage:(UIImage *)image]; +``` + +######Swift +``` swift +UIColor(averageColorFromImage: UIImage) +``` + +#####Chameleon Shorthand: +######Objective-C +``` objective-c +AverageColorFromImage(image) +``` + +######Swift +``` swift +AverageColorFromImage(image) +``` + +###UIStatusBarStyle Methods +####Contrasting UIStatusBarStyle +Many apps on the market, even the most popular ones, overlook this aspect of a beautiful app: the status bar style. Chameleon has done something no other framework has... it has created a new status bar style: `UIStatusBarStyleContrast`. Whether you have a `ViewController` embedded in a `NavigationController`, or not, you can do the following: + +#####Normal Convention: +######Objective-C +``` objective-c +[self setStatusBarStyle:UIStatusBarStyleContrast]; +``` + +######Swift +``` swift +self.setStatusBarStyle(UIStatusBarStyleContrast) +``` +######**Note**: Make sure that the key *View controller-based status bar appearance* in **Info.plist** is set to `YES`. + +###Color Schemes Methods +######**Note**: *Due to the limited number of flat colors currently available, color schemes may return results that reuse certain flat colors. Because of this redundancy, we have provided an option to return either a flat color scheme or a non-flat color scheme until more flat colors are added to the inventory.* + +The initial color can be either a non-flat color or flat color. Chameleon will return an `NSArray` of 5 `UIColors` in which the original color will be the third object of the scheme. This allows for Chameleon to designate the colors of the color scheme (2 colors counter-clockwise and 2 clockwise from the initial color), and thus, the chosen colors are aligned specifically in that order. + +####Analogous Color Scheme +An analogous color scheme uses three adjacent colors on the color wheel. According to Wikipedia, it’s best used with either warm or cool colors, creating a cohesive collection with certain temperature qualities as well as proper color harmony; however, this particular scheme lacks contrast and is less vibrant than complementary schemes. Within the scheme, choose one color to dominate and two to support. The remaining two colors should be used (along with black, white or gray) as accents. + +####Complementary Color Scheme +A complementary color scheme uses opposite colors on the color wheel. To put into slightly more technical terms, they are two colors that, when combined, produce a neutral color. Complementary colors are tricky to use extensively, but work well when you want a point of emphasis. Complementary colors are generally not favorable to use for text. + +####Triadic Color Scheme +A triadic scheme uses evenly spaced colors on the color wheel. The colors tend to be richly vivid and offer a higher degree of contrast while, at the same time, retain color harmony. Let one color dominate and use the two others for accent. + +####Getting Colors in a Color Scheme +To retrieve an array of colors, first make sure to initialize an NSMutableArray (in case you want to use the same array to replace with different colors later): + +#####Normal Convention: +######Objective-C +``` objective-c +NSMutableArray *colorArray = [NSMutableArray alloc] initWithArray:[NSArray arrayOfColorsWithColorScheme:(ColorScheme)colorScheme + with:(UIColor *)color + flatScheme:(BOOL)isFlatScheme]]; +``` + +######Swift +``` swift +var colorArray = NSArray(ofColorsWithColorScheme:ColorScheme, with:UIColor!, flatScheme:Bool) +``` + +#####Chameleon Shorthand: +######Objective-C +``` objective-c +NSMutableArray *colorArray = [[NSMutableArray alloc] initWithArray:ColorScheme(colorSchemeType, color, isFlatScheme)]; +``` + +######Swift +``` swift +var colorArray = ColorSchemeOf(colorSchemeType, color, isFlatScheme) +``` + +#####Example: +Assuming you want to generate an analogous color scheme for the light shade of Flat Red, perform the following method call: + +#####Normal Convention: +######Objective-C +``` objective-c +NSMutableArray *colorArray = [NSMutableArray alloc] initWithArray:[NSArray arrayOfColorsWithColorScheme:ColorSchemeAnalogous + with:[UIColor flatRedColor] + flatScheme:YES]]; +``` + +######Swift +``` swift +var colorArray = NSArray(ofColorsWithColorScheme:ColorScheme.Analogous, with:UIColor.flatRedColor(), flatScheme:true) +``` + +#####Chameleon Shorthand: +######Objective-C +``` objective-c +NSMutableArray *colorArray = [[NSMutableArray alloc] initWithArray:ColorScheme(ColorSchemeAnalogous, FlatRed, YES)]; +``` + +######Swift +``` swift +var colorArray = ColorSchemeOf(ColorScheme.Analogous, FlatRed(), true) +``` + +You can then retrieve each individual color the same way you would normally retrieve any object from an array: + +######Objective-C +```objective-c +UIColor *firstColor = colorArray[0]; +``` + +######Swift +``` swift +var firstColor = colorArray[0] as! UIColor +``` + +###Theme Methods + +With Chameleon, you can now specify a global color theme with simply one line of code (It even takes care of dealing with the status bar style as well)! Here's one of three methods to get you started. `ContentStyle` allows you to decide whether text and a few other elements should be white, black, or whichever contrasts more over any UI element's `backgroundColor`. + +To set a global theme, you can do the following in your app delegate: + +#####Normal Convention: +######Objective-C +``` objective-c +[Chameleon setGlobalThemeUsingPrimaryColor:(UIColor *)color withContentStyle:(UIContentStyle)contentStyle]; +``` + +But what if you want a different theme for a specific `UIViewController?` No problem, Chameleon allows you to override the global theme in any `UIViewController` and `UINavigationController`, by simply doing the following: + +#####Normal Convention: +######Objective-C +```objective-c +//This would go in the controller you specifically want to theme differently +[self setThemeUsingPrimaryColor:FlatMint withSecondaryColor:FlatBlue andContentStyle:UIContentStyleContrast]; +``` + +###### **Note:** In order for the status bar style to automatically be set using a theme, you need to make sure that the *View controller-based status bar appearance* key in **Info.plist** is set to `NO`. + +#### Navigation Bar Hairline + +![No Hairline](http://i.imgur.com/tjwx53y.png) + +As of `2.0.3` the navigation bar hairline view is no longer hidden by default. However, if you're seeking a true flat look (like the image above), you can hide the hairline at the bottom of the navigation bar by doing the following: + +######Objective-C +```objective-c +[self.navigationController setHidesNavigationBarHairline:YES]; + +//or + +self.navigationController.hidesNavigationBarHairline = YES; +``` + +## 👑 Author +Chameleon was developed by **Vicc Alexander** [(@ViccsMind)](https://twitter.com/viccsmind) in 2014. Currently, it is being maintained by [@ViccAlexander](https://github.com/ViccAlexander) and [@Bre7](https://github.com/bre7). + +##### Support ☕️ +If you enjoy Chameleon and would like to buy us a coffee we'd appreciate it. Donate + +## 📝 To Do List +* ~~Cocoapods Support~~ ![1.0.1](http://i.imgur.com/8Li5aRR.png) +* ~~Table of Contents~~ ![1.0.1](http://i.imgur.com/8Li5aRR.png) +* ~~Storyboard Color Picker Add-On~~ ![1.1.0](http://i.imgur.com/Py4QvaK.png) +* ~~Xcode In-App Documentation~~ ![1.1.0](http://i.imgur.com/Py4QvaK.png) +* ~~Switch from RGB values over to HSB and LAB~~ ![1.1.0](http://i.imgur.com/Py4QvaK.png) +* ~~Gradient Colors~~ ![1.1.0](http://i.imgur.com/Py4QvaK.png) +* ~~Update GradientStyle & ShadeStyle Syntax~~ ![1.1.1](http://i.imgur.com/AHxj8Rb.png) +* ~~Add Radial Gradient Support~~ ![1.1.1](http://i.imgur.com/AHxj8Rb.png) +* ~~Fix Swift Conflict with `initWithArray:for:flatScheme:` method~~ ![1.1.12](http://i.imgur.com/7NrZ7yx.png) +* ~~Swift Support~~ ![1.1.3](http://i.imgur.com/WgpBlLo.png) +* ~~Color Scheme From Images~~ ![2.0.0](http://i.imgur.com/HdE8kjQ.png) +* ~~UIAppearance Convenience Methods~~ ![2.0.0](http://i.imgur.com/HdE8kjQ.png) +* ~~Add option to hide `NavigationBar` hairline~~ ![2.0.3](http://i.imgur.com/DmlOKPJ.png) +* Allow Gradient Colors to Adapt To Frame Changes + +## 📄 Change Log + +### See [Changelog.md](https://github.com/ViccAlexander/Chameleon/blob/master/CHANGELOG.md) 👀 + diff --git a/Pods/Charts/LICENSE b/Pods/Charts/LICENSE new file mode 100644 index 00000000..17c2ed44 --- /dev/null +++ b/Pods/Charts/LICENSE @@ -0,0 +1,202 @@ +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2016 Daniel Cohen Gindi & Philipp Jahoda + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/Pods/Charts/README.md b/Pods/Charts/README.md new file mode 100644 index 00000000..89d92c81 --- /dev/null +++ b/Pods/Charts/README.md @@ -0,0 +1,213 @@ +**Version 3.3.0**, synced to [MPAndroidChart #f6a398b](https://github.com/PhilJay/MPAndroidChart/commit/f6a398b) + +![alt tag](https://raw.github.com/danielgindi/Charts/master/Assets/feature_graphic.png) + ![Supported Platforms](https://img.shields.io/cocoapods/p/Charts.svg) [![Releases](https://img.shields.io/github/release/danielgindi/Charts.svg)](https://github.com/danielgindi/Charts/releases) [![Latest pod release](https://img.shields.io/cocoapods/v/Charts.svg)](http://cocoapods.org/pods/charts) [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) [![Build Status](https://travis-ci.org/danielgindi/Charts.svg?branch=master)](https://travis-ci.org/danielgindi/Charts) [![codecov](https://codecov.io/gh/danielgindi/Charts/branch/master/graph/badge.svg)](https://codecov.io/gh/danielgindi/Charts) +[![Join the chat at https://gitter.im/danielgindi/Charts](https://badges.gitter.im/danielgindi/Charts.svg)](https://gitter.im/danielgindi/Charts?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + +### Just a heads up: Charts 3.0 has some breaking changes. Please read [the release/migration notes](https://github.com/danielgindi/Charts/releases/tag/v3.0.0). +### Another heads up: ChartsRealm is now in a [separate repo](https://github.com/danielgindi/ChartsRealm). Pods is also now `Charts` and `ChartsRealm`, instead of ~`Charts/Core`~ and ~`Charts/Realm`~ +### One more heads up: As Swift evolves, if you are not using the latest Swift compiler, you shouldn't check out the master branch. Instead, you should go to the release page and pick up whatever suits you. + +* Xcode 10.2 / Swift 5.0 (master branch) +* iOS >= 8.0 (Use as an **Embedded** Framework) +* tvOS >= 9.0 +* macOS >= 10.11 + +Okay so there's this beautiful library called [MPAndroidChart](https://github.com/PhilJay/MPAndroidChart) by [Philipp Jahoda](https://www.linkedin.com/in/philippjahoda) which has become very popular amongst Android developers, but there was no decent solution to create charts for iOS. + +I've chosen to write it in `Swift` as it can be highly optimized by the compiler, and can be used in both `Swift` and `ObjC` project. The demo project is written in `ObjC` to demonstrate how it works. + +**An amazing feature** of this library now, for Android, iOS, tvOS and macOS, is the time it saves you when developing for both platforms, as the learning curve is singleton- it happens only once, and the code stays very similar so developers don't have to go around and re-invent the app to produce the same output with a different library. (And that's not even considering the fact that there's not really another good choice out there currently...) + +## Having trouble running the demo? + +* `ChartsDemo/ChartsDemo.xcodeproj` is the demo project for iOS/tvOS +* `ChartsDemo-OSX/ChartsDemo-OSX.xcodeproj` is the demo project for macOS +* Make sure you are running a supported version of Xcode. + * Usually it is specified here a few lines above. + * In most cases it will be the latest Xcode version. +* Make sure that your project supports Swift 5.0 +* Optional: Run `carthage checkout` in the project folder, to fetch dependencies (i.e testing dependencies). + * If you don't have Carthage - you can get it [here](https://github.com/Carthage/Carthage/releases). + + +## Usage + +In order to correctly compile: + +1. Drag the `Charts.xcodeproj` to your project +2. Go to your target's settings, hit the "+" under the "Embedded Binaries" section, and select the Charts.framework +3. `@import Charts` +4. When using Swift in an ObjC project: + - You need to import your Bridging Header. Usually it is "*YourProject-Swift.h*", so in ChartsDemo it's "*ChartsDemo-Swift.h*". Do not try to actually include "*ChartsDemo-Swift.h*" in your project :-) + - (Xcode 8.1 and earlier) Under "Build Options", mark "Embedded Content Contains Swift Code" + - (Xcode 8.2+) Under "Build Options", mark "Always Embed Swift Standard Libraries" +5. When using [Realm.io](https://realm.io/): + - Note that the Realm framework is not linked with Charts - it is only there for *optional* bindings. Which means that you need to have the framework in your project, and in a compatible version to whatever is compiled with Charts. We will do our best to always compile against the latest version. + - You'll need to add `ChartsRealm` as a dependency too. + +## 3rd party tutorials + +* [Using Realm and Charts with Swift 3 in iOS 10 (Sami Korpela)](https://medium.com/@skoli/using-realm-and-charts-with-swift-3-in-ios-10-40c42e3838c0#.2gyymwfh8) +* [Creating a Line Chart in Swift 3 and iOS 10 (Osian Smith)](https://medium.com/@OsianSmith/creating-a-line-chart-in-swift-3-and-ios-10-2f647c95392e) +* [Beginning Set-up and Example Using Charts with Swift 3](https://github.com/annalizhaz/ChartsForSwiftBasic) +* Want your tutorial to show here? Create a PR! + +## Troubleshooting + +#### Can't compile? + +* Please note the difference between installing a compiled framework from CocoaPods or Carthage, and copying the source code. +* Please read the **Usage** section again. +* Search in the issues +* Try to politely ask in the issues section + +#### Other problems / feature requests + +* Search in the issues +* Try to politely ask in the issues section + +## CocoaPods Install + +Add `pod 'Charts'` to your Podfile. "Charts" is the name of the library. +For [Realm](https://realm.io/) support, please add `pod 'ChartsRealm'` too. + +**Note:** ~~`pod 'ios-charts'`~~ is not the correct library, and refers to a different project by someone else. + +## Carthage Install + +Charts now include Carthage prebuilt binaries. + +```carthage +github "danielgindi/Charts" == 3.3.0 +github "danielgindi/Charts" ~> 3.3.0 +``` + +In order to build the binaries for a new release, use `carthage build --no-skip-current && carthage archive Charts`. + +## 3rd party bindings + +Xamarin (by @Flash3001): *iOS* - [GitHub](https://github.com/Flash3001/iOSCharts.Xamarin)/[NuGet](https://www.nuget.org/packages/iOSCharts/). *Android* - [GitHub](https://github.com/Flash3001/MPAndroidChart.Xamarin)/[NuGet](https://www.nuget.org/packages/MPAndroidChart/). + +## Help + +If you like what you see here, and want to support the work being done in this repository, you could: +* Contribute code, issues and pull requests +* Let people know this library exists (:fire: spread the word :fire:) +* [![Donate](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=68UL6Y8KUPS96) (You can buy me a beer, or you can buy me dinner :-) + +**Note:** The author of [MPAndroidChart](https://github.com/PhilJay/MPAndroidChart) is the reason that this library exists, and is accepting [donations](https://github.com/PhilJay/MPAndroidChart#donations) on his page. He deserves them! + +Questions & Issues +----- + +If you are having questions or problems, you should: + + - Make sure you are using the latest version of the library. Check the [**release-section**](https://github.com/danielgindi/Charts/releases). + - Study the Android version's [**Documentation-Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) + - Study the (Still incomplete [![Doc-Percent](https://img.shields.io/cocoapods/metrics/doc-percent/Charts.svg)](http://cocoadocs.org/docsets/Charts/)) [**Pod-Documentation**](http://cocoadocs.org/docsets/Charts/) + - Search or open questions on [**stackoverflow**](http://stackoverflow.com/questions/tagged/ios-charts) with the `ios-charts` tag + - Search [**known issues**](https://github.com/danielgindi/Charts/issues) for your problem (open and closed) + - Create new issues (please :fire: **search known issues before** :fire:, do not create duplicate issues) + + +Features +======= + +**Core features:** + - 8 different chart types + - Scaling on both axes (with touch-gesture, axes separately or pinch-zoom) + - Dragging / Panning (with touch-gesture) + - Combined-Charts (line-, bar-, scatter-, candle-stick-, bubble-) + - Dual (separate) Axes + - Customizable Axes (both x- and y-axis) + - Highlighting values (with customizable popup-views) + - Save chart to camera-roll / export to PNG/JPEG + - Predefined color templates + - Legends (generated automatically, customizable) + - Animations (build up animations, on both x- and y-axis) + - Limit lines (providing additional information, maximums, ...) + - Fully customizable (paints, typefaces, legends, colors, background, gestures, dashed lines, ...) + - Plotting data directly from [**Realm.io**](https://realm.io) mobile database ([here](https://github.com/danielgindi/ChartsRealm)) + +**Chart types:** + +*Screenshots are currently taken from the original repository, as they render exactly the same :-)* + + + - **LineChart (with legend, simple design)** +![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/simpledesign_linechart4.png) + - **LineChart (with legend, simple design)** +![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/simpledesign_linechart3.png) + + - **LineChart (cubic lines)** +![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/cubiclinechart.png) + + - **LineChart (gradient fill)** +![alt tag](https://raw.github.com/PhilJay/MPAndroidChart/master/screenshots/line_chart_gradient.png) + + - **Combined-Chart (bar- and linechart in this case)** +![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/combined_chart.png) + + - **BarChart (with legend, simple design)** + +![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/simpledesign_barchart3.png) + + - **BarChart (grouped DataSets)** + +![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/groupedbarchart.png) + + - **Horizontal-BarChart** + +![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/horizontal_barchart.png) + + + - **PieChart (with selection, ...)** + +![alt tag](https://raw.github.com/PhilJay/MPAndroidChart/master/screenshots/simpledesign_piechart1.png) + + - **ScatterChart** (with squares, triangles, circles, ... and more) + +![alt tag](https://raw.github.com/PhilJay/MPAndroidChart/master/screenshots/scatterchart.png) + + - **CandleStickChart** (for financial data) + +![alt tag](https://raw.github.com/PhilJay/MPAndroidChart/master/screenshots/candlestickchart.png) + + - **BubbleChart** (area covered by bubbles indicates the value) + +![alt tag](https://raw.github.com/PhilJay/MPAndroidChart/master/screenshots/bubblechart.png) + + - **RadarChart** (spider web chart) + +![alt tag](https://raw.github.com/PhilJay/MPAndroidChart/master/screenshots/radarchart.png) + + +Documentation +======= +Currently there's no need for documentation for the iOS/tvOS/macOS version, as the API is **95% the same** as on Android. +You can read the official [MPAndroidChart](https://github.com/PhilJay/MPAndroidChart) documentation here: [**Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) + +Or you can see the Charts Demo project in both Objective-C and Swift ([**ChartsDemo-iOS**](https://github.com/danielgindi/Charts/tree/master/ChartsDemo-iOS), as well as macOS [**ChartsDemo-macOS**](https://github.com/danielgindi/Charts/tree/master/ChartsDemo-macOS)) and learn the how-tos from it. + + +Special Thanks +======= + +Goes to [@liuxuan30](https://github.com/liuxuan30), [@petester42](https://github.com/petester42) and [@AlBirdie](https://github.com/AlBirdie) for new features, bugfixes, and lots and lots of involvement in our open-sourced community! You guys are a huge help to all of those coming here with questions and issues, and I couldn't respond to all of those without you. + +License +======= +Copyright 2016 Daniel Cohen Gindi & Philipp Jahoda + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/Pods/Charts/Source/Charts/Animation/Animator.swift b/Pods/Charts/Source/Charts/Animation/Animator.swift new file mode 100644 index 00000000..b94b21f4 --- /dev/null +++ b/Pods/Charts/Source/Charts/Animation/Animator.swift @@ -0,0 +1,280 @@ +// +// Animator.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + +@objc(ChartAnimatorDelegate) +public protocol AnimatorDelegate +{ + /// Called when the Animator has stepped. + func animatorUpdated(_ animator: Animator) + + /// Called when the Animator has stopped. + func animatorStopped(_ animator: Animator) +} + +@objc(ChartAnimator) +open class Animator: NSObject +{ + @objc open weak var delegate: AnimatorDelegate? + @objc open var updateBlock: (() -> Void)? + @objc open var stopBlock: (() -> Void)? + + /// the phase that is animated and influences the drawn values on the x-axis + @objc open var phaseX: Double = 1.0 + + /// the phase that is animated and influences the drawn values on the y-axis + @objc open var phaseY: Double = 1.0 + + private var _startTimeX: TimeInterval = 0.0 + private var _startTimeY: TimeInterval = 0.0 + private var _displayLink: NSUIDisplayLink? + + private var _durationX: TimeInterval = 0.0 + private var _durationY: TimeInterval = 0.0 + + private var _endTimeX: TimeInterval = 0.0 + private var _endTimeY: TimeInterval = 0.0 + private var _endTime: TimeInterval = 0.0 + + private var _enabledX: Bool = false + private var _enabledY: Bool = false + + private var _easingX: ChartEasingFunctionBlock? + private var _easingY: ChartEasingFunctionBlock? + + public override init() + { + super.init() + } + + deinit + { + stop() + } + + @objc open func stop() + { + guard _displayLink != nil else { return } + + _displayLink?.remove(from: .main, forMode: RunLoop.Mode.common) + _displayLink = nil + + _enabledX = false + _enabledY = false + + // If we stopped an animation in the middle, we do not want to leave it like this + if phaseX != 1.0 || phaseY != 1.0 + { + phaseX = 1.0 + phaseY = 1.0 + + delegate?.animatorUpdated(self) + updateBlock?() + } + + delegate?.animatorStopped(self) + stopBlock?() + } + + private func updateAnimationPhases(_ currentTime: TimeInterval) + { + if _enabledX + { + let elapsedTime: TimeInterval = currentTime - _startTimeX + let duration: TimeInterval = _durationX + var elapsed: TimeInterval = elapsedTime + if elapsed > duration + { + elapsed = duration + } + + phaseX = _easingX?(elapsed, duration) ?? elapsed / duration + } + + if _enabledY + { + let elapsedTime: TimeInterval = currentTime - _startTimeY + let duration: TimeInterval = _durationY + var elapsed: TimeInterval = elapsedTime + if elapsed > duration + { + elapsed = duration + } + + phaseY = _easingY?(elapsed, duration) ?? elapsed / duration + } + } + + @objc private func animationLoop() + { + let currentTime: TimeInterval = CACurrentMediaTime() + + updateAnimationPhases(currentTime) + + delegate?.animatorUpdated(self) + updateBlock?() + + if currentTime >= _endTime + { + stop() + } + } + + /// Animates the drawing / rendering of the chart on both x- and y-axis with the specified animation time. + /// If `animate(...)` is called, no further calling of `invalidate()` is necessary to refresh the chart. + /// + /// - Parameters: + /// - xAxisDuration: duration for animating the x axis + /// - yAxisDuration: duration for animating the y axis + /// - easingX: an easing function for the animation on the x axis + /// - easingY: an easing function for the animation on the y axis + @objc open func animate(xAxisDuration: TimeInterval, yAxisDuration: TimeInterval, easingX: ChartEasingFunctionBlock?, easingY: ChartEasingFunctionBlock?) + { + stop() + + _startTimeX = CACurrentMediaTime() + _startTimeY = _startTimeX + _durationX = xAxisDuration + _durationY = yAxisDuration + _endTimeX = _startTimeX + xAxisDuration + _endTimeY = _startTimeY + yAxisDuration + _endTime = _endTimeX > _endTimeY ? _endTimeX : _endTimeY + _enabledX = xAxisDuration > 0.0 + _enabledY = yAxisDuration > 0.0 + + _easingX = easingX + _easingY = easingY + + // Take care of the first frame if rendering is already scheduled... + updateAnimationPhases(_startTimeX) + + if _enabledX || _enabledY + { + _displayLink = NSUIDisplayLink(target: self, selector: #selector(animationLoop)) + _displayLink?.add(to: RunLoop.main, forMode: RunLoop.Mode.common) + } + } + + /// Animates the drawing / rendering of the chart on both x- and y-axis with the specified animation time. + /// If `animate(...)` is called, no further calling of `invalidate()` is necessary to refresh the chart. + /// + /// - Parameters: + /// - xAxisDuration: duration for animating the x axis + /// - yAxisDuration: duration for animating the y axis + /// - easingOptionX: the easing function for the animation on the x axis + /// - easingOptionY: the easing function for the animation on the y axis + @objc open func animate(xAxisDuration: TimeInterval, yAxisDuration: TimeInterval, easingOptionX: ChartEasingOption, easingOptionY: ChartEasingOption) + { + animate(xAxisDuration: xAxisDuration, yAxisDuration: yAxisDuration, easingX: easingFunctionFromOption(easingOptionX), easingY: easingFunctionFromOption(easingOptionY)) + } + + /// Animates the drawing / rendering of the chart on both x- and y-axis with the specified animation time. + /// If `animate(...)` is called, no further calling of `invalidate()` is necessary to refresh the chart. + /// + /// - Parameters: + /// - xAxisDuration: duration for animating the x axis + /// - yAxisDuration: duration for animating the y axis + /// - easing: an easing function for the animation + @objc open func animate(xAxisDuration: TimeInterval, yAxisDuration: TimeInterval, easing: ChartEasingFunctionBlock?) + { + animate(xAxisDuration: xAxisDuration, yAxisDuration: yAxisDuration, easingX: easing, easingY: easing) + } + + /// Animates the drawing / rendering of the chart on both x- and y-axis with the specified animation time. + /// If `animate(...)` is called, no further calling of `invalidate()` is necessary to refresh the chart. + /// + /// - Parameters: + /// - xAxisDuration: duration for animating the x axis + /// - yAxisDuration: duration for animating the y axis + /// - easingOption: the easing function for the animation + @objc open func animate(xAxisDuration: TimeInterval, yAxisDuration: TimeInterval, easingOption: ChartEasingOption = .easeInOutSine) + { + animate(xAxisDuration: xAxisDuration, yAxisDuration: yAxisDuration, easing: easingFunctionFromOption(easingOption)) + } + + /// Animates the drawing / rendering of the chart the x-axis with the specified animation time. + /// If `animate(...)` is called, no further calling of `invalidate()` is necessary to refresh the chart. + /// + /// - Parameters: + /// - xAxisDuration: duration for animating the x axis + /// - easing: an easing function for the animation + @objc open func animate(xAxisDuration: TimeInterval, easing: ChartEasingFunctionBlock?) + { + _startTimeX = CACurrentMediaTime() + _durationX = xAxisDuration + _endTimeX = _startTimeX + xAxisDuration + _endTime = _endTimeX > _endTimeY ? _endTimeX : _endTimeY + _enabledX = xAxisDuration > 0.0 + + _easingX = easing + + // Take care of the first frame if rendering is already scheduled... + updateAnimationPhases(_startTimeX) + + if _enabledX || _enabledY, + _displayLink == nil + { + _displayLink = NSUIDisplayLink(target: self, selector: #selector(animationLoop)) + _displayLink?.add(to: .main, forMode: RunLoop.Mode.common) + } + } + + /// Animates the drawing / rendering of the chart the x-axis with the specified animation time. + /// If `animate(...)` is called, no further calling of `invalidate()` is necessary to refresh the chart. + /// + /// - Parameters: + /// - xAxisDuration: duration for animating the x axis + /// - easingOption: the easing function for the animation + @objc open func animate(xAxisDuration: TimeInterval, easingOption: ChartEasingOption = .easeInOutSine) + { + animate(xAxisDuration: xAxisDuration, easing: easingFunctionFromOption(easingOption)) + } + + /// Animates the drawing / rendering of the chart the y-axis with the specified animation time. + /// If `animate(...)` is called, no further calling of `invalidate()` is necessary to refresh the chart. + /// + /// - Parameters: + /// - yAxisDuration: duration for animating the y axis + /// - easing: an easing function for the animation + @objc open func animate(yAxisDuration: TimeInterval, easing: ChartEasingFunctionBlock?) + { + _startTimeY = CACurrentMediaTime() + _durationY = yAxisDuration + _endTimeY = _startTimeY + yAxisDuration + _endTime = _endTimeX > _endTimeY ? _endTimeX : _endTimeY + _enabledY = yAxisDuration > 0.0 + + _easingY = easing + + // Take care of the first frame if rendering is already scheduled... + updateAnimationPhases(_startTimeY) + + if _enabledX || _enabledY, + _displayLink == nil + { + _displayLink = NSUIDisplayLink(target: self, selector: #selector(animationLoop)) + _displayLink?.add(to: .main, forMode: RunLoop.Mode.common) + } + } + + /// Animates the drawing / rendering of the chart the y-axis with the specified animation time. + /// If `animate(...)` is called, no further calling of `invalidate()` is necessary to refresh the chart. + /// + /// - Parameters: + /// - yAxisDuration: duration for animating the y axis + /// - easingOption: the easing function for the animation + @objc open func animate(yAxisDuration: TimeInterval, easingOption: ChartEasingOption = .easeInOutSine) + { + animate(yAxisDuration: yAxisDuration, easing: easingFunctionFromOption(easingOption)) + } +} diff --git a/Pods/Charts/Source/Charts/Animation/ChartAnimationEasing.swift b/Pods/Charts/Source/Charts/Animation/ChartAnimationEasing.swift new file mode 100644 index 00000000..58b0b632 --- /dev/null +++ b/Pods/Charts/Source/Charts/Animation/ChartAnimationEasing.swift @@ -0,0 +1,394 @@ +// +// ChartAnimationUtils.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + +@objc +public enum ChartEasingOption: Int +{ + case linear + case easeInQuad + case easeOutQuad + case easeInOutQuad + case easeInCubic + case easeOutCubic + case easeInOutCubic + case easeInQuart + case easeOutQuart + case easeInOutQuart + case easeInQuint + case easeOutQuint + case easeInOutQuint + case easeInSine + case easeOutSine + case easeInOutSine + case easeInExpo + case easeOutExpo + case easeInOutExpo + case easeInCirc + case easeOutCirc + case easeInOutCirc + case easeInElastic + case easeOutElastic + case easeInOutElastic + case easeInBack + case easeOutBack + case easeInOutBack + case easeInBounce + case easeOutBounce + case easeInOutBounce +} + +public typealias ChartEasingFunctionBlock = ((_ elapsed: TimeInterval, _ duration: TimeInterval) -> Double) + +internal func easingFunctionFromOption(_ easing: ChartEasingOption) -> ChartEasingFunctionBlock +{ + switch easing + { + case .linear: + return EasingFunctions.Linear + case .easeInQuad: + return EasingFunctions.EaseInQuad + case .easeOutQuad: + return EasingFunctions.EaseOutQuad + case .easeInOutQuad: + return EasingFunctions.EaseInOutQuad + case .easeInCubic: + return EasingFunctions.EaseInCubic + case .easeOutCubic: + return EasingFunctions.EaseOutCubic + case .easeInOutCubic: + return EasingFunctions.EaseInOutCubic + case .easeInQuart: + return EasingFunctions.EaseInQuart + case .easeOutQuart: + return EasingFunctions.EaseOutQuart + case .easeInOutQuart: + return EasingFunctions.EaseInOutQuart + case .easeInQuint: + return EasingFunctions.EaseInQuint + case .easeOutQuint: + return EasingFunctions.EaseOutQuint + case .easeInOutQuint: + return EasingFunctions.EaseInOutQuint + case .easeInSine: + return EasingFunctions.EaseInSine + case .easeOutSine: + return EasingFunctions.EaseOutSine + case .easeInOutSine: + return EasingFunctions.EaseInOutSine + case .easeInExpo: + return EasingFunctions.EaseInExpo + case .easeOutExpo: + return EasingFunctions.EaseOutExpo + case .easeInOutExpo: + return EasingFunctions.EaseInOutExpo + case .easeInCirc: + return EasingFunctions.EaseInCirc + case .easeOutCirc: + return EasingFunctions.EaseOutCirc + case .easeInOutCirc: + return EasingFunctions.EaseInOutCirc + case .easeInElastic: + return EasingFunctions.EaseInElastic + case .easeOutElastic: + return EasingFunctions.EaseOutElastic + case .easeInOutElastic: + return EasingFunctions.EaseInOutElastic + case .easeInBack: + return EasingFunctions.EaseInBack + case .easeOutBack: + return EasingFunctions.EaseOutBack + case .easeInOutBack: + return EasingFunctions.EaseInOutBack + case .easeInBounce: + return EasingFunctions.EaseInBounce + case .easeOutBounce: + return EasingFunctions.EaseOutBounce + case .easeInOutBounce: + return EasingFunctions.EaseInOutBounce + } +} + +internal struct EasingFunctions +{ + internal static let Linear = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in return Double(elapsed / duration) } + + internal static let EaseInQuad = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in + var position = Double(elapsed / duration) + return position * position + } + + internal static let EaseOutQuad = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in + var position = Double(elapsed / duration) + return -position * (position - 2.0) + } + + internal static let EaseInOutQuad = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in + var position = Double(elapsed / (duration / 2.0)) + if position < 1.0 + { + return 0.5 * position * position + } + + return -0.5 * ((position - 1.0) * (position - 3.0) - 1.0) + } + + internal static let EaseInCubic = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in + var position = Double(elapsed / duration) + return position * position * position + } + + internal static let EaseOutCubic = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in + var position = Double(elapsed / duration) + position -= 1.0 + return (position * position * position + 1.0) + } + + internal static let EaseInOutCubic = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in + var position = Double(elapsed / (duration / 2.0)) + if position < 1.0 + { + return 0.5 * position * position * position + } + position -= 2.0 + return 0.5 * (position * position * position + 2.0) + } + + internal static let EaseInQuart = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in + var position = Double(elapsed / duration) + return position * position * position * position + } + + internal static let EaseOutQuart = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in + var position = Double(elapsed / duration) + position -= 1.0 + return -(position * position * position * position - 1.0) + } + + internal static let EaseInOutQuart = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in + var position = Double(elapsed / (duration / 2.0)) + if position < 1.0 + { + return 0.5 * position * position * position * position + } + position -= 2.0 + return -0.5 * (position * position * position * position - 2.0) + } + + internal static let EaseInQuint = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in + var position = Double(elapsed / duration) + return position * position * position * position * position + } + + internal static let EaseOutQuint = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in + var position = Double(elapsed / duration) + position -= 1.0 + return (position * position * position * position * position + 1.0) + } + + internal static let EaseInOutQuint = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in + var position = Double(elapsed / (duration / 2.0)) + if position < 1.0 + { + return 0.5 * position * position * position * position * position + } + else + { + position -= 2.0 + return 0.5 * (position * position * position * position * position + 2.0) + } + } + + internal static let EaseInSine = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in + var position: TimeInterval = elapsed / duration + return Double( -cos(position * Double.pi / 2) + 1.0 ) + } + + internal static let EaseOutSine = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in + var position: TimeInterval = elapsed / duration + return Double( sin(position * Double.pi / 2) ) + } + + internal static let EaseInOutSine = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in + var position: TimeInterval = elapsed / duration + return Double( -0.5 * (cos(Double.pi * position) - 1.0) ) + } + + internal static let EaseInExpo = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in + return (elapsed == 0) ? 0.0 : Double(pow(2.0, 10.0 * (elapsed / duration - 1.0))) + } + + internal static let EaseOutExpo = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in + return (elapsed == duration) ? 1.0 : (-Double(pow(2.0, -10.0 * elapsed / duration)) + 1.0) + } + + internal static let EaseInOutExpo = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in + if elapsed == 0 + { + return 0.0 + } + if elapsed == duration + { + return 1.0 + } + + var position: TimeInterval = elapsed / (duration / 2.0) + if position < 1.0 + { + return Double( 0.5 * pow(2.0, 10.0 * (position - 1.0)) ) + } + + position = position - 1.0 + return Double( 0.5 * (-pow(2.0, -10.0 * position) + 2.0) ) + } + + internal static let EaseInCirc = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in + var position = Double(elapsed / duration) + return -(Double(sqrt(1.0 - position * position)) - 1.0) + } + + internal static let EaseOutCirc = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in + var position = Double(elapsed / duration) + position -= 1.0 + return Double( sqrt(1 - position * position) ) + } + + internal static let EaseInOutCirc = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in + var position: TimeInterval = elapsed / (duration / 2.0) + if position < 1.0 + { + return Double( -0.5 * (sqrt(1.0 - position * position) - 1.0) ) + } + position -= 2.0 + return Double( 0.5 * (sqrt(1.0 - position * position) + 1.0) ) + } + + internal static let EaseInElastic = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in + if elapsed == 0.0 + { + return 0.0 + } + + var position: TimeInterval = elapsed / duration + if position == 1.0 + { + return 1.0 + } + + var p = duration * 0.3 + var s = p / (2.0 * Double.pi) * asin(1.0) + position -= 1.0 + return Double( -(pow(2.0, 10.0 * position) * sin((position * duration - s) * (2.0 * Double.pi) / p)) ) + } + + internal static let EaseOutElastic = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in + if elapsed == 0.0 + { + return 0.0 + } + + var position: TimeInterval = elapsed / duration + if position == 1.0 + { + return 1.0 + } + + var p = duration * 0.3 + var s = p / (2.0 * Double.pi) * asin(1.0) + return Double( pow(2.0, -10.0 * position) * sin((position * duration - s) * (2.0 * Double.pi) / p) + 1.0 ) + } + + internal static let EaseInOutElastic = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in + if elapsed == 0.0 + { + return 0.0 + } + + var position: TimeInterval = elapsed / (duration / 2.0) + if position == 2.0 + { + return 1.0 + } + + var p = duration * (0.3 * 1.5) + var s = p / (2.0 * Double.pi) * asin(1.0) + if position < 1.0 + { + position -= 1.0 + return Double( -0.5 * (pow(2.0, 10.0 * position) * sin((position * duration - s) * (2.0 * Double.pi) / p)) ) + } + position -= 1.0 + return Double( pow(2.0, -10.0 * position) * sin((position * duration - s) * (2.0 * Double.pi) / p) * 0.5 + 1.0 ) + } + + internal static let EaseInBack = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in + let s: TimeInterval = 1.70158 + var position: TimeInterval = elapsed / duration + return Double( position * position * ((s + 1.0) * position - s) ) + } + + internal static let EaseOutBack = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in + let s: TimeInterval = 1.70158 + var position: TimeInterval = elapsed / duration + position -= 1.0 + return Double( position * position * ((s + 1.0) * position + s) + 1.0 ) + } + + internal static let EaseInOutBack = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in + var s: TimeInterval = 1.70158 + var position: TimeInterval = elapsed / (duration / 2.0) + if position < 1.0 + { + s *= 1.525 + return Double( 0.5 * (position * position * ((s + 1.0) * position - s)) ) + } + s *= 1.525 + position -= 2.0 + return Double( 0.5 * (position * position * ((s + 1.0) * position + s) + 2.0) ) + } + + internal static let EaseInBounce = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in + return 1.0 - EaseOutBounce(duration - elapsed, duration) + } + + internal static let EaseOutBounce = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in + var position: TimeInterval = elapsed / duration + if position < (1.0 / 2.75) + { + return Double( 7.5625 * position * position ) + } + else if position < (2.0 / 2.75) + { + position -= (1.5 / 2.75) + return Double( 7.5625 * position * position + 0.75 ) + } + else if position < (2.5 / 2.75) + { + position -= (2.25 / 2.75) + return Double( 7.5625 * position * position + 0.9375 ) + } + else + { + position -= (2.625 / 2.75) + return Double( 7.5625 * position * position + 0.984375 ) + } + } + + internal static let EaseInOutBounce = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in + if elapsed < (duration / 2.0) + { + return EaseInBounce(elapsed * 2.0, duration) * 0.5 + } + return EaseOutBounce(elapsed * 2.0 - duration, duration) * 0.5 + 0.5 + } +} diff --git a/Pods/Charts/Source/Charts/Charts/BarChartView.swift b/Pods/Charts/Source/Charts/Charts/BarChartView.swift new file mode 100644 index 00000000..4f9aaa0b --- /dev/null +++ b/Pods/Charts/Source/Charts/Charts/BarChartView.swift @@ -0,0 +1,186 @@ +// +// BarChartView.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + +/// Chart that draws bars. +open class BarChartView: BarLineChartViewBase, BarChartDataProvider +{ + /// if set to true, all values are drawn above their bars, instead of below their top + private var _drawValueAboveBarEnabled = true + + /// if set to true, a grey area is drawn behind each bar that indicates the maximum value + private var _drawBarShadowEnabled = false + + internal override func initialize() + { + super.initialize() + + renderer = BarChartRenderer(dataProvider: self, animator: _animator, viewPortHandler: _viewPortHandler) + + self.highlighter = BarHighlighter(chart: self) + + self.xAxis.spaceMin = 0.5 + self.xAxis.spaceMax = 0.5 + } + + internal override func calcMinMax() + { + guard let data = self.data as? BarChartData + else { return } + + if fitBars + { + _xAxis.calculate( + min: data.xMin - data.barWidth / 2.0, + max: data.xMax + data.barWidth / 2.0) + } + else + { + _xAxis.calculate(min: data.xMin, max: data.xMax) + } + + // calculate axis range (min / max) according to provided data + leftAxis.calculate( + min: data.getYMin(axis: .left), + max: data.getYMax(axis: .left)) + rightAxis.calculate( + min: data.getYMin(axis: .right), + max: data.getYMax(axis: .right)) + } + + /// - Returns: The Highlight object (contains x-index and DataSet index) of the selected value at the given touch point inside the BarChart. + open override func getHighlightByTouchPoint(_ pt: CGPoint) -> Highlight? + { + if _data === nil + { + Swift.print("Can't select by touch. No data set.") + return nil + } + + guard let h = self.highlighter?.getHighlight(x: pt.x, y: pt.y) + else { return nil } + + if !isHighlightFullBarEnabled { return h } + + // For isHighlightFullBarEnabled, remove stackIndex + return Highlight( + x: h.x, y: h.y, + xPx: h.xPx, yPx: h.yPx, + dataIndex: h.dataIndex, + dataSetIndex: h.dataSetIndex, + stackIndex: -1, + axis: h.axis) + } + + /// - Returns: The bounding box of the specified Entry in the specified DataSet. Returns null if the Entry could not be found in the charts data. + @objc open func getBarBounds(entry e: BarChartDataEntry) -> CGRect + { + guard let + data = _data as? BarChartData, + let set = data.getDataSetForEntry(e) as? IBarChartDataSet + else { return CGRect.null } + + let y = e.y + let x = e.x + + let barWidth = data.barWidth + + let left = x - barWidth / 2.0 + let right = x + barWidth / 2.0 + let top = y >= 0.0 ? y : 0.0 + let bottom = y <= 0.0 ? y : 0.0 + + var bounds = CGRect(x: left, y: top, width: right - left, height: bottom - top) + + getTransformer(forAxis: set.axisDependency).rectValueToPixel(&bounds) + + return bounds + } + + /// Groups all BarDataSet objects this data object holds together by modifying the x-value of their entries. + /// Previously set x-values of entries will be overwritten. Leaves space between bars and groups as specified by the parameters. + /// Calls `notifyDataSetChanged()` afterwards. + /// + /// - Parameters: + /// - fromX: the starting point on the x-axis where the grouping should begin + /// - groupSpace: the space between groups of bars in values (not pixels) e.g. 0.8f for bar width 1f + /// - barSpace: the space between individual bars in values (not pixels) e.g. 0.1f for bar width 1f + @objc open func groupBars(fromX: Double, groupSpace: Double, barSpace: Double) + { + guard let barData = self.barData + else + { + Swift.print("You need to set data for the chart before grouping bars.", terminator: "\n") + return + } + + barData.groupBars(fromX: fromX, groupSpace: groupSpace, barSpace: barSpace) + notifyDataSetChanged() + } + + /// Highlights the value at the given x-value in the given DataSet. Provide -1 as the dataSetIndex to undo all highlighting. + /// + /// - Parameters: + /// - x: + /// - dataSetIndex: + /// - stackIndex: the index inside the stack - only relevant for stacked entries + @objc open func highlightValue(x: Double, dataSetIndex: Int, stackIndex: Int) + { + highlightValue(Highlight(x: x, dataSetIndex: dataSetIndex, stackIndex: stackIndex)) + } + + // MARK: Accessors + + /// if set to true, all values are drawn above their bars, instead of below their top + @objc open var drawValueAboveBarEnabled: Bool + { + get { return _drawValueAboveBarEnabled } + set + { + _drawValueAboveBarEnabled = newValue + setNeedsDisplay() + } + } + + /// if set to true, a grey area is drawn behind each bar that indicates the maximum value + @objc open var drawBarShadowEnabled: Bool + { + get { return _drawBarShadowEnabled } + set + { + _drawBarShadowEnabled = newValue + setNeedsDisplay() + } + } + + /// Adds half of the bar width to each side of the x-axis range in order to allow the bars of the barchart to be fully displayed. + /// **default**: false + @objc open var fitBars = false + + /// Set this to `true` to make the highlight operation full-bar oriented, `false` to make it highlight single values (relevant only for stacked). + /// If enabled, highlighting operations will highlight the whole bar, even if only a single stack entry was tapped. + @objc open var highlightFullBarEnabled: Bool = false + + /// `true` the highlight is be full-bar oriented, `false` ifsingle-value + open var isHighlightFullBarEnabled: Bool { return highlightFullBarEnabled } + + // MARK: - BarChartDataProvider + + open var barData: BarChartData? { return _data as? BarChartData } + + /// `true` if drawing values above bars is enabled, `false` ifnot + open var isDrawValueAboveBarEnabled: Bool { return drawValueAboveBarEnabled } + + /// `true` if drawing shadows (maxvalue) for each bar is enabled, `false` ifnot + open var isDrawBarShadowEnabled: Bool { return drawBarShadowEnabled } +} diff --git a/Pods/Charts/Source/Charts/Charts/BarLineChartViewBase.swift b/Pods/Charts/Source/Charts/Charts/BarLineChartViewBase.swift new file mode 100644 index 00000000..2ae82568 --- /dev/null +++ b/Pods/Charts/Source/Charts/Charts/BarLineChartViewBase.swift @@ -0,0 +1,1958 @@ +// +// BarLineChartViewBase.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + +/// Base-class of LineChart, BarChart, ScatterChart and CandleStickChart. +open class BarLineChartViewBase: ChartViewBase, BarLineScatterCandleBubbleChartDataProvider, NSUIGestureRecognizerDelegate +{ + /// the maximum number of entries to which values will be drawn + /// (entry numbers greater than this value will cause value-labels to disappear) + internal var _maxVisibleCount = 100 + + /// flag that indicates if auto scaling on the y axis is enabled + private var _autoScaleMinMaxEnabled = false + + private var _pinchZoomEnabled = false + private var _doubleTapToZoomEnabled = true + private var _dragXEnabled = true + private var _dragYEnabled = true + + private var _scaleXEnabled = true + private var _scaleYEnabled = true + + /// the color for the background of the chart-drawing area (everything behind the grid lines). + @objc open var gridBackgroundColor = NSUIColor(red: 240/255.0, green: 240/255.0, blue: 240/255.0, alpha: 1.0) + + @objc open var borderColor = NSUIColor.black + @objc open var borderLineWidth: CGFloat = 1.0 + + /// flag indicating if the grid background should be drawn or not + @objc open var drawGridBackgroundEnabled = false + + /// When enabled, the borders rectangle will be rendered. + /// If this is enabled, there is no point drawing the axis-lines of x- and y-axis. + @objc open var drawBordersEnabled = false + + /// When enabled, the values will be clipped to contentRect, otherwise they can bleed outside the content rect. + @objc open var clipValuesToContentEnabled: Bool = false + + /// When disabled, the data and/or highlights will not be clipped to contentRect. Disabling this option can + /// be useful, when the data lies fully within the content rect, but is drawn in such a way (such as thick lines) + /// that there is unwanted clipping. + @objc open var clipDataToContentEnabled: Bool = true + + /// Sets the minimum offset (padding) around the chart, defaults to 10 + @objc open var minOffset = CGFloat(10.0) + + /// Sets whether the chart should keep its position (zoom / scroll) after a rotation (orientation change) + /// **default**: false + @objc open var keepPositionOnRotation: Bool = false + + /// The left y-axis object. In the horizontal bar-chart, this is the + /// top axis. + @objc open internal(set) var leftAxis = YAxis(position: .left) + + /// The right y-axis object. In the horizontal bar-chart, this is the + /// bottom axis. + @objc open internal(set) var rightAxis = YAxis(position: .right) + + /// The left Y axis renderer. This is a read-write property so you can set your own custom renderer here. + /// **default**: An instance of YAxisRenderer + @objc open lazy var leftYAxisRenderer = YAxisRenderer(viewPortHandler: _viewPortHandler, yAxis: leftAxis, transformer: _leftAxisTransformer) + + /// The right Y axis renderer. This is a read-write property so you can set your own custom renderer here. + /// **default**: An instance of YAxisRenderer + @objc open lazy var rightYAxisRenderer = YAxisRenderer(viewPortHandler: _viewPortHandler, yAxis: rightAxis, transformer: _rightAxisTransformer) + + internal var _leftAxisTransformer: Transformer! + internal var _rightAxisTransformer: Transformer! + + /// The X axis renderer. This is a read-write property so you can set your own custom renderer here. + /// **default**: An instance of XAxisRenderer + @objc open lazy var xAxisRenderer = XAxisRenderer(viewPortHandler: _viewPortHandler, xAxis: _xAxis, transformer: _leftAxisTransformer) + + internal var _tapGestureRecognizer: NSUITapGestureRecognizer! + internal var _doubleTapGestureRecognizer: NSUITapGestureRecognizer! + #if !os(tvOS) + internal var _pinchGestureRecognizer: NSUIPinchGestureRecognizer! + #endif + internal var _panGestureRecognizer: NSUIPanGestureRecognizer! + + /// flag that indicates if a custom viewport offset has been set + private var _customViewPortEnabled = false + + public override init(frame: CGRect) + { + super.init(frame: frame) + } + + public required init?(coder aDecoder: NSCoder) + { + super.init(coder: aDecoder) + } + + deinit + { + stopDeceleration() + } + + internal override func initialize() + { + super.initialize() + + _leftAxisTransformer = Transformer(viewPortHandler: _viewPortHandler) + _rightAxisTransformer = Transformer(viewPortHandler: _viewPortHandler) + + self.highlighter = ChartHighlighter(chart: self) + + _tapGestureRecognizer = NSUITapGestureRecognizer(target: self, action: #selector(tapGestureRecognized(_:))) + _doubleTapGestureRecognizer = NSUITapGestureRecognizer(target: self, action: #selector(doubleTapGestureRecognized(_:))) + _doubleTapGestureRecognizer.nsuiNumberOfTapsRequired = 2 + _panGestureRecognizer = NSUIPanGestureRecognizer(target: self, action: #selector(panGestureRecognized(_:))) + + _panGestureRecognizer.delegate = self + + self.addGestureRecognizer(_tapGestureRecognizer) + self.addGestureRecognizer(_doubleTapGestureRecognizer) + self.addGestureRecognizer(_panGestureRecognizer) + + _doubleTapGestureRecognizer.isEnabled = _doubleTapToZoomEnabled + _panGestureRecognizer.isEnabled = _dragXEnabled || _dragYEnabled + + #if !os(tvOS) + _pinchGestureRecognizer = NSUIPinchGestureRecognizer(target: self, action: #selector(BarLineChartViewBase.pinchGestureRecognized(_:))) + _pinchGestureRecognizer.delegate = self + self.addGestureRecognizer(_pinchGestureRecognizer) + _pinchGestureRecognizer.isEnabled = _pinchZoomEnabled || _scaleXEnabled || _scaleYEnabled + #endif + } + + open override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) + { + // Saving current position of chart. + var oldPoint: CGPoint? + if (keepPositionOnRotation && (keyPath == "frame" || keyPath == "bounds")) + { + oldPoint = viewPortHandler.contentRect.origin + getTransformer(forAxis: .left).pixelToValues(&oldPoint!) + } + + // Superclass transforms chart. + super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context) + + // Restoring old position of chart + if var newPoint = oldPoint , keepPositionOnRotation + { + getTransformer(forAxis: .left).pointValueToPixel(&newPoint) + viewPortHandler.centerViewPort(pt: newPoint, chart: self) + } + else + { + viewPortHandler.refresh(newMatrix: viewPortHandler.touchMatrix, chart: self, invalidate: true) + } + } + + 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 } + + // execute all drawing commands + drawGridBackground(context: context) + + + if _autoScaleMinMaxEnabled + { + autoScale() + } + + if leftAxis.isEnabled + { + leftYAxisRenderer.computeAxis(min: leftAxis._axisMinimum, max: leftAxis._axisMaximum, inverted: leftAxis.isInverted) + } + + if rightAxis.isEnabled + { + rightYAxisRenderer.computeAxis(min: rightAxis._axisMinimum, max: rightAxis._axisMaximum, inverted: rightAxis.isInverted) + } + + if _xAxis.isEnabled + { + xAxisRenderer.computeAxis(min: _xAxis._axisMinimum, max: _xAxis._axisMaximum, inverted: false) + } + + xAxisRenderer.renderAxisLine(context: context) + leftYAxisRenderer.renderAxisLine(context: context) + rightYAxisRenderer.renderAxisLine(context: context) + + // The renderers are responsible for clipping, to account for line-width center etc. + xAxisRenderer.renderGridLines(context: context) + leftYAxisRenderer.renderGridLines(context: context) + rightYAxisRenderer.renderGridLines(context: context) + + if _xAxis.isEnabled && _xAxis.isDrawLimitLinesBehindDataEnabled + { + xAxisRenderer.renderLimitLines(context: context) + } + + if leftAxis.isEnabled && leftAxis.isDrawLimitLinesBehindDataEnabled + { + leftYAxisRenderer.renderLimitLines(context: context) + } + + if rightAxis.isEnabled && rightAxis.isDrawLimitLinesBehindDataEnabled + { + rightYAxisRenderer.renderLimitLines(context: context) + } + + context.saveGState() + // make sure the data cannot be drawn outside the content-rect + if clipDataToContentEnabled { + context.clip(to: _viewPortHandler.contentRect) + } + renderer.drawData(context: context) + + // if highlighting is enabled + if (valuesToHighlight()) + { + renderer.drawHighlighted(context: context, indices: _indicesToHighlight) + } + + context.restoreGState() + + renderer.drawExtras(context: context) + + if _xAxis.isEnabled && !_xAxis.isDrawLimitLinesBehindDataEnabled + { + xAxisRenderer.renderLimitLines(context: context) + } + + if leftAxis.isEnabled && !leftAxis.isDrawLimitLinesBehindDataEnabled + { + leftYAxisRenderer.renderLimitLines(context: context) + } + + if rightAxis.isEnabled && !rightAxis.isDrawLimitLinesBehindDataEnabled + { + rightYAxisRenderer.renderLimitLines(context: context) + } + + xAxisRenderer.renderAxisLabels(context: context) + leftYAxisRenderer.renderAxisLabels(context: context) + rightYAxisRenderer.renderAxisLabels(context: context) + + if clipValuesToContentEnabled + { + context.saveGState() + context.clip(to: _viewPortHandler.contentRect) + + renderer.drawValues(context: context) + + context.restoreGState() + } + else + { + renderer.drawValues(context: context) + } + + _legendRenderer.renderLegend(context: context) + + drawDescription(context: context) + + drawMarkers(context: context) + } + + private var _autoScaleLastLowestVisibleX: Double? + private var _autoScaleLastHighestVisibleX: Double? + + /// Performs auto scaling of the axis by recalculating the minimum and maximum y-values based on the entries currently in view. + internal func autoScale() + { + guard let data = _data + else { return } + + data.calcMinMaxY(fromX: self.lowestVisibleX, toX: self.highestVisibleX) + + _xAxis.calculate(min: data.xMin, max: data.xMax) + + // calculate axis range (min / max) according to provided data + + if leftAxis.isEnabled + { + leftAxis.calculate(min: data.getYMin(axis: .left), max: data.getYMax(axis: .left)) + } + + if rightAxis.isEnabled + { + rightAxis.calculate(min: data.getYMin(axis: .right), max: data.getYMax(axis: .right)) + } + + calculateOffsets() + } + + internal func prepareValuePxMatrix() + { + _rightAxisTransformer.prepareMatrixValuePx(chartXMin: _xAxis._axisMinimum, deltaX: CGFloat(xAxis.axisRange), deltaY: CGFloat(rightAxis.axisRange), chartYMin: rightAxis._axisMinimum) + _leftAxisTransformer.prepareMatrixValuePx(chartXMin: xAxis._axisMinimum, deltaX: CGFloat(xAxis.axisRange), deltaY: CGFloat(leftAxis.axisRange), chartYMin: leftAxis._axisMinimum) + } + + internal func prepareOffsetMatrix() + { + _rightAxisTransformer.prepareMatrixOffset(inverted: rightAxis.isInverted) + _leftAxisTransformer.prepareMatrixOffset(inverted: leftAxis.isInverted) + } + + open override func notifyDataSetChanged() + { + renderer?.initBuffers() + + calcMinMax() + + leftYAxisRenderer.computeAxis(min: leftAxis._axisMinimum, max: leftAxis._axisMaximum, inverted: leftAxis.isInverted) + rightYAxisRenderer.computeAxis(min: rightAxis._axisMinimum, max: rightAxis._axisMaximum, inverted: rightAxis.isInverted) + + if let data = _data + { + xAxisRenderer.computeAxis( + min: _xAxis._axisMinimum, + max: _xAxis._axisMaximum, + inverted: false) + + if _legend !== nil + { + legendRenderer?.computeLegend(data: data) + } + } + + calculateOffsets() + + setNeedsDisplay() + } + + internal override func calcMinMax() + { + // calculate / set x-axis range + _xAxis.calculate(min: _data?.xMin ?? 0.0, max: _data?.xMax ?? 0.0) + + // calculate axis range (min / max) according to provided data + leftAxis.calculate(min: _data?.getYMin(axis: .left) ?? 0.0, max: _data?.getYMax(axis: .left) ?? 0.0) + rightAxis.calculate(min: _data?.getYMin(axis: .right) ?? 0.0, max: _data?.getYMax(axis: .right) ?? 0.0) + } + + internal func calculateLegendOffsets(offsetLeft: inout CGFloat, offsetTop: inout CGFloat, offsetRight: inout CGFloat, offsetBottom: inout CGFloat) + { + // setup offsets for legend + if _legend !== nil && _legend.isEnabled && !_legend.drawInside + { + 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 + if xAxis.isEnabled && xAxis.isDrawLabelsEnabled + { + offsetTop += xAxis.labelRotatedHeight + } + + case .bottom: + offsetBottom += min(_legend.neededHeight, _viewPortHandler.chartHeight * _legend.maxSizePercent) + _legend.yOffset + if xAxis.isEnabled && xAxis.isDrawLabelsEnabled + { + offsetBottom += xAxis.labelRotatedHeight + } + + default: + break + } + } + } + } + + internal override func calculateOffsets() + { + if !_customViewPortEnabled + { + var offsetLeft = CGFloat(0.0) + var offsetRight = CGFloat(0.0) + var offsetTop = CGFloat(0.0) + var offsetBottom = CGFloat(0.0) + + calculateLegendOffsets(offsetLeft: &offsetLeft, + offsetTop: &offsetTop, + offsetRight: &offsetRight, + offsetBottom: &offsetBottom) + + // offsets for y-labels + if leftAxis.needsOffset + { + offsetLeft += leftAxis.requiredSize().width + } + + if rightAxis.needsOffset + { + offsetRight += rightAxis.requiredSize().width + } + + if xAxis.isEnabled && xAxis.isDrawLabelsEnabled + { + let xlabelheight = xAxis.labelRotatedHeight + xAxis.yOffset + + // offsets for x-labels + if xAxis.labelPosition == .bottom + { + offsetBottom += xlabelheight + } + else if xAxis.labelPosition == .top + { + offsetTop += xlabelheight + } + else if xAxis.labelPosition == .bothSided + { + offsetBottom += xlabelheight + offsetTop += xlabelheight + } + } + + 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() + } + + /// draws the grid background + internal func drawGridBackground(context: CGContext) + { + if drawGridBackgroundEnabled || drawBordersEnabled + { + context.saveGState() + } + + if drawGridBackgroundEnabled + { + // draw the grid background + context.setFillColor(gridBackgroundColor.cgColor) + context.fill(_viewPortHandler.contentRect) + } + + if drawBordersEnabled + { + context.setLineWidth(borderLineWidth) + context.setStrokeColor(borderColor.cgColor) + context.stroke(_viewPortHandler.contentRect) + } + + if drawGridBackgroundEnabled || drawBordersEnabled + { + context.restoreGState() + } + } + + // MARK: - Gestures + + private enum GestureScaleAxis + { + case both + case x + case y + } + + private var _isDragging = false + private var _isScaling = false + private var _gestureScaleAxis = GestureScaleAxis.both + private var _closestDataSetToTouch: IChartDataSet! + private var _panGestureReachedEdge: Bool = false + private weak var _outerScrollView: NSUIScrollView? + + private var _lastPanPoint = CGPoint() /// This is to prevent using setTranslation which resets velocity + + private var _decelerationLastTime: TimeInterval = 0.0 + private var _decelerationDisplayLink: NSUIDisplayLink! + private var _decelerationVelocity = CGPoint() + + @objc private func tapGestureRecognized(_ recognizer: NSUITapGestureRecognizer) + { + if _data === nil + { + return + } + + if recognizer.state == NSUIGestureRecognizerState.ended + { + if !isHighLightPerTapEnabled { return } + + let h = getHighlightByTouchPoint(recognizer.location(in: self)) + + if h === nil || h == self.lastHighlighted + { + lastHighlighted = nil + highlightValue(nil, callDelegate: true) + } + else + { + lastHighlighted = h + highlightValue(h, callDelegate: true) + } + } + } + + @objc private func doubleTapGestureRecognized(_ recognizer: NSUITapGestureRecognizer) + { + if _data === nil + { + return + } + + if recognizer.state == NSUIGestureRecognizerState.ended + { + if _data !== nil && _doubleTapToZoomEnabled && (data?.entryCount ?? 0) > 0 + { + var location = recognizer.location(in: self) + location.x = location.x - _viewPortHandler.offsetLeft + + if isTouchInverted() + { + location.y = -(location.y - _viewPortHandler.offsetTop) + } + else + { + location.y = -(self.bounds.size.height - location.y - _viewPortHandler.offsetBottom) + } + + let scaleX: CGFloat = isScaleXEnabled ? 1.4 : 1.0 + let scaleY: CGFloat = isScaleYEnabled ? 1.4 : 1.0 + + self.zoom(scaleX: scaleX, scaleY: scaleY, x: location.x, y: location.y) + delegate?.chartScaled?(self, scaleX: scaleX, scaleY: scaleY) + } + } + } + + #if !os(tvOS) + @objc private func pinchGestureRecognized(_ recognizer: NSUIPinchGestureRecognizer) + { + if recognizer.state == NSUIGestureRecognizerState.began + { + stopDeceleration() + + if _data !== nil && + (_pinchZoomEnabled || _scaleXEnabled || _scaleYEnabled) + { + _isScaling = true + + if _pinchZoomEnabled + { + _gestureScaleAxis = .both + } + else + { + let x = abs(recognizer.location(in: self).x - recognizer.nsuiLocationOfTouch(1, inView: self).x) + let y = abs(recognizer.location(in: self).y - recognizer.nsuiLocationOfTouch(1, inView: self).y) + + if _scaleXEnabled != _scaleYEnabled + { + _gestureScaleAxis = _scaleXEnabled ? .x : .y + } + else + { + _gestureScaleAxis = x > y ? .x : .y + } + } + } + } + else if recognizer.state == NSUIGestureRecognizerState.ended || + recognizer.state == NSUIGestureRecognizerState.cancelled + { + if _isScaling + { + _isScaling = false + + // Range might have changed, which means that Y-axis labels could have changed in size, affecting Y-axis size. So we need to recalculate offsets. + calculateOffsets() + setNeedsDisplay() + } + } + else if recognizer.state == NSUIGestureRecognizerState.changed + { + let isZoomingOut = (recognizer.nsuiScale < 1) + var canZoomMoreX = isZoomingOut ? _viewPortHandler.canZoomOutMoreX : _viewPortHandler.canZoomInMoreX + var canZoomMoreY = isZoomingOut ? _viewPortHandler.canZoomOutMoreY : _viewPortHandler.canZoomInMoreY + + if _isScaling + { + canZoomMoreX = canZoomMoreX && _scaleXEnabled && (_gestureScaleAxis == .both || _gestureScaleAxis == .x) + canZoomMoreY = canZoomMoreY && _scaleYEnabled && (_gestureScaleAxis == .both || _gestureScaleAxis == .y) + if canZoomMoreX || canZoomMoreY + { + var location = recognizer.location(in: self) + location.x = location.x - _viewPortHandler.offsetLeft + + if isTouchInverted() + { + location.y = -(location.y - _viewPortHandler.offsetTop) + } + else + { + location.y = -(_viewPortHandler.chartHeight - location.y - _viewPortHandler.offsetBottom) + } + + let scaleX = canZoomMoreX ? recognizer.nsuiScale : 1.0 + let scaleY = canZoomMoreY ? recognizer.nsuiScale : 1.0 + + var matrix = CGAffineTransform(translationX: location.x, y: location.y) + matrix = matrix.scaledBy(x: scaleX, y: scaleY) + matrix = matrix.translatedBy(x: -location.x, y: -location.y) + + matrix = _viewPortHandler.touchMatrix.concatenating(matrix) + + _viewPortHandler.refresh(newMatrix: matrix, chart: self, invalidate: true) + + if delegate !== nil + { + delegate?.chartScaled?(self, scaleX: scaleX, scaleY: scaleY) + } + } + + recognizer.nsuiScale = 1.0 + } + } + } + #endif + + @objc private func panGestureRecognized(_ recognizer: NSUIPanGestureRecognizer) + { + if recognizer.state == NSUIGestureRecognizerState.began && recognizer.nsuiNumberOfTouches() > 0 + { + stopDeceleration() + + if _data === nil || !self.isDragEnabled + { // If we have no data, we have nothing to pan and no data to highlight + return + } + + // If drag is enabled and we are in a position where there's something to drag: + // * If we're zoomed in, then obviously we have something to drag. + // * If we have a drag offset - we always have something to drag + if !self.hasNoDragOffset || !self.isFullyZoomedOut + { + _isDragging = true + + _closestDataSetToTouch = getDataSetByTouchPoint(point: recognizer.nsuiLocationOfTouch(0, inView: self)) + + var translation = recognizer.translation(in: self) + if !self.dragXEnabled + { + translation.x = 0.0 + } + else if !self.dragYEnabled + { + translation.y = 0.0 + } + + let didUserDrag = translation.x != 0.0 || translation.y != 0.0 + + // Check to see if user dragged at all and if so, can the chart be dragged by the given amount + if didUserDrag && !performPanChange(translation: translation) + { + if _outerScrollView !== nil + { + // We can stop dragging right now, and let the scroll view take control + _outerScrollView = nil + _isDragging = false + } + } + else + { + if _outerScrollView !== nil + { + // Prevent the parent scroll view from scrolling + _outerScrollView?.nsuiIsScrollEnabled = false + } + } + + _lastPanPoint = recognizer.translation(in: self) + } + else if self.isHighlightPerDragEnabled + { + // We will only handle highlights on NSUIGestureRecognizerState.Changed + + _isDragging = false + } + } + else if recognizer.state == NSUIGestureRecognizerState.changed + { + if _isDragging + { + let originalTranslation = recognizer.translation(in: self) + var translation = CGPoint(x: originalTranslation.x - _lastPanPoint.x, y: originalTranslation.y - _lastPanPoint.y) + + if !self.dragXEnabled + { + translation.x = 0.0 + } + else if !self.dragYEnabled + { + translation.y = 0.0 + } + + let _ = performPanChange(translation: translation) + + _lastPanPoint = originalTranslation + } + else if isHighlightPerDragEnabled + { + let h = getHighlightByTouchPoint(recognizer.location(in: self)) + + let lastHighlighted = self.lastHighlighted + + if h != lastHighlighted + { + self.lastHighlighted = h + self.highlightValue(h, callDelegate: true) + } + } + } + else if recognizer.state == NSUIGestureRecognizerState.ended || recognizer.state == NSUIGestureRecognizerState.cancelled + { + if _isDragging + { + if recognizer.state == NSUIGestureRecognizerState.ended && isDragDecelerationEnabled + { + stopDeceleration() + + _decelerationLastTime = CACurrentMediaTime() + _decelerationVelocity = recognizer.velocity(in: self) + + _decelerationDisplayLink = NSUIDisplayLink(target: self, selector: #selector(BarLineChartViewBase.decelerationLoop)) + _decelerationDisplayLink.add(to: RunLoop.main, forMode: RunLoop.Mode.common) + } + + _isDragging = false + } + + if _outerScrollView !== nil + { + _outerScrollView?.nsuiIsScrollEnabled = true + _outerScrollView = nil + } + + delegate?.chartViewDidEndPanning?(self) + } + } + + private func performPanChange(translation: CGPoint) -> Bool + { + var translation = translation + + if isTouchInverted() + { + if self is HorizontalBarChartView + { + translation.x = -translation.x + } + else + { + translation.y = -translation.y + } + } + + let originalMatrix = _viewPortHandler.touchMatrix + + var matrix = CGAffineTransform(translationX: translation.x, y: translation.y) + matrix = originalMatrix.concatenating(matrix) + + matrix = _viewPortHandler.refresh(newMatrix: matrix, chart: self, invalidate: true) + + if matrix != originalMatrix + { + delegate?.chartTranslated?(self, dX: translation.x, dY: translation.y) + } + + // Did we managed to actually drag or did we reach the edge? + return matrix.tx != originalMatrix.tx || matrix.ty != originalMatrix.ty + } + + private func isTouchInverted() -> Bool + { + return isAnyAxisInverted && + _closestDataSetToTouch !== nil && + getAxis(_closestDataSetToTouch.axisDependency).isInverted + } + + @objc open func stopDeceleration() + { + if _decelerationDisplayLink !== nil + { + _decelerationDisplayLink.remove(from: RunLoop.main, forMode: RunLoop.Mode.common) + _decelerationDisplayLink = nil + } + } + + @objc private func decelerationLoop() + { + let currentTime = CACurrentMediaTime() + + _decelerationVelocity.x *= self.dragDecelerationFrictionCoef + _decelerationVelocity.y *= self.dragDecelerationFrictionCoef + + let timeInterval = CGFloat(currentTime - _decelerationLastTime) + + let distance = CGPoint( + x: _decelerationVelocity.x * timeInterval, + y: _decelerationVelocity.y * timeInterval + ) + + if !performPanChange(translation: distance) + { + // We reached the edge, stop + _decelerationVelocity.x = 0.0 + _decelerationVelocity.y = 0.0 + } + + _decelerationLastTime = currentTime + + if abs(_decelerationVelocity.x) < 0.001 && abs(_decelerationVelocity.y) < 0.001 + { + stopDeceleration() + + // Range might have changed, which means that Y-axis labels could have changed in size, affecting Y-axis size. So we need to recalculate offsets. + calculateOffsets() + setNeedsDisplay() + } + } + + private func nsuiGestureRecognizerShouldBegin(_ gestureRecognizer: NSUIGestureRecognizer) -> Bool + { + if gestureRecognizer == _panGestureRecognizer + { + let velocity = _panGestureRecognizer.velocity(in: self) + if _data === nil || !isDragEnabled || + (self.hasNoDragOffset && self.isFullyZoomedOut && !self.isHighlightPerDragEnabled) || + (!_dragYEnabled && abs(velocity.y) > abs(velocity.x)) || + (!_dragXEnabled && abs(velocity.y) < abs(velocity.x)) + { + return false + } + } + else + { + #if !os(tvOS) + if gestureRecognizer == _pinchGestureRecognizer + { + if _data === nil || (!_pinchZoomEnabled && !_scaleXEnabled && !_scaleYEnabled) + { + return false + } + } + #endif + } + + return true + } + + #if !os(OSX) + open override func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool + { + if !super.gestureRecognizerShouldBegin(gestureRecognizer) + { + return false + } + + return nsuiGestureRecognizerShouldBegin(gestureRecognizer) + } + #endif + + #if os(OSX) + public func gestureRecognizerShouldBegin(gestureRecognizer: NSGestureRecognizer) -> Bool + { + return nsuiGestureRecognizerShouldBegin(gestureRecognizer) + } + #endif + + open func gestureRecognizer(_ gestureRecognizer: NSUIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: NSUIGestureRecognizer) -> Bool + { + #if !os(tvOS) + if ((gestureRecognizer is NSUIPinchGestureRecognizer && otherGestureRecognizer is NSUIPanGestureRecognizer) || + (gestureRecognizer is NSUIPanGestureRecognizer && otherGestureRecognizer is NSUIPinchGestureRecognizer)) + { + return true + } + #endif + + if gestureRecognizer is NSUIPanGestureRecognizer, + otherGestureRecognizer is NSUIPanGestureRecognizer, + gestureRecognizer == _panGestureRecognizer + { + var scrollView = self.superview + while scrollView != nil && !(scrollView is NSUIScrollView) + { + scrollView = scrollView?.superview + } + + // If there is two scrollview together, we pick the superview of the inner scrollview. + // In the case of UITableViewWrepperView, the superview will be UITableView + if let superViewOfScrollView = scrollView?.superview, + superViewOfScrollView is NSUIScrollView + { + scrollView = superViewOfScrollView + } + + var foundScrollView = scrollView as? NSUIScrollView + + if !(foundScrollView?.nsuiIsScrollEnabled ?? true) + { + foundScrollView = nil + } + + let scrollViewPanGestureRecognizer = foundScrollView?.nsuiGestureRecognizers?.first { + $0 is NSUIPanGestureRecognizer + } + + if otherGestureRecognizer === scrollViewPanGestureRecognizer + { + _outerScrollView = foundScrollView + + return true + } + } + + return false + } + + /// MARK: Viewport modifiers + + /// Zooms in by 1.4, into the charts center. + @objc open func zoomIn() + { + let center = _viewPortHandler.contentCenter + + let matrix = _viewPortHandler.zoomIn(x: center.x, y: -center.y) + _viewPortHandler.refresh(newMatrix: matrix, chart: self, invalidate: false) + + // Range might have changed, which means that Y-axis labels could have changed in size, affecting Y-axis size. So we need to recalculate offsets. + calculateOffsets() + setNeedsDisplay() + } + + /// Zooms out by 0.7, from the charts center. + @objc open func zoomOut() + { + let center = _viewPortHandler.contentCenter + + let matrix = _viewPortHandler.zoomOut(x: center.x, y: -center.y) + _viewPortHandler.refresh(newMatrix: matrix, chart: self, invalidate: false) + + // Range might have changed, which means that Y-axis labels could have changed in size, affecting Y-axis size. So we need to recalculate offsets. + calculateOffsets() + setNeedsDisplay() + } + + /// Zooms out to original size. + @objc open func resetZoom() + { + let matrix = _viewPortHandler.resetZoom() + _viewPortHandler.refresh(newMatrix: matrix, chart: self, invalidate: false) + + // Range might have changed, which means that Y-axis labels could have changed in size, affecting Y-axis size. So we need to recalculate offsets. + calculateOffsets() + setNeedsDisplay() + } + + /// Zooms in or out by the given scale factor. x and y are the coordinates + /// (in pixels) of the zoom center. + /// + /// - Parameters: + /// - scaleX: if < 1 --> zoom out, if > 1 --> zoom in + /// - scaleY: if < 1 --> zoom out, if > 1 --> zoom in + /// - x: + /// - y: + @objc open func zoom( + scaleX: CGFloat, + scaleY: CGFloat, + x: CGFloat, + y: CGFloat) + { + let matrix = _viewPortHandler.zoom(scaleX: scaleX, scaleY: scaleY, x: x, y: -y) + _viewPortHandler.refresh(newMatrix: matrix, chart: self, invalidate: false) + + // Range might have changed, which means that Y-axis labels could have changed in size, affecting Y-axis size. So we need to recalculate offsets. + calculateOffsets() + setNeedsDisplay() + } + + /// Zooms in or out by the given scale factor. + /// x and y are the values (**not pixels**) of the zoom center. + /// + /// - Parameters: + /// - scaleX: if < 1 --> zoom out, if > 1 --> zoom in + /// - scaleY: if < 1 --> zoom out, if > 1 --> zoom in + /// - xValue: + /// - yValue: + /// - axis: + @objc open func zoom( + scaleX: CGFloat, + scaleY: CGFloat, + xValue: Double, + yValue: Double, + axis: YAxis.AxisDependency) + { + let job = ZoomViewJob( + viewPortHandler: viewPortHandler, + scaleX: scaleX, + scaleY: scaleY, + xValue: xValue, + yValue: yValue, + transformer: getTransformer(forAxis: axis), + axis: axis, + view: self) + addViewportJob(job) + } + + /// Zooms to the center of the chart with the given scale factor. + /// + /// - Parameters: + /// - scaleX: if < 1 --> zoom out, if > 1 --> zoom in + /// - scaleY: if < 1 --> zoom out, if > 1 --> zoom in + /// - xValue: + /// - yValue: + /// - axis: + @objc open func zoomToCenter( + scaleX: CGFloat, + scaleY: CGFloat) + { + let center = centerOffsets + let matrix = viewPortHandler.zoom( + scaleX: scaleX, + scaleY: scaleY, + x: center.x, + y: -center.y) + viewPortHandler.refresh(newMatrix: matrix, chart: self, invalidate: false) + } + + /// Zooms by the specified scale factor to the specified values on the specified axis. + /// + /// - Parameters: + /// - scaleX: + /// - scaleY: + /// - xValue: + /// - yValue: + /// - axis: which axis should be used as a reference for the y-axis + /// - duration: the duration of the animation in seconds + /// - easing: + @objc open func zoomAndCenterViewAnimated( + scaleX: CGFloat, + scaleY: CGFloat, + xValue: Double, + yValue: Double, + axis: YAxis.AxisDependency, + duration: TimeInterval, + easing: ChartEasingFunctionBlock?) + { + let origin = valueForTouchPoint( + point: CGPoint(x: viewPortHandler.contentLeft, y: viewPortHandler.contentTop), + axis: axis) + + let job = AnimatedZoomViewJob( + viewPortHandler: viewPortHandler, + transformer: getTransformer(forAxis: axis), + view: self, + yAxis: getAxis(axis), + xAxisRange: _xAxis.axisRange, + scaleX: scaleX, + scaleY: scaleY, + xOrigin: viewPortHandler.scaleX, + yOrigin: viewPortHandler.scaleY, + zoomCenterX: CGFloat(xValue), + zoomCenterY: CGFloat(yValue), + zoomOriginX: origin.x, + zoomOriginY: origin.y, + duration: duration, + easing: easing) + + addViewportJob(job) + } + + /// Zooms by the specified scale factor to the specified values on the specified axis. + /// + /// - Parameters: + /// - scaleX: + /// - scaleY: + /// - xValue: + /// - yValue: + /// - axis: which axis should be used as a reference for the y-axis + /// - duration: the duration of the animation in seconds + /// - easing: + @objc open func zoomAndCenterViewAnimated( + scaleX: CGFloat, + scaleY: CGFloat, + xValue: Double, + yValue: Double, + axis: YAxis.AxisDependency, + duration: TimeInterval, + easingOption: ChartEasingOption) + { + zoomAndCenterViewAnimated(scaleX: scaleX, scaleY: scaleY, xValue: xValue, yValue: yValue, axis: axis, duration: duration, easing: easingFunctionFromOption(easingOption)) + } + + /// Zooms by the specified scale factor to the specified values on the specified axis. + /// + /// - Parameters: + /// - scaleX: + /// - scaleY: + /// - xValue: + /// - yValue: + /// - axis: which axis should be used as a reference for the y-axis + /// - duration: the duration of the animation in seconds + /// - easing: + @objc open func zoomAndCenterViewAnimated( + scaleX: CGFloat, + scaleY: CGFloat, + xValue: Double, + yValue: Double, + axis: YAxis.AxisDependency, + duration: TimeInterval) + { + zoomAndCenterViewAnimated(scaleX: scaleX, scaleY: scaleY, xValue: xValue, yValue: yValue, axis: axis, duration: duration, easingOption: .easeInOutSine) + } + + /// Resets all zooming and dragging and makes the chart fit exactly it's bounds. + @objc open func fitScreen() + { + let matrix = _viewPortHandler.fitScreen() + _viewPortHandler.refresh(newMatrix: matrix, chart: self, invalidate: false) + + calculateOffsets() + setNeedsDisplay() + } + + /// Sets the minimum scale value to which can be zoomed out. 1 = fitScreen + @objc open func setScaleMinima(_ scaleX: CGFloat, scaleY: CGFloat) + { + _viewPortHandler.setMinimumScaleX(scaleX) + _viewPortHandler.setMinimumScaleY(scaleY) + } + + @objc open var visibleXRange: Double + { + return abs(highestVisibleX - lowestVisibleX) + } + + /// Sets the size of the area (range on the x-axis) that should be maximum visible at once (no further zooming out allowed). + /// + /// If this is e.g. set to 10, no more than a range of 10 values on the x-axis can be viewed at once without scrolling. + /// + /// If you call this method, chart must have data or it has no effect. + @objc open func setVisibleXRangeMaximum(_ maxXRange: Double) + { + let xScale = _xAxis.axisRange / maxXRange + _viewPortHandler.setMinimumScaleX(CGFloat(xScale)) + } + + /// Sets the size of the area (range on the x-axis) that should be minimum visible at once (no further zooming in allowed). + /// + /// If this is e.g. set to 10, no less than a range of 10 values on the x-axis can be viewed at once without scrolling. + /// + /// If you call this method, chart must have data or it has no effect. + @objc open func setVisibleXRangeMinimum(_ minXRange: Double) + { + let xScale = _xAxis.axisRange / minXRange + _viewPortHandler.setMaximumScaleX(CGFloat(xScale)) + } + + /// Limits the maximum and minimum value count that can be visible by pinching and zooming. + /// + /// e.g. minRange=10, maxRange=100 no less than 10 values and no more that 100 values can be viewed + /// at once without scrolling. + /// + /// If you call this method, chart must have data or it has no effect. + @objc open func setVisibleXRange(minXRange: Double, maxXRange: Double) + { + let minScale = _xAxis.axisRange / maxXRange + let maxScale = _xAxis.axisRange / minXRange + _viewPortHandler.setMinMaxScaleX( + minScaleX: CGFloat(minScale), + maxScaleX: CGFloat(maxScale)) + } + + /// Sets the size of the area (range on the y-axis) that should be maximum visible at once. + /// + /// - Parameters: + /// - yRange: + /// - axis: - the axis for which this limit should apply + @objc open func setVisibleYRangeMaximum(_ maxYRange: Double, axis: YAxis.AxisDependency) + { + let yScale = getAxisRange(axis: axis) / maxYRange + _viewPortHandler.setMinimumScaleY(CGFloat(yScale)) + } + + /// Sets the size of the area (range on the y-axis) that should be minimum visible at once, no further zooming in possible. + /// + /// - Parameters: + /// - yRange: + /// - axis: - the axis for which this limit should apply + @objc open func setVisibleYRangeMinimum(_ minYRange: Double, axis: YAxis.AxisDependency) + { + let yScale = getAxisRange(axis: axis) / minYRange + _viewPortHandler.setMaximumScaleY(CGFloat(yScale)) + } + + /// Limits the maximum and minimum y range that can be visible by pinching and zooming. + /// + /// - Parameters: + /// - minYRange: + /// - maxYRange: + /// - axis: + @objc open func setVisibleYRange(minYRange: Double, maxYRange: Double, axis: YAxis.AxisDependency) + { + let minScale = getAxisRange(axis: axis) / minYRange + let maxScale = getAxisRange(axis: axis) / maxYRange + _viewPortHandler.setMinMaxScaleY(minScaleY: CGFloat(minScale), maxScaleY: CGFloat(maxScale)) + } + + /// Moves the left side of the current viewport to the specified x-value. + /// This also refreshes the chart by calling setNeedsDisplay(). + @objc open func moveViewToX(_ xValue: Double) + { + let job = MoveViewJob( + viewPortHandler: viewPortHandler, + xValue: xValue, + yValue: 0.0, + transformer: getTransformer(forAxis: .left), + view: self) + + addViewportJob(job) + } + + /// Centers the viewport to the specified y-value on the y-axis. + /// This also refreshes the chart by calling setNeedsDisplay(). + /// + /// - Parameters: + /// - yValue: + /// - axis: - which axis should be used as a reference for the y-axis + @objc open func moveViewToY(_ yValue: Double, axis: YAxis.AxisDependency) + { + let yInView = getAxisRange(axis: axis) / Double(_viewPortHandler.scaleY) + + let job = MoveViewJob( + viewPortHandler: viewPortHandler, + xValue: 0.0, + yValue: yValue + yInView / 2.0, + transformer: getTransformer(forAxis: axis), + view: self) + + addViewportJob(job) + } + + /// This will move the left side of the current viewport to the specified x-value on the x-axis, and center the viewport to the specified y-value on the y-axis. + /// This also refreshes the chart by calling setNeedsDisplay(). + /// + /// - Parameters: + /// - xValue: + /// - yValue: + /// - axis: - which axis should be used as a reference for the y-axis + @objc open func moveViewTo(xValue: Double, yValue: Double, axis: YAxis.AxisDependency) + { + let yInView = getAxisRange(axis: axis) / Double(_viewPortHandler.scaleY) + + let job = MoveViewJob( + viewPortHandler: viewPortHandler, + xValue: xValue, + yValue: yValue + yInView / 2.0, + transformer: getTransformer(forAxis: axis), + view: self) + + addViewportJob(job) + } + + /// This will move the left side of the current viewport to the specified x-position and center the viewport to the specified y-position animated. + /// This also refreshes the chart by calling setNeedsDisplay(). + /// + /// - Parameters: + /// - xValue: + /// - yValue: + /// - axis: which axis should be used as a reference for the y-axis + /// - duration: the duration of the animation in seconds + /// - easing: + @objc open func moveViewToAnimated( + xValue: Double, + yValue: Double, + axis: YAxis.AxisDependency, + duration: TimeInterval, + easing: ChartEasingFunctionBlock?) + { + let bounds = valueForTouchPoint( + point: CGPoint(x: viewPortHandler.contentLeft, y: viewPortHandler.contentTop), + axis: axis) + + let yInView = getAxisRange(axis: axis) / Double(_viewPortHandler.scaleY) + + let job = AnimatedMoveViewJob( + viewPortHandler: viewPortHandler, + xValue: xValue, + yValue: yValue + yInView / 2.0, + transformer: getTransformer(forAxis: axis), + view: self, + xOrigin: bounds.x, + yOrigin: bounds.y, + duration: duration, + easing: easing) + + addViewportJob(job) + } + + /// This will move the left side of the current viewport to the specified x-position and center the viewport to the specified y-position animated. + /// This also refreshes the chart by calling setNeedsDisplay(). + /// + /// - Parameters: + /// - xValue: + /// - yValue: + /// - axis: which axis should be used as a reference for the y-axis + /// - duration: the duration of the animation in seconds + /// - easing: + @objc open func moveViewToAnimated( + xValue: Double, + yValue: Double, + axis: YAxis.AxisDependency, + duration: TimeInterval, + easingOption: ChartEasingOption) + { + moveViewToAnimated(xValue: xValue, yValue: yValue, axis: axis, duration: duration, easing: easingFunctionFromOption(easingOption)) + } + + /// This will move the left side of the current viewport to the specified x-position and center the viewport to the specified y-position animated. + /// This also refreshes the chart by calling setNeedsDisplay(). + /// + /// - Parameters: + /// - xValue: + /// - yValue: + /// - axis: which axis should be used as a reference for the y-axis + /// - duration: the duration of the animation in seconds + /// - easing: + @objc open func moveViewToAnimated( + xValue: Double, + yValue: Double, + axis: YAxis.AxisDependency, + duration: TimeInterval) + { + moveViewToAnimated(xValue: xValue, yValue: yValue, axis: axis, duration: duration, easingOption: .easeInOutSine) + } + + /// This will move the center of the current viewport to the specified x-value and y-value. + /// This also refreshes the chart by calling setNeedsDisplay(). + /// + /// - Parameters: + /// - xValue: + /// - yValue: + /// - axis: - which axis should be used as a reference for the y-axis + @objc open func centerViewTo( + xValue: Double, + yValue: Double, + axis: YAxis.AxisDependency) + { + let yInView = getAxisRange(axis: axis) / Double(_viewPortHandler.scaleY) + let xInView = xAxis.axisRange / Double(_viewPortHandler.scaleX) + + let job = MoveViewJob( + viewPortHandler: viewPortHandler, + xValue: xValue - xInView / 2.0, + yValue: yValue + yInView / 2.0, + transformer: getTransformer(forAxis: axis), + view: self) + + addViewportJob(job) + } + + /// This will move the center of the current viewport to the specified x-value and y-value animated. + /// + /// - Parameters: + /// - xValue: + /// - yValue: + /// - axis: which axis should be used as a reference for the y-axis + /// - duration: the duration of the animation in seconds + /// - easing: + @objc open func centerViewToAnimated( + xValue: Double, + yValue: Double, + axis: YAxis.AxisDependency, + duration: TimeInterval, + easing: ChartEasingFunctionBlock?) + { + let bounds = valueForTouchPoint( + point: CGPoint(x: viewPortHandler.contentLeft, y: viewPortHandler.contentTop), + axis: axis) + + let yInView = getAxisRange(axis: axis) / Double(_viewPortHandler.scaleY) + let xInView = xAxis.axisRange / Double(_viewPortHandler.scaleX) + + let job = AnimatedMoveViewJob( + viewPortHandler: viewPortHandler, + xValue: xValue - xInView / 2.0, + yValue: yValue + yInView / 2.0, + transformer: getTransformer(forAxis: axis), + view: self, + xOrigin: bounds.x, + yOrigin: bounds.y, + duration: duration, + easing: easing) + + addViewportJob(job) + } + + /// This will move the center of the current viewport to the specified x-value and y-value animated. + /// + /// - Parameters: + /// - xValue: + /// - yValue: + /// - axis: which axis should be used as a reference for the y-axis + /// - duration: the duration of the animation in seconds + /// - easing: + @objc open func centerViewToAnimated( + xValue: Double, + yValue: Double, + axis: YAxis.AxisDependency, + duration: TimeInterval, + easingOption: ChartEasingOption) + { + centerViewToAnimated(xValue: xValue, yValue: yValue, axis: axis, duration: duration, easing: easingFunctionFromOption(easingOption)) + } + + /// This will move the center of the current viewport to the specified x-value and y-value animated. + /// + /// - Parameters: + /// - xValue: + /// - yValue: + /// - axis: which axis should be used as a reference for the y-axis + /// - duration: the duration of the animation in seconds + /// - easing: + @objc open func centerViewToAnimated( + xValue: Double, + yValue: Double, + axis: YAxis.AxisDependency, + duration: TimeInterval) + { + centerViewToAnimated(xValue: xValue, yValue: yValue, axis: axis, duration: duration, easingOption: .easeInOutSine) + } + + /// Sets custom offsets for the current `ChartViewPort` (the offsets on the sides of the actual chart window). Setting this will prevent the chart from automatically calculating it's offsets. Use `resetViewPortOffsets()` to undo this. + /// ONLY USE THIS WHEN YOU KNOW WHAT YOU ARE DOING, else use `setExtraOffsets(...)`. + @objc open func setViewPortOffsets(left: CGFloat, top: CGFloat, right: CGFloat, bottom: CGFloat) + { + _customViewPortEnabled = true + + if Thread.isMainThread + { + self._viewPortHandler.restrainViewPort(offsetLeft: left, offsetTop: top, offsetRight: right, offsetBottom: bottom) + prepareOffsetMatrix() + prepareValuePxMatrix() + } + else + { + DispatchQueue.main.async(execute: { + self.setViewPortOffsets(left: left, top: top, right: right, bottom: bottom) + }) + } + } + + /// Resets all custom offsets set via `setViewPortOffsets(...)` method. Allows the chart to again calculate all offsets automatically. + @objc open func resetViewPortOffsets() + { + _customViewPortEnabled = false + calculateOffsets() + } + + // MARK: - Accessors + + /// - Returns: The range of the specified axis. + @objc open func getAxisRange(axis: YAxis.AxisDependency) -> Double + { + if axis == .left + { + return leftAxis.axisRange + } + else + { + return rightAxis.axisRange + } + } + + /// - Returns: The position (in pixels) the provided Entry has inside the chart view + @objc open func getPosition(entry e: ChartDataEntry, axis: YAxis.AxisDependency) -> CGPoint + { + var vals = CGPoint(x: CGFloat(e.x), y: CGFloat(e.y)) + + getTransformer(forAxis: axis).pointValueToPixel(&vals) + + return vals + } + + /// is dragging enabled? (moving the chart with the finger) for the chart (this does not affect scaling). + @objc open var dragEnabled: Bool + { + get + { + return _dragXEnabled || _dragYEnabled + } + set + { + _dragYEnabled = newValue + _dragXEnabled = newValue + } + } + + /// is dragging enabled? (moving the chart with the finger) for the chart (this does not affect scaling). + @objc open var isDragEnabled: Bool + { + return dragEnabled + } + + /// is dragging on the X axis enabled? + @objc open var dragXEnabled: Bool + { + get + { + return _dragXEnabled + } + set + { + _dragXEnabled = newValue + } + } + + /// is dragging on the Y axis enabled? + @objc open var dragYEnabled: Bool + { + get + { + return _dragYEnabled + } + set + { + _dragYEnabled = newValue + } + } + + /// is scaling enabled? (zooming in and out by gesture) for the chart (this does not affect dragging). + @objc open func setScaleEnabled(_ enabled: Bool) + { + if _scaleXEnabled != enabled || _scaleYEnabled != enabled + { + _scaleXEnabled = enabled + _scaleYEnabled = enabled + #if !os(tvOS) + _pinchGestureRecognizer.isEnabled = _pinchZoomEnabled || _scaleXEnabled || _scaleYEnabled + #endif + } + } + + @objc open var scaleXEnabled: Bool + { + get + { + return _scaleXEnabled + } + set + { + if _scaleXEnabled != newValue + { + _scaleXEnabled = newValue + #if !os(tvOS) + _pinchGestureRecognizer.isEnabled = _pinchZoomEnabled || _scaleXEnabled || _scaleYEnabled + #endif + } + } + } + + @objc open var scaleYEnabled: Bool + { + get + { + return _scaleYEnabled + } + set + { + if _scaleYEnabled != newValue + { + _scaleYEnabled = newValue + #if !os(tvOS) + _pinchGestureRecognizer.isEnabled = _pinchZoomEnabled || _scaleXEnabled || _scaleYEnabled + #endif + } + } + } + + @objc open var isScaleXEnabled: Bool { return scaleXEnabled } + @objc open var isScaleYEnabled: Bool { return scaleYEnabled } + + /// flag that indicates if double tap zoom is enabled or not + @objc open var doubleTapToZoomEnabled: Bool + { + get + { + return _doubleTapToZoomEnabled + } + set + { + if _doubleTapToZoomEnabled != newValue + { + _doubleTapToZoomEnabled = newValue + _doubleTapGestureRecognizer.isEnabled = _doubleTapToZoomEnabled + } + } + } + + /// **default**: true + /// `true` if zooming via double-tap is enabled `false` ifnot. + @objc open var isDoubleTapToZoomEnabled: Bool + { + return doubleTapToZoomEnabled + } + + /// flag that indicates if highlighting per dragging over a fully zoomed out chart is enabled + @objc open var highlightPerDragEnabled = true + + /// If set to true, highlighting per dragging over a fully zoomed out chart is enabled + /// You might want to disable this when using inside a `NSUIScrollView` + /// + /// **default**: true + @objc open var isHighlightPerDragEnabled: Bool + { + return highlightPerDragEnabled + } + + /// **default**: true + /// `true` if drawing the grid background is enabled, `false` ifnot. + @objc open var isDrawGridBackgroundEnabled: Bool + { + return drawGridBackgroundEnabled + } + + /// **default**: false + /// `true` if drawing the borders rectangle is enabled, `false` ifnot. + @objc open var isDrawBordersEnabled: Bool + { + return drawBordersEnabled + } + + /// - Returns: The x and y values in the chart at the given touch point + /// (encapsulated in a `CGPoint`). This method transforms pixel coordinates to + /// coordinates / values in the chart. This is the opposite method to + /// `getPixelsForValues(...)`. + @objc open func valueForTouchPoint(point pt: CGPoint, axis: YAxis.AxisDependency) -> CGPoint + { + return getTransformer(forAxis: axis).valueForTouchPoint(pt) + } + + /// Transforms the given chart values into pixels. This is the opposite + /// method to `valueForTouchPoint(...)`. + @objc open func pixelForValues(x: Double, y: Double, axis: YAxis.AxisDependency) -> CGPoint + { + return getTransformer(forAxis: axis).pixelForValues(x: x, y: y) + } + + /// - Returns: The Entry object displayed at the touched position of the chart + @objc open func getEntryByTouchPoint(point pt: CGPoint) -> ChartDataEntry! + { + if let h = getHighlightByTouchPoint(pt) + { + return _data!.entryForHighlight(h) + } + return nil + } + + /// - Returns: The DataSet object displayed at the touched position of the chart + @objc open func getDataSetByTouchPoint(point pt: CGPoint) -> IBarLineScatterCandleBubbleChartDataSet? + { + let h = getHighlightByTouchPoint(pt) + if h !== nil + { + return _data?.getDataSetByIndex(h!.dataSetIndex) as? IBarLineScatterCandleBubbleChartDataSet + } + return nil + } + + /// The current x-scale factor + @objc open var scaleX: CGFloat + { + if _viewPortHandler === nil + { + return 1.0 + } + return _viewPortHandler.scaleX + } + + /// The current y-scale factor + @objc open var scaleY: CGFloat + { + if _viewPortHandler === nil + { + return 1.0 + } + return _viewPortHandler.scaleY + } + + /// if the chart is fully zoomed out, return true + @objc open var isFullyZoomedOut: Bool { return _viewPortHandler.isFullyZoomedOut } + + /// - Returns: The y-axis object to the corresponding AxisDependency. In the + /// horizontal bar-chart, LEFT == top, RIGHT == BOTTOM + @objc open func getAxis(_ axis: YAxis.AxisDependency) -> YAxis + { + if axis == .left + { + return leftAxis + } + else + { + return rightAxis + } + } + + /// flag that indicates if pinch-zoom is enabled. if true, both x and y axis can be scaled simultaneously with 2 fingers, if false, x and y axis can be scaled separately + @objc open var pinchZoomEnabled: Bool + { + get + { + return _pinchZoomEnabled + } + set + { + if _pinchZoomEnabled != newValue + { + _pinchZoomEnabled = newValue + #if !os(tvOS) + _pinchGestureRecognizer.isEnabled = _pinchZoomEnabled || _scaleXEnabled || _scaleYEnabled + #endif + } + } + } + + /// **default**: false + /// `true` if pinch-zoom is enabled, `false` ifnot + @objc open var isPinchZoomEnabled: Bool { return pinchZoomEnabled } + + /// Set an offset in dp that allows the user to drag the chart over it's + /// bounds on the x-axis. + @objc open func setDragOffsetX(_ offset: CGFloat) + { + _viewPortHandler.setDragOffsetX(offset) + } + + /// Set an offset in dp that allows the user to drag the chart over it's + /// bounds on the y-axis. + @objc open func setDragOffsetY(_ offset: CGFloat) + { + _viewPortHandler.setDragOffsetY(offset) + } + + /// `true` if both drag offsets (x and y) are zero or smaller. + @objc open var hasNoDragOffset: Bool { return _viewPortHandler.hasNoDragOffset } + + open override var chartYMax: Double + { + return max(leftAxis._axisMaximum, rightAxis._axisMaximum) + } + + open override var chartYMin: Double + { + return min(leftAxis._axisMinimum, rightAxis._axisMinimum) + } + + /// `true` if either the left or the right or both axes are inverted. + @objc open var isAnyAxisInverted: Bool + { + return leftAxis.isInverted || rightAxis.isInverted + } + + /// flag that indicates if auto scaling on the y axis is enabled. + /// if yes, the y axis automatically adjusts to the min and max y values of the current x axis range whenever the viewport changes + @objc open var autoScaleMinMaxEnabled: Bool + { + get { return _autoScaleMinMaxEnabled } + set { _autoScaleMinMaxEnabled = newValue } + } + + /// **default**: false + /// `true` if auto scaling on the y axis is enabled. + @objc open var isAutoScaleMinMaxEnabled : Bool { return autoScaleMinMaxEnabled } + + /// Sets a minimum width to the specified y axis. + @objc open func setYAxisMinWidth(_ axis: YAxis.AxisDependency, width: CGFloat) + { + if axis == .left + { + leftAxis.minWidth = width + } + else + { + rightAxis.minWidth = width + } + } + + /// **default**: 0.0 + /// + /// - Returns: The (custom) minimum width of the specified Y axis. + @objc open func getYAxisMinWidth(_ axis: YAxis.AxisDependency) -> CGFloat + { + if axis == .left + { + return leftAxis.minWidth + } + else + { + return rightAxis.minWidth + } + } + /// Sets a maximum width to the specified y axis. + /// Zero (0.0) means there's no maximum width + @objc open func setYAxisMaxWidth(_ axis: YAxis.AxisDependency, width: CGFloat) + { + if axis == .left + { + leftAxis.maxWidth = width + } + else + { + rightAxis.maxWidth = width + } + } + + /// Zero (0.0) means there's no maximum width + /// + /// **default**: 0.0 (no maximum specified) + /// + /// - Returns: The (custom) maximum width of the specified Y axis. + @objc open func getYAxisMaxWidth(_ axis: YAxis.AxisDependency) -> CGFloat + { + if axis == .left + { + return leftAxis.maxWidth + } + else + { + return rightAxis.maxWidth + } + } + + /// - Returns the width of the specified y axis. + @objc open func getYAxisWidth(_ axis: YAxis.AxisDependency) -> CGFloat + { + if axis == .left + { + return leftAxis.requiredSize().width + } + else + { + return rightAxis.requiredSize().width + } + } + + // MARK: - BarLineScatterCandleBubbleChartDataProvider + + /// - Returns: The Transformer class that contains all matrices and is + /// responsible for transforming values into pixels on the screen and + /// backwards. + open func getTransformer(forAxis axis: YAxis.AxisDependency) -> Transformer + { + if axis == .left + { + return _leftAxisTransformer + } + else + { + return _rightAxisTransformer + } + } + + /// the number of maximum visible drawn values on the chart only active when `drawValuesEnabled` is enabled + open override var maxVisibleCount: Int + { + get + { + return _maxVisibleCount + } + set + { + _maxVisibleCount = newValue + } + } + + open func isInverted(axis: YAxis.AxisDependency) -> Bool + { + return getAxis(axis).isInverted + } + + /// The lowest x-index (value on the x-axis) that is still visible on he chart. + open var lowestVisibleX: Double + { + var pt = CGPoint( + x: viewPortHandler.contentLeft, + y: viewPortHandler.contentBottom) + + getTransformer(forAxis: .left).pixelToValues(&pt) + + return max(xAxis._axisMinimum, Double(pt.x)) + } + + /// The highest x-index (value on the x-axis) that is still visible on the chart. + open var highestVisibleX: Double + { + var pt = CGPoint( + x: viewPortHandler.contentRight, + y: viewPortHandler.contentBottom) + + getTransformer(forAxis: .left).pixelToValues(&pt) + + return min(xAxis._axisMaximum, Double(pt.x)) + } +} diff --git a/Pods/Charts/Source/Charts/Charts/BubbleChartView.swift b/Pods/Charts/Source/Charts/Charts/BubbleChartView.swift new file mode 100644 index 00000000..1b136775 --- /dev/null +++ b/Pods/Charts/Source/Charts/Charts/BubbleChartView.swift @@ -0,0 +1,27 @@ +// +// BubbleChartView.swift +// Charts +// +// Bubble chart implementation: +// Copyright 2015 Pierre-Marc Airoldi +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + +open class BubbleChartView: BarLineChartViewBase, BubbleChartDataProvider +{ + open override func initialize() + { + super.initialize() + + renderer = BubbleChartRenderer(dataProvider: self, animator: _animator, viewPortHandler: _viewPortHandler) + } + + // MARK: - BubbleChartDataProvider + + open var bubbleData: BubbleChartData? { return _data as? BubbleChartData } +} diff --git a/Pods/Charts/Source/Charts/Charts/CandleStickChartView.swift b/Pods/Charts/Source/Charts/Charts/CandleStickChartView.swift new file mode 100644 index 00000000..0366e8b8 --- /dev/null +++ b/Pods/Charts/Source/Charts/Charts/CandleStickChartView.swift @@ -0,0 +1,34 @@ +// +// CandleStickChartView.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + +/// Financial chart type that draws candle-sticks. +open class CandleStickChartView: BarLineChartViewBase, CandleChartDataProvider +{ + internal override func initialize() + { + super.initialize() + + renderer = CandleStickChartRenderer(dataProvider: self, animator: _animator, viewPortHandler: _viewPortHandler) + + self.xAxis.spaceMin = 0.5 + self.xAxis.spaceMax = 0.5 + } + + // MARK: - CandleChartDataProvider + + open var candleData: CandleChartData? + { + return _data as? CandleChartData + } +} diff --git a/Pods/Charts/Source/Charts/Charts/ChartViewBase.swift b/Pods/Charts/Source/Charts/Charts/ChartViewBase.swift new file mode 100644 index 00000000..0b58b263 --- /dev/null +++ b/Pods/Charts/Source/Charts/Charts/ChartViewBase.swift @@ -0,0 +1,1034 @@ +// +// ChartViewBase.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 +// +// Based on https://github.com/PhilJay/MPAndroidChart/commit/c42b880 + +import Foundation +import CoreGraphics + +@objc +public protocol ChartViewDelegate +{ + /// Called when a value has been selected inside the chart. + /// + /// - Parameters: + /// - entry: The selected Entry. + /// - highlight: The corresponding highlight object that contains information about the highlighted position such as dataSetIndex etc. + @objc optional func chartValueSelected(_ chartView: ChartViewBase, entry: ChartDataEntry, highlight: Highlight) + + /// Called when a user stops panning between values on the chart + @objc optional func chartViewDidEndPanning(_ chartView: ChartViewBase) + + // Called when nothing has been selected or an "un-select" has been made. + @objc optional func chartValueNothingSelected(_ chartView: ChartViewBase) + + // Callbacks when the chart is scaled / zoomed via pinch zoom gesture. + @objc optional func chartScaled(_ chartView: ChartViewBase, scaleX: CGFloat, scaleY: CGFloat) + + // Callbacks when the chart is moved / translated via drag gesture. + @objc optional func chartTranslated(_ chartView: ChartViewBase, dX: CGFloat, dY: CGFloat) + + // Callbacks when Animator stops animating + @objc optional func chartView(_ chartView: ChartViewBase, animatorDidStop animator: Animator) +} + +open class ChartViewBase: NSUIView, ChartDataProvider, AnimatorDelegate +{ + // MARK: - Properties + + /// - Returns: The object representing all x-labels, this method can be used to + /// acquire the XAxis object and modify it (e.g. change the position of the + /// labels) + @objc open var xAxis: XAxis + { + return _xAxis + } + + /// The default IValueFormatter that has been determined by the chart considering the provided minimum and maximum values. + internal var _defaultValueFormatter: IValueFormatter? = DefaultValueFormatter(decimals: 0) + + /// object that holds all data that was originally set for the chart, before it was modified or any filtering algorithms had been applied + internal var _data: ChartData? + + /// Flag that indicates if highlighting per tap (touch) is enabled + private var _highlightPerTapEnabled = true + + /// If set to true, chart continues to scroll after touch up + @objc open var dragDecelerationEnabled = true + + /// Deceleration friction coefficient in [0 ; 1] interval, higher values indicate that speed will decrease slowly, for example if it set to 0, it will stop immediately. + /// 1 is an invalid value, and will be converted to 0.999 automatically. + private var _dragDecelerationFrictionCoef: CGFloat = 0.9 + + /// if true, units are drawn next to the values in the chart + internal var _drawUnitInChart = false + + /// The object representing the labels on the x-axis + internal var _xAxis: XAxis! + + /// The `Description` object of the chart. + /// This should have been called just "description", but + @objc open var chartDescription: Description? + + /// The legend object containing all data associated with the legend + internal var _legend: Legend! + + /// delegate to receive chart events + @objc open weak var delegate: ChartViewDelegate? + + /// text that is displayed when the chart is empty + @objc open var noDataText = "No chart data available." + + /// Font to be used for the no data text. + @objc open var noDataFont = NSUIFont.systemFont(ofSize: 12) + + /// color of the no data text + @objc open var noDataTextColor: NSUIColor = NSUIColor.black + + /// alignment of the no data text + @objc open var noDataTextAlignment: NSTextAlignment = .left + + internal var _legendRenderer: LegendRenderer! + + /// object responsible for rendering the data + @objc open var renderer: DataRenderer? + + @objc open var highlighter: IHighlighter? + + /// object that manages the bounds and drawing constraints of the chart + internal var _viewPortHandler: ViewPortHandler! + + /// object responsible for animations + internal var _animator: Animator! + + /// flag that indicates if offsets calculation has already been done or not + private var _offsetsCalculated = false + + /// array of Highlight objects that reference the highlighted slices in the chart + internal var _indicesToHighlight = [Highlight]() + + /// `true` if drawing the marker is enabled when tapping on values + /// (use the `marker` property to specify a marker) + @objc open var drawMarkers = true + + /// - Returns: `true` if drawing the marker is enabled when tapping on values + /// (use the `marker` property to specify a marker) + @objc open var isDrawMarkersEnabled: Bool { return drawMarkers } + + /// The marker that is displayed when a value is clicked on the chart + @objc open var marker: IMarker? + + private var _interceptTouchEvents = false + + /// An extra offset to be appended to the viewport's top + @objc open var extraTopOffset: CGFloat = 0.0 + + /// An extra offset to be appended to the viewport's right + @objc open var extraRightOffset: CGFloat = 0.0 + + /// An extra offset to be appended to the viewport's bottom + @objc open var extraBottomOffset: CGFloat = 0.0 + + /// An extra offset to be appended to the viewport's left + @objc open var extraLeftOffset: CGFloat = 0.0 + + @objc open func setExtraOffsets(left: CGFloat, top: CGFloat, right: CGFloat, bottom: CGFloat) + { + extraLeftOffset = left + extraTopOffset = top + extraRightOffset = right + extraBottomOffset = bottom + } + + // MARK: - Initializers + + public override init(frame: CGRect) + { + super.init(frame: frame) + initialize() + } + + public required init?(coder aDecoder: NSCoder) + { + super.init(coder: aDecoder) + initialize() + } + + deinit + { + self.removeObserver(self, forKeyPath: "bounds") + self.removeObserver(self, forKeyPath: "frame") + } + + internal func initialize() + { + #if os(iOS) + self.backgroundColor = NSUIColor.clear + #endif + + _animator = Animator() + _animator.delegate = self + + _viewPortHandler = ViewPortHandler(width: bounds.size.width, height: bounds.size.height) + + chartDescription = Description() + + _legend = Legend() + _legendRenderer = LegendRenderer(viewPortHandler: _viewPortHandler, legend: _legend) + + _xAxis = XAxis() + + self.addObserver(self, forKeyPath: "bounds", options: .new, context: nil) + self.addObserver(self, forKeyPath: "frame", options: .new, context: nil) + } + + // MARK: - ChartViewBase + + /// The data for the chart + open var data: ChartData? + { + get + { + return _data + } + set + { + _data = newValue + _offsetsCalculated = false + + guard let _data = _data else + { + setNeedsDisplay() + return + } + + // calculate how many digits are needed + setupDefaultFormatter(min: _data.getYMin(), max: _data.getYMax()) + + for set in _data.dataSets + { + if set.needsFormatter || set.valueFormatter === _defaultValueFormatter + { + set.valueFormatter = _defaultValueFormatter + } + } + + // let the chart know there is new data + notifyDataSetChanged() + } + } + + /// Clears the chart from all data (sets it to null) and refreshes it (by calling setNeedsDisplay()). + @objc open func clear() + { + _data = nil + _offsetsCalculated = false + _indicesToHighlight.removeAll() + lastHighlighted = nil + + setNeedsDisplay() + } + + /// Removes all DataSets (and thereby Entries) from the chart. Does not set the data object to nil. Also refreshes the chart by calling setNeedsDisplay(). + @objc open func clearValues() + { + _data?.clearValues() + setNeedsDisplay() + } + + /// - Returns: `true` if the chart is empty (meaning it's data object is either null or contains no entries). + @objc open func isEmpty() -> Bool + { + guard let data = _data else { return true } + + if data.entryCount <= 0 + { + return true + } + else + { + return false + } + } + + /// Lets the chart know its underlying data has changed and should perform all necessary recalculations. + /// It is crucial that this method is called everytime data is changed dynamically. Not calling this method can lead to crashes or unexpected behaviour. + @objc open func notifyDataSetChanged() + { + fatalError("notifyDataSetChanged() cannot be called on ChartViewBase") + } + + /// Calculates the offsets of the chart to the border depending on the position of an eventual legend or depending on the length of the y-axis and x-axis labels and their position + internal func calculateOffsets() + { + fatalError("calculateOffsets() cannot be called on ChartViewBase") + } + + /// calcualtes the y-min and y-max value and the y-delta and x-delta value + internal func calcMinMax() + { + fatalError("calcMinMax() cannot be called on ChartViewBase") + } + + /// calculates the required number of digits for the values that might be drawn in the chart (if enabled), and creates the default value formatter + internal func setupDefaultFormatter(min: Double, max: Double) + { + // check if a custom formatter is set or not + var reference = Double(0.0) + + if let data = _data , data.entryCount >= 2 + { + reference = fabs(max - min) + } + else + { + let absMin = fabs(min) + let absMax = fabs(max) + reference = absMin > absMax ? absMin : absMax + } + + + if _defaultValueFormatter is DefaultValueFormatter + { + // setup the formatter with a new number of digits + let digits = reference.decimalPlaces + + (_defaultValueFormatter as? DefaultValueFormatter)?.decimals + = digits + } + } + + open override func draw(_ rect: CGRect) + { + let optionalContext = NSUIGraphicsGetCurrentContext() + guard let context = optionalContext else { return } + + let frame = self.bounds + + if _data === nil && noDataText.count > 0 + { + context.saveGState() + defer { context.restoreGState() } + + let paragraphStyle = NSMutableParagraphStyle.default.mutableCopy() as! NSMutableParagraphStyle + paragraphStyle.minimumLineHeight = noDataFont.lineHeight + paragraphStyle.lineBreakMode = .byWordWrapping + paragraphStyle.alignment = noDataTextAlignment + + ChartUtils.drawMultilineText( + context: context, + text: noDataText, + point: CGPoint(x: frame.width / 2.0, y: frame.height / 2.0), + attributes: + [.font: noDataFont, + .foregroundColor: noDataTextColor, + .paragraphStyle: paragraphStyle], + constrainedToSize: self.bounds.size, + anchor: CGPoint(x: 0.5, y: 0.5), + angleRadians: 0.0) + + return + } + + if !_offsetsCalculated + { + calculateOffsets() + _offsetsCalculated = true + } + } + + /// Draws the description text in the bottom right corner of the chart (per default) + internal func drawDescription(context: CGContext) + { + // check if description should be drawn + guard + let description = chartDescription, + description.isEnabled, + let descriptionText = description.text, + descriptionText.count > 0 + else { return } + + let position = description.position ?? CGPoint(x: bounds.width - _viewPortHandler.offsetRight - description.xOffset, + y: bounds.height - _viewPortHandler.offsetBottom - description.yOffset - description.font.lineHeight) + + var attrs = [NSAttributedString.Key : Any]() + + attrs[NSAttributedString.Key.font] = description.font + attrs[NSAttributedString.Key.foregroundColor] = description.textColor + + ChartUtils.drawText( + context: context, + text: descriptionText, + point: position, + align: description.textAlign, + attributes: attrs) + } + + // MARK: - Accessibility + + open override func accessibilityChildren() -> [Any]? { + return renderer?.accessibleChartElements + } + + // MARK: - Highlighting + + /// The array of currently highlighted values. This might an empty if nothing is highlighted. + @objc open var highlighted: [Highlight] + { + return _indicesToHighlight + } + + /// Set this to false to prevent values from being highlighted by tap gesture. + /// Values can still be highlighted via drag or programmatically. + /// **default**: true + @objc open var highlightPerTapEnabled: Bool + { + get { return _highlightPerTapEnabled } + set { _highlightPerTapEnabled = newValue } + } + + /// `true` if values can be highlighted via tap gesture, `false` ifnot. + @objc open var isHighLightPerTapEnabled: Bool + { + return highlightPerTapEnabled + } + + /// Checks if the highlight array is null, has a length of zero or if the first object is null. + /// + /// - Returns: `true` if there are values to highlight, `false` ifthere are no values to highlight. + @objc open func valuesToHighlight() -> Bool + { + return !_indicesToHighlight.isEmpty + } + + /// Highlights the values at the given indices in the given DataSets. Provide + /// null or an empty array to undo all highlighting. + /// This should be used to programmatically highlight values. + /// This method *will not* call the delegate. + @objc open func highlightValues(_ highs: [Highlight]?) + { + // set the indices to highlight + _indicesToHighlight = highs ?? [Highlight]() + + if _indicesToHighlight.isEmpty + { + self.lastHighlighted = nil + } + else + { + self.lastHighlighted = _indicesToHighlight[0] + } + + // redraw the chart + setNeedsDisplay() + } + + /// Highlights any y-value at the given x-value in the given DataSet. + /// Provide -1 as the dataSetIndex to undo all highlighting. + /// This method will call the delegate. + /// + /// - Parameters: + /// - x: The x-value to highlight + /// - dataSetIndex: The dataset index to search in + /// - dataIndex: The data index to search in (only used in CombinedChartView currently) + @objc open func highlightValue(x: Double, dataSetIndex: Int, dataIndex: Int = -1) + { + highlightValue(x: x, dataSetIndex: dataSetIndex, dataIndex: dataIndex, callDelegate: true) + } + + /// Highlights the value at the given x-value and y-value in the given DataSet. + /// Provide -1 as the dataSetIndex to undo all highlighting. + /// This method will call the delegate. + /// + /// - Parameters: + /// - x: The x-value to highlight + /// - y: The y-value to highlight. Supply `NaN` for "any" + /// - dataSetIndex: The dataset index to search in + /// - dataIndex: The data index to search in (only used in CombinedChartView currently) + @objc open func highlightValue(x: Double, y: Double, dataSetIndex: Int, dataIndex: Int = -1) + { + highlightValue(x: x, y: y, dataSetIndex: dataSetIndex, dataIndex: dataIndex, callDelegate: true) + } + + /// Highlights any y-value at the given x-value in the given DataSet. + /// Provide -1 as the dataSetIndex to undo all highlighting. + /// + /// - Parameters: + /// - x: The x-value to highlight + /// - dataSetIndex: The dataset index to search in + /// - dataIndex: The data index to search in (only used in CombinedChartView currently) + /// - callDelegate: Should the delegate be called for this change + @objc open func highlightValue(x: Double, dataSetIndex: Int, dataIndex: Int = -1, callDelegate: Bool) + { + highlightValue(x: x, y: .nan, dataSetIndex: dataSetIndex, dataIndex: dataIndex, callDelegate: callDelegate) + } + + /// Highlights the value at the given x-value and y-value in the given DataSet. + /// Provide -1 as the dataSetIndex to undo all highlighting. + /// + /// - Parameters: + /// - x: The x-value to highlight + /// - y: The y-value to highlight. Supply `NaN` for "any" + /// - dataSetIndex: The dataset index to search in + /// - dataIndex: The data index to search in (only used in CombinedChartView currently) + /// - callDelegate: Should the delegate be called for this change + @objc open func highlightValue(x: Double, y: Double, dataSetIndex: Int, dataIndex: Int = -1, callDelegate: Bool) + { + guard let data = _data else + { + Swift.print("Value not highlighted because data is nil") + return + } + + if dataSetIndex < 0 || dataSetIndex >= data.dataSetCount + { + highlightValue(nil, callDelegate: callDelegate) + } + else + { + highlightValue(Highlight(x: x, y: y, dataSetIndex: dataSetIndex, dataIndex: dataIndex), callDelegate: callDelegate) + } + } + + /// Highlights the values represented by the provided Highlight object + /// This method *will not* call the delegate. + /// + /// - Parameters: + /// - highlight: contains information about which entry should be highlighted + @objc open func highlightValue(_ highlight: Highlight?) + { + highlightValue(highlight, callDelegate: false) + } + + /// Highlights the value selected by touch gesture. + @objc open func highlightValue(_ highlight: Highlight?, callDelegate: Bool) + { + var entry: ChartDataEntry? + var h = highlight + + if h == nil + { + self.lastHighlighted = nil + _indicesToHighlight.removeAll(keepingCapacity: false) + } + else + { + // set the indices to highlight + entry = _data?.entryForHighlight(h!) + if entry == nil + { + h = nil + _indicesToHighlight.removeAll(keepingCapacity: false) + } + else + { + _indicesToHighlight = [h!] + } + } + + if callDelegate, let delegate = delegate + { + if let h = h + { + // notify the listener + delegate.chartValueSelected?(self, entry: entry!, highlight: h) + } + else + { + delegate.chartValueNothingSelected?(self) + } + } + + // redraw the chart + setNeedsDisplay() + } + + /// - Returns: The Highlight object (contains x-index and DataSet index) of the + /// selected value at the given touch point inside the Line-, Scatter-, or + /// CandleStick-Chart. + @objc open func getHighlightByTouchPoint(_ pt: CGPoint) -> Highlight? + { + if _data === nil + { + Swift.print("Can't select by touch. No data set.") + return nil + } + + return self.highlighter?.getHighlight(x: pt.x, y: pt.y) + } + + /// The last value that was highlighted via touch. + @objc open var lastHighlighted: Highlight? + + // MARK: - Markers + + /// draws all MarkerViews on the highlighted positions + internal func drawMarkers(context: CGContext) + { + // if there is no marker view or drawing marker is disabled + guard + let marker = marker + , isDrawMarkersEnabled && + valuesToHighlight() + else { return } + + for i in 0 ..< _indicesToHighlight.count + { + let highlight = _indicesToHighlight[i] + + guard let + set = data?.getDataSetByIndex(highlight.dataSetIndex), + 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) + } + } + + /// - Returns: The actual position in pixels of the MarkerView for the given Entry in the given DataSet. + @objc open func getMarkerPosition(highlight: Highlight) -> CGPoint + { + return CGPoint(x: highlight.drawX, y: highlight.drawY) + } + + // MARK: - Animation + + /// The animator responsible for animating chart values. + @objc open var chartAnimator: Animator! + { + return _animator + } + + /// Animates the drawing / rendering of the chart on both x- and y-axis with the specified animation time. + /// If `animate(...)` is called, no further calling of `invalidate()` is necessary to refresh the chart. + /// + /// - Parameters: + /// - xAxisDuration: duration for animating the x axis + /// - yAxisDuration: duration for animating the y axis + /// - easingX: an easing function for the animation on the x axis + /// - easingY: an easing function for the animation on the y axis + @objc open func animate(xAxisDuration: TimeInterval, yAxisDuration: TimeInterval, easingX: ChartEasingFunctionBlock?, easingY: ChartEasingFunctionBlock?) + { + _animator.animate(xAxisDuration: xAxisDuration, yAxisDuration: yAxisDuration, easingX: easingX, easingY: easingY) + } + + /// Animates the drawing / rendering of the chart on both x- and y-axis with the specified animation time. + /// If `animate(...)` is called, no further calling of `invalidate()` is necessary to refresh the chart. + /// + /// - Parameters: + /// - xAxisDuration: duration for animating the x axis + /// - yAxisDuration: duration for animating the y axis + /// - easingOptionX: the easing function for the animation on the x axis + /// - easingOptionY: the easing function for the animation on the y axis + @objc open func animate(xAxisDuration: TimeInterval, yAxisDuration: TimeInterval, easingOptionX: ChartEasingOption, easingOptionY: ChartEasingOption) + { + _animator.animate(xAxisDuration: xAxisDuration, yAxisDuration: yAxisDuration, easingOptionX: easingOptionX, easingOptionY: easingOptionY) + } + + /// Animates the drawing / rendering of the chart on both x- and y-axis with the specified animation time. + /// If `animate(...)` is called, no further calling of `invalidate()` is necessary to refresh the chart. + /// + /// - Parameters: + /// - xAxisDuration: duration for animating the x axis + /// - yAxisDuration: duration for animating the y axis + /// - easing: an easing function for the animation + @objc open func animate(xAxisDuration: TimeInterval, yAxisDuration: TimeInterval, easing: ChartEasingFunctionBlock?) + { + _animator.animate(xAxisDuration: xAxisDuration, yAxisDuration: yAxisDuration, easing: easing) + } + + /// Animates the drawing / rendering of the chart on both x- and y-axis with the specified animation time. + /// If `animate(...)` is called, no further calling of `invalidate()` is necessary to refresh the chart. + /// + /// - Parameters: + /// - xAxisDuration: duration for animating the x axis + /// - yAxisDuration: duration for animating the y axis + /// - easingOption: the easing function for the animation + @objc open func animate(xAxisDuration: TimeInterval, yAxisDuration: TimeInterval, easingOption: ChartEasingOption) + { + _animator.animate(xAxisDuration: xAxisDuration, yAxisDuration: yAxisDuration, easingOption: easingOption) + } + + /// Animates the drawing / rendering of the chart on both x- and y-axis with the specified animation time. + /// If `animate(...)` is called, no further calling of `invalidate()` is necessary to refresh the chart. + /// + /// - Parameters: + /// - xAxisDuration: duration for animating the x axis + /// - yAxisDuration: duration for animating the y axis + @objc open func animate(xAxisDuration: TimeInterval, yAxisDuration: TimeInterval) + { + _animator.animate(xAxisDuration: xAxisDuration, yAxisDuration: yAxisDuration) + } + + /// Animates the drawing / rendering of the chart the x-axis with the specified animation time. + /// If `animate(...)` is called, no further calling of `invalidate()` is necessary to refresh the chart. + /// + /// - Parameters: + /// - xAxisDuration: duration for animating the x axis + /// - easing: an easing function for the animation + @objc open func animate(xAxisDuration: TimeInterval, easing: ChartEasingFunctionBlock?) + { + _animator.animate(xAxisDuration: xAxisDuration, easing: easing) + } + + /// Animates the drawing / rendering of the chart the x-axis with the specified animation time. + /// If `animate(...)` is called, no further calling of `invalidate()` is necessary to refresh the chart. + /// + /// - Parameters: + /// - xAxisDuration: duration for animating the x axis + /// - easingOption: the easing function for the animation + @objc open func animate(xAxisDuration: TimeInterval, easingOption: ChartEasingOption) + { + _animator.animate(xAxisDuration: xAxisDuration, easingOption: easingOption) + } + + /// Animates the drawing / rendering of the chart the x-axis with the specified animation time. + /// If `animate(...)` is called, no further calling of `invalidate()` is necessary to refresh the chart. + /// + /// - Parameters: + /// - xAxisDuration: duration for animating the x axis + @objc open func animate(xAxisDuration: TimeInterval) + { + _animator.animate(xAxisDuration: xAxisDuration) + } + + /// Animates the drawing / rendering of the chart the y-axis with the specified animation time. + /// If `animate(...)` is called, no further calling of `invalidate()` is necessary to refresh the chart. + /// + /// - Parameters: + /// - yAxisDuration: duration for animating the y axis + /// - easing: an easing function for the animation + @objc open func animate(yAxisDuration: TimeInterval, easing: ChartEasingFunctionBlock?) + { + _animator.animate(yAxisDuration: yAxisDuration, easing: easing) + } + + /// Animates the drawing / rendering of the chart the y-axis with the specified animation time. + /// If `animate(...)` is called, no further calling of `invalidate()` is necessary to refresh the chart. + /// + /// - Parameters: + /// - yAxisDuration: duration for animating the y axis + /// - easingOption: the easing function for the animation + @objc open func animate(yAxisDuration: TimeInterval, easingOption: ChartEasingOption) + { + _animator.animate(yAxisDuration: yAxisDuration, easingOption: easingOption) + } + + /// Animates the drawing / rendering of the chart the y-axis with the specified animation time. + /// If `animate(...)` is called, no further calling of `invalidate()` is necessary to refresh the chart. + /// + /// - Parameters: + /// - yAxisDuration: duration for animating the y axis + @objc open func animate(yAxisDuration: TimeInterval) + { + _animator.animate(yAxisDuration: yAxisDuration) + } + + // MARK: - Accessors + + /// The current y-max value across all DataSets + open var chartYMax: Double + { + return _data?.yMax ?? 0.0 + } + + /// The current y-min value across all DataSets + open var chartYMin: Double + { + return _data?.yMin ?? 0.0 + } + + open var chartXMax: Double + { + return _xAxis._axisMaximum + } + + open var chartXMin: Double + { + return _xAxis._axisMinimum + } + + open var xRange: Double + { + return _xAxis.axisRange + } + + /// - Note: (Equivalent of getCenter() in MPAndroidChart, as center is already a standard in iOS that returns the center point relative to superview, and MPAndroidChart returns relative to self)* + /// The center point of the chart (the whole View) in pixels. + @objc open var midPoint: CGPoint + { + let bounds = self.bounds + return CGPoint(x: bounds.origin.x + bounds.size.width / 2.0, y: bounds.origin.y + bounds.size.height / 2.0) + } + + /// The center of the chart taking offsets under consideration. (returns the center of the content rectangle) + open var centerOffsets: CGPoint + { + return _viewPortHandler.contentCenter + } + + /// The Legend object of the chart. This method can be used to get an instance of the legend in order to customize the automatically generated Legend. + @objc open var legend: Legend + { + return _legend + } + + /// The renderer object responsible for rendering / drawing the Legend. + @objc open var legendRenderer: LegendRenderer! + { + return _legendRenderer + } + + /// The rectangle that defines the borders of the chart-value surface (into which the actual values are drawn). + @objc open var contentRect: CGRect + { + return _viewPortHandler.contentRect + } + + /// - Returns: The ViewPortHandler of the chart that is responsible for the + /// content area of the chart and its offsets and dimensions. + @objc open var viewPortHandler: ViewPortHandler! + { + return _viewPortHandler + } + + /// - Returns: The bitmap that represents the chart. + @objc open func getChartImage(transparent: Bool) -> NSUIImage? + { + NSUIGraphicsBeginImageContextWithOptions(bounds.size, isOpaque || !transparent, NSUIMainScreen()?.nsuiScale ?? 1.0) + + guard let context = NSUIGraphicsGetCurrentContext() + else { return nil } + + let rect = CGRect(origin: CGPoint(x: 0, y: 0), size: bounds.size) + + if isOpaque || !transparent + { + // Background color may be partially transparent, we must fill with white if we want to output an opaque image + context.setFillColor(NSUIColor.white.cgColor) + context.fill(rect) + + if let backgroundColor = self.backgroundColor + { + context.setFillColor(backgroundColor.cgColor) + context.fill(rect) + } + } + + nsuiLayer?.render(in: context) + + let image = NSUIGraphicsGetImageFromCurrentImageContext() + + NSUIGraphicsEndImageContext() + + return image + } + + public enum ImageFormat + { + case jpeg + case png + } + + /// Saves the current chart state with the given name to the given path on + /// the sdcard leaving the path empty "" will put the saved file directly on + /// the SD card chart is saved as a PNG image, example: + /// saveToPath("myfilename", "foldername1/foldername2") + /// + /// - Parameters: + /// - to: path to the image to save + /// - format: the format to save + /// - compressionQuality: compression quality for lossless formats (JPEG) + /// - Returns: `true` if the image was saved successfully + open func save(to path: String, format: ImageFormat, compressionQuality: Double) -> Bool + { + guard let image = getChartImage(transparent: format != .jpeg) else { return false } + + let imageData: Data? + switch (format) + { + case .png: imageData = NSUIImagePNGRepresentation(image) + case .jpeg: imageData = NSUIImageJPEGRepresentation(image, CGFloat(compressionQuality)) + } + + guard let data = imageData else { return false } + + do + { + try data.write(to: URL(fileURLWithPath: path), options: .atomic) + } + catch + { + return false + } + + return true + } + + internal var _viewportJobs = [ViewPortJob]() + + open override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) + { + if keyPath == "bounds" || keyPath == "frame" + { + let bounds = self.bounds + + if (_viewPortHandler !== nil && + (bounds.size.width != _viewPortHandler.chartWidth || + bounds.size.height != _viewPortHandler.chartHeight)) + { + _viewPortHandler.setChartDimens(width: bounds.size.width, height: bounds.size.height) + + // This may cause the chart view to mutate properties affecting the view port -- lets do this + // before we try to run any pending jobs on the view port itself + notifyDataSetChanged() + + // Finish any pending viewport changes + while (!_viewportJobs.isEmpty) + { + let job = _viewportJobs.remove(at: 0) + job.doJob() + } + } + } + } + + @objc open func removeViewportJob(_ job: ViewPortJob) + { + if let index = _viewportJobs.firstIndex(where: { $0 === job }) + { + _viewportJobs.remove(at: index) + } + } + + @objc open func clearAllViewportJobs() + { + _viewportJobs.removeAll(keepingCapacity: false) + } + + @objc open func addViewportJob(_ job: ViewPortJob) + { + if _viewPortHandler.hasChartDimens + { + job.doJob() + } + else + { + _viewportJobs.append(job) + } + } + + /// **default**: true + /// `true` if chart continues to scroll after touch up, `false` ifnot. + @objc open var isDragDecelerationEnabled: Bool + { + return dragDecelerationEnabled + } + + /// Deceleration friction coefficient in [0 ; 1] interval, higher values indicate that speed will decrease slowly, for example if it set to 0, it will stop immediately. + /// 1 is an invalid value, and will be converted to 0.999 automatically. + /// + /// **default**: true + @objc open var dragDecelerationFrictionCoef: CGFloat + { + get + { + return _dragDecelerationFrictionCoef + } + set + { + var val = newValue + if val < 0.0 + { + val = 0.0 + } + if val >= 1.0 + { + val = 0.999 + } + + _dragDecelerationFrictionCoef = val + } + } + + /// The maximum distance in screen pixels away from an entry causing it to highlight. + /// **default**: 500.0 + open var maxHighlightDistance: CGFloat = 500.0 + + /// the number of maximum visible drawn values on the chart only active when `drawValuesEnabled` is enabled + open var maxVisibleCount: Int + { + return Int(INT_MAX) + } + + // MARK: - AnimatorDelegate + + open func animatorUpdated(_ chartAnimator: Animator) + { + setNeedsDisplay() + } + + open func animatorStopped(_ chartAnimator: Animator) + { + delegate?.chartView?(self, animatorDidStop: chartAnimator) + } + + // MARK: - Touches + + open override func nsuiTouchesBegan(_ touches: Set, withEvent event: NSUIEvent?) + { + if !_interceptTouchEvents + { + super.nsuiTouchesBegan(touches, withEvent: event) + } + } + + open override func nsuiTouchesMoved(_ touches: Set, withEvent event: NSUIEvent?) + { + if !_interceptTouchEvents + { + super.nsuiTouchesMoved(touches, withEvent: event) + } + } + + open override func nsuiTouchesEnded(_ touches: Set, withEvent event: NSUIEvent?) + { + if !_interceptTouchEvents + { + super.nsuiTouchesEnded(touches, withEvent: event) + } + } + + open override func nsuiTouchesCancelled(_ touches: Set?, withEvent event: NSUIEvent?) + { + if !_interceptTouchEvents + { + super.nsuiTouchesCancelled(touches, withEvent: event) + } + } +} diff --git a/Pods/Charts/Source/Charts/Charts/CombinedChartView.swift b/Pods/Charts/Source/Charts/Charts/CombinedChartView.swift new file mode 100644 index 00000000..47eebd6c --- /dev/null +++ b/Pods/Charts/Source/Charts/Charts/CombinedChartView.swift @@ -0,0 +1,246 @@ +// +// CombinedChartView.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + +/// This chart class allows the combination of lines, bars, scatter and candle data all displayed in one chart area. +open class CombinedChartView: BarLineChartViewBase, CombinedChartDataProvider +{ + /// the fill-formatter used for determining the position of the fill-line + internal var _fillFormatter: IFillFormatter! + + /// enum that allows to specify the order in which the different data objects for the combined-chart are drawn + @objc(CombinedChartDrawOrder) + public enum DrawOrder: Int + { + case bar + case bubble + case line + case candle + case scatter + } + + open override func initialize() + { + super.initialize() + + self.highlighter = CombinedHighlighter(chart: self, barDataProvider: self) + + // Old default behaviour + self.highlightFullBarEnabled = true + + _fillFormatter = DefaultFillFormatter() + + renderer = CombinedChartRenderer(chart: self, animator: _animator, viewPortHandler: _viewPortHandler) + } + + open override var data: ChartData? + { + get + { + return super.data + } + set + { + super.data = newValue + + self.highlighter = CombinedHighlighter(chart: self, barDataProvider: self) + + (renderer as? CombinedChartRenderer)?.createRenderers() + renderer?.initBuffers() + } + } + + @objc open var fillFormatter: IFillFormatter + { + get + { + return _fillFormatter + } + set + { + _fillFormatter = newValue + if _fillFormatter == nil + { + _fillFormatter = DefaultFillFormatter() + } + } + } + + /// - Returns: The Highlight object (contains x-index and DataSet index) of the selected value at the given touch point inside the CombinedChart. + open override func getHighlightByTouchPoint(_ pt: CGPoint) -> Highlight? + { + if _data === nil + { + Swift.print("Can't select by touch. No data set.") + return nil + } + + guard let h = self.highlighter?.getHighlight(x: pt.x, y: pt.y) + else { return nil } + + if !isHighlightFullBarEnabled { return h } + + // For isHighlightFullBarEnabled, remove stackIndex + return Highlight( + x: h.x, y: h.y, + xPx: h.xPx, yPx: h.yPx, + dataIndex: h.dataIndex, + dataSetIndex: h.dataSetIndex, + stackIndex: -1, + axis: h.axis) + } + + // MARK: - CombinedChartDataProvider + + open var combinedData: CombinedChartData? + { + get + { + return _data as? CombinedChartData + } + } + + // MARK: - LineChartDataProvider + + open var lineData: LineChartData? + { + get + { + return combinedData?.lineData + } + } + + // MARK: - BarChartDataProvider + + open var barData: BarChartData? + { + get + { + return combinedData?.barData + } + } + + // MARK: - ScatterChartDataProvider + + open var scatterData: ScatterChartData? + { + get + { + return combinedData?.scatterData + } + } + + // MARK: - CandleChartDataProvider + + open var candleData: CandleChartData? + { + get + { + return combinedData?.candleData + } + } + + // MARK: - BubbleChartDataProvider + + open var bubbleData: BubbleChartData? + { + get + { + return combinedData?.bubbleData + } + } + + // MARK: - Accessors + + /// if set to true, all values are drawn above their bars, instead of below their top + @objc open var drawValueAboveBarEnabled: Bool + { + get { return (renderer as! CombinedChartRenderer).drawValueAboveBarEnabled } + set { (renderer as! CombinedChartRenderer).drawValueAboveBarEnabled = newValue } + } + + /// if set to true, a grey area is drawn behind each bar that indicates the maximum value + @objc open var drawBarShadowEnabled: Bool + { + get { return (renderer as! CombinedChartRenderer).drawBarShadowEnabled } + set { (renderer as! CombinedChartRenderer).drawBarShadowEnabled = newValue } + } + + /// `true` if drawing values above bars is enabled, `false` ifnot + open var isDrawValueAboveBarEnabled: Bool { return (renderer as! CombinedChartRenderer).drawValueAboveBarEnabled } + + /// `true` if drawing shadows (maxvalue) for each bar is enabled, `false` ifnot + open var isDrawBarShadowEnabled: Bool { return (renderer as! CombinedChartRenderer).drawBarShadowEnabled } + + /// the order in which the provided data objects should be drawn. + /// The earlier you place them in the provided array, the further they will be in the background. + /// e.g. if you provide [DrawOrder.Bar, DrawOrder.Line], the bars will be drawn behind the lines. + @objc open var drawOrder: [Int] + { + get + { + return (renderer as! CombinedChartRenderer).drawOrder.map { $0.rawValue } + } + set + { + (renderer as! CombinedChartRenderer).drawOrder = newValue.map { DrawOrder(rawValue: $0)! } + } + } + + /// Set this to `true` to make the highlight operation full-bar oriented, `false` to make it highlight single values + @objc open var highlightFullBarEnabled: Bool = false + + /// `true` the highlight is be full-bar oriented, `false` ifsingle-value + open var isHighlightFullBarEnabled: Bool { return highlightFullBarEnabled } + + // MARK: - ChartViewBase + + /// draws all MarkerViews on the highlighted positions + override func drawMarkers(context: CGContext) + { + guard + let marker = marker, + isDrawMarkersEnabled && valuesToHighlight() + else { return } + + for i in 0 ..< _indicesToHighlight.count + { + let highlight = _indicesToHighlight[i] + + guard + let set = combinedData?.getDataSetByHighlight(highlight), + let e = _data?.entryForHighlight(highlight) + else { continue } + + let entryIndex = set.entryIndex(entry: e) + if entryIndex > Int(Double(set.entryCount) * _animator.phaseX) + { + continue + } + + let pos = getMarkerPosition(highlight: highlight) + + // check bounds + if !_viewPortHandler.isInBounds(x: pos.x, y: pos.y) + { + continue + } + + // callbacks to update the content + marker.refreshContent(entry: e, highlight: highlight) + + // draw the marker + marker.draw(context: context, point: pos) + } + } +} diff --git a/Pods/Charts/Source/Charts/Charts/HorizontalBarChartView.swift b/Pods/Charts/Source/Charts/Charts/HorizontalBarChartView.swift new file mode 100644 index 00000000..7b6163c8 --- /dev/null +++ b/Pods/Charts/Source/Charts/Charts/HorizontalBarChartView.swift @@ -0,0 +1,270 @@ +// +// HorizontalBarChartView.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + +/// BarChart with horizontal bar orientation. In this implementation, x- and y-axis are switched. +open class HorizontalBarChartView: BarChartView +{ + internal override func initialize() + { + super.initialize() + + _leftAxisTransformer = TransformerHorizontalBarChart(viewPortHandler: _viewPortHandler) + _rightAxisTransformer = TransformerHorizontalBarChart(viewPortHandler: _viewPortHandler) + + renderer = HorizontalBarChartRenderer(dataProvider: self, animator: _animator, viewPortHandler: _viewPortHandler) + leftYAxisRenderer = YAxisRendererHorizontalBarChart(viewPortHandler: _viewPortHandler, yAxis: leftAxis, transformer: _leftAxisTransformer) + rightYAxisRenderer = YAxisRendererHorizontalBarChart(viewPortHandler: _viewPortHandler, yAxis: rightAxis, transformer: _rightAxisTransformer) + xAxisRenderer = XAxisRendererHorizontalBarChart(viewPortHandler: _viewPortHandler, xAxis: _xAxis, transformer: _leftAxisTransformer, chart: self) + + self.highlighter = HorizontalBarHighlighter(chart: self) + } + + internal override func calculateLegendOffsets(offsetLeft: inout CGFloat, offsetTop: inout CGFloat, offsetRight: inout CGFloat, offsetBottom: inout CGFloat) + { + guard + let legend = _legend, + legend.isEnabled, + !legend.drawInside + else { return } + + // setup offsets for legend + switch legend.orientation + { + case .vertical: + switch legend.horizontalAlignment + { + case .left: + offsetLeft += min(legend.neededWidth, _viewPortHandler.chartWidth * legend.maxSizePercent) + legend.xOffset + + case .right: + offsetRight += min(legend.neededWidth, _viewPortHandler.chartWidth * legend.maxSizePercent) + legend.xOffset + + case .center: + + switch legend.verticalAlignment + { + case .top: + offsetTop += min(legend.neededHeight, _viewPortHandler.chartHeight * legend.maxSizePercent) + legend.yOffset + + case .bottom: + offsetBottom += min(legend.neededHeight, _viewPortHandler.chartHeight * legend.maxSizePercent) + legend.yOffset + + default: + break + } + } + + case .horizontal: + switch legend.verticalAlignment + { + case .top: + offsetTop += min(legend.neededHeight, _viewPortHandler.chartHeight * legend.maxSizePercent) + legend.yOffset + + // left axis equals the top x-axis in a horizontal chart + if leftAxis.isEnabled && leftAxis.isDrawLabelsEnabled + { + offsetTop += leftAxis.getRequiredHeightSpace() + } + + case .bottom: + offsetBottom += min(legend.neededHeight, _viewPortHandler.chartHeight * legend.maxSizePercent) + legend.yOffset + + // right axis equals the bottom x-axis in a horizontal chart + if rightAxis.isEnabled && rightAxis.isDrawLabelsEnabled + { + offsetBottom += rightAxis.getRequiredHeightSpace() + } + default: + break + } + } + } + + internal override func calculateOffsets() + { + var offsetLeft: CGFloat = 0.0, + offsetRight: CGFloat = 0.0, + offsetTop: CGFloat = 0.0, + offsetBottom: CGFloat = 0.0 + + calculateLegendOffsets(offsetLeft: &offsetLeft, + offsetTop: &offsetTop, + offsetRight: &offsetRight, + offsetBottom: &offsetBottom) + + // offsets for y-labels + if leftAxis.needsOffset + { + offsetTop += leftAxis.getRequiredHeightSpace() + } + + if rightAxis.needsOffset + { + offsetBottom += rightAxis.getRequiredHeightSpace() + } + + let xlabelwidth = _xAxis.labelRotatedWidth + + if _xAxis.isEnabled + { + // offsets for x-labels + if _xAxis.labelPosition == .bottom + { + offsetLeft += xlabelwidth + } + else if _xAxis.labelPosition == .top + { + offsetRight += xlabelwidth + } + else if _xAxis.labelPosition == .bothSided + { + offsetLeft += xlabelwidth + offsetRight += xlabelwidth + } + } + + offsetTop += self.extraTopOffset + offsetRight += self.extraRightOffset + offsetBottom += self.extraBottomOffset + offsetLeft += self.extraLeftOffset + + _viewPortHandler.restrainViewPort( + offsetLeft: max(self.minOffset, offsetLeft), + offsetTop: max(self.minOffset, offsetTop), + offsetRight: max(self.minOffset, offsetRight), + offsetBottom: max(self.minOffset, offsetBottom)) + + prepareOffsetMatrix() + prepareValuePxMatrix() + } + + internal override func prepareValuePxMatrix() + { + _rightAxisTransformer.prepareMatrixValuePx(chartXMin: rightAxis._axisMinimum, deltaX: CGFloat(rightAxis.axisRange), deltaY: CGFloat(_xAxis.axisRange), chartYMin: _xAxis._axisMinimum) + _leftAxisTransformer.prepareMatrixValuePx(chartXMin: leftAxis._axisMinimum, deltaX: CGFloat(leftAxis.axisRange), deltaY: CGFloat(_xAxis.axisRange), chartYMin: _xAxis._axisMinimum) + } + + open override func getMarkerPosition(highlight: Highlight) -> CGPoint + { + return CGPoint(x: highlight.drawY, y: highlight.drawX) + } + + open override func getBarBounds(entry e: BarChartDataEntry) -> CGRect + { + guard + let data = _data as? BarChartData, + let set = data.getDataSetForEntry(e) as? IBarChartDataSet + else { return CGRect.null } + + let y = e.y + let x = e.x + + let barWidth = data.barWidth + + let top = x - 0.5 + barWidth / 2.0 + let bottom = x + 0.5 - barWidth / 2.0 + let left = y >= 0.0 ? y : 0.0 + let right = y <= 0.0 ? y : 0.0 + + var bounds = CGRect(x: left, y: top, width: right - left, height: bottom - top) + + getTransformer(forAxis: set.axisDependency).rectValueToPixel(&bounds) + + return bounds + } + + open override func getPosition(entry e: ChartDataEntry, axis: YAxis.AxisDependency) -> CGPoint + { + var vals = CGPoint(x: CGFloat(e.y), y: CGFloat(e.x)) + + getTransformer(forAxis: axis).pointValueToPixel(&vals) + + return vals + } + + open override func getHighlightByTouchPoint(_ pt: CGPoint) -> Highlight? + { + if _data === nil + { + Swift.print("Can't select by touch. No data set.", terminator: "\n") + return nil + } + + return self.highlighter?.getHighlight(x: pt.y, y: pt.x) + } + + /// The lowest x-index (value on the x-axis) that is still visible on he chart. + open override var lowestVisibleX: Double + { + var pt = CGPoint( + x: viewPortHandler.contentLeft, + y: viewPortHandler.contentBottom) + + getTransformer(forAxis: .left).pixelToValues(&pt) + + return max(xAxis._axisMinimum, Double(pt.y)) + } + + /// The highest x-index (value on the x-axis) that is still visible on the chart. + open override var highestVisibleX: Double + { + var pt = CGPoint( + x: viewPortHandler.contentLeft, + y: viewPortHandler.contentTop) + + getTransformer(forAxis: .left).pixelToValues(&pt) + + return min(xAxis._axisMaximum, Double(pt.y)) + } + + // MARK: - Viewport + + open override func setVisibleXRangeMaximum(_ maxXRange: Double) + { + let xScale = xAxis.axisRange / maxXRange + viewPortHandler.setMinimumScaleY(CGFloat(xScale)) + } + + open override func setVisibleXRangeMinimum(_ minXRange: Double) + { + let xScale = xAxis.axisRange / minXRange + viewPortHandler.setMaximumScaleY(CGFloat(xScale)) + } + + open override func setVisibleXRange(minXRange: Double, maxXRange: Double) + { + let minScale = xAxis.axisRange / minXRange + let maxScale = xAxis.axisRange / maxXRange + viewPortHandler.setMinMaxScaleY(minScaleY: CGFloat(minScale), maxScaleY: CGFloat(maxScale)) + } + + open override func setVisibleYRangeMaximum(_ maxYRange: Double, axis: YAxis.AxisDependency) + { + let yScale = getAxisRange(axis: axis) / maxYRange + viewPortHandler.setMinimumScaleX(CGFloat(yScale)) + } + + open override func setVisibleYRangeMinimum(_ minYRange: Double, axis: YAxis.AxisDependency) + { + let yScale = getAxisRange(axis: axis) / minYRange + viewPortHandler.setMaximumScaleX(CGFloat(yScale)) + } + + open override func setVisibleYRange(minYRange: Double, maxYRange: Double, axis: YAxis.AxisDependency) + { + let minScale = getAxisRange(axis: axis) / minYRange + let maxScale = getAxisRange(axis: axis) / maxYRange + viewPortHandler.setMinMaxScaleX(minScaleX: CGFloat(minScale), maxScaleX: CGFloat(maxScale)) + } +} diff --git a/Pods/Charts/Source/Charts/Charts/LineChartView.swift b/Pods/Charts/Source/Charts/Charts/LineChartView.swift new file mode 100644 index 00000000..c5fbecfa --- /dev/null +++ b/Pods/Charts/Source/Charts/Charts/LineChartView.swift @@ -0,0 +1,28 @@ +// +// LineChartView.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + +/// Chart that draws lines, surfaces, circles, ... +open class LineChartView: BarLineChartViewBase, LineChartDataProvider +{ + internal override func initialize() + { + super.initialize() + + renderer = LineChartRenderer(dataProvider: self, animator: _animator, viewPortHandler: _viewPortHandler) + } + + // MARK: - LineChartDataProvider + + open var lineData: LineChartData? { return _data as? LineChartData } +} diff --git a/Pods/Charts/Source/Charts/Charts/PieChartView.swift b/Pods/Charts/Source/Charts/Charts/PieChartView.swift new file mode 100644 index 00000000..1010434f --- /dev/null +++ b/Pods/Charts/Source/Charts/Charts/PieChartView.swift @@ -0,0 +1,599 @@ +// +// PieChartView.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + +/// View that represents a pie chart. Draws cake like slices. +open class PieChartView: PieRadarChartViewBase +{ + /// rect object that represents the bounds of the piechart, needed for drawing the circle + private var _circleBox = CGRect() + + /// flag indicating if entry labels should be drawn or not + private var _drawEntryLabelsEnabled = true + + /// array that holds the width of each pie-slice in degrees + private var _drawAngles = [CGFloat]() + + /// array that holds the absolute angle in degrees of each slice + private var _absoluteAngles = [CGFloat]() + + /// if true, the hole inside the chart will be drawn + private var _drawHoleEnabled = true + + private var _holeColor: NSUIColor? = NSUIColor.white + + /// Sets the color the entry labels are drawn with. + private var _entryLabelColor: NSUIColor? = NSUIColor.white + + /// Sets the font the entry labels are drawn with. + private var _entryLabelFont: NSUIFont? = NSUIFont(name: "HelveticaNeue", size: 13.0) + + /// if true, the hole will see-through to the inner tips of the slices + private var _drawSlicesUnderHoleEnabled = false + + /// if true, the values inside the piechart are drawn as percent values + private var _usePercentValuesEnabled = false + + /// variable for the text that is drawn in the center of the pie-chart + private var _centerAttributedText: NSAttributedString? + + /// the offset on the x- and y-axis the center text has in dp. + private var _centerTextOffset: CGPoint = CGPoint() + + /// indicates the size of the hole in the center of the piechart + /// + /// **default**: `0.5` + private var _holeRadiusPercent = CGFloat(0.5) + + private var _transparentCircleColor: NSUIColor? = NSUIColor(white: 1.0, alpha: 105.0/255.0) + + /// the radius of the transparent circle next to the chart-hole in the center + private var _transparentCircleRadiusPercent = CGFloat(0.55) + + /// if enabled, centertext is drawn + private var _drawCenterTextEnabled = true + + private var _centerTextRadiusPercent: CGFloat = 1.0 + + /// maximum angle for this pie + private var _maxAngle: CGFloat = 360.0 + + public override init(frame: CGRect) + { + super.init(frame: frame) + } + + public required init?(coder aDecoder: NSCoder) + { + super.init(coder: aDecoder) + } + + internal override func initialize() + { + super.initialize() + + renderer = PieChartRenderer(chart: self, animator: _animator, viewPortHandler: _viewPortHandler) + _xAxis = nil + + self.highlighter = PieHighlighter(chart: self) + } + + open override func draw(_ rect: CGRect) + { + super.draw(rect) + + if _data === nil + { + return + } + + let optionalContext = NSUIGraphicsGetCurrentContext() + guard let context = optionalContext, let renderer = renderer else + { + return + } + + renderer.drawData(context: context) + + if (valuesToHighlight()) + { + renderer.drawHighlighted(context: context, indices: _indicesToHighlight) + } + + renderer.drawExtras(context: context) + + renderer.drawValues(context: context) + + legendRenderer.renderLegend(context: context) + + drawDescription(context: context) + + drawMarkers(context: context) + } + + internal override func calculateOffsets() + { + super.calculateOffsets() + + // prevent nullpointer when no data set + if _data === nil + { + return + } + + let radius = diameter / 2.0 + + let c = self.centerOffsets + + let shift = (data as? PieChartData)?.dataSet?.selectionShift ?? 0.0 + + // create the circle box that will contain the pie-chart (the bounds of the pie-chart) + _circleBox.origin.x = (c.x - radius) + shift + _circleBox.origin.y = (c.y - radius) + shift + _circleBox.size.width = diameter - shift * 2.0 + _circleBox.size.height = diameter - shift * 2.0 + } + + internal override func calcMinMax() + { + calcAngles() + } + + open override func getMarkerPosition(highlight: Highlight) -> CGPoint + { + let center = self.centerCircleBox + var r = self.radius + + var off = r / 10.0 * 3.6 + + if self.isDrawHoleEnabled + { + off = (r - (r * self.holeRadiusPercent)) / 2.0 + } + + r -= off // offset to keep things inside the chart + + let rotationAngle = self.rotationAngle + + let entryIndex = Int(highlight.x) + + // offset needed to center the drawn text in the slice + let offset = drawAngles[entryIndex] / 2.0 + + // calculate the text position + let x: CGFloat = (r * cos(((rotationAngle + absoluteAngles[entryIndex] - offset) * CGFloat(_animator.phaseY)).DEG2RAD) + center.x) + let y: CGFloat = (r * sin(((rotationAngle + absoluteAngles[entryIndex] - offset) * CGFloat(_animator.phaseY)).DEG2RAD) + center.y) + + return CGPoint(x: x, y: y) + } + + /// calculates the needed angles for the chart slices + private func calcAngles() + { + _drawAngles = [CGFloat]() + _absoluteAngles = [CGFloat]() + + guard let data = _data else { return } + + let entryCount = data.entryCount + + _drawAngles.reserveCapacity(entryCount) + _absoluteAngles.reserveCapacity(entryCount) + + let yValueSum = (_data as! PieChartData).yValueSum + + var cnt = 0 + + for set in data.dataSets + { + for j in 0 ..< set.entryCount + { + guard let e = set.entryForIndex(j) else { continue } + + _drawAngles.append(calcAngle(value: abs(e.y), yValueSum: yValueSum)) + + if cnt == 0 + { + _absoluteAngles.append(_drawAngles[cnt]) + } + else + { + _absoluteAngles.append(_absoluteAngles[cnt - 1] + _drawAngles[cnt]) + } + + cnt += 1 + } + } + } + + /// Checks if the given index is set to be highlighted. + @objc open func needsHighlight(index: Int) -> Bool + { + return _indicesToHighlight.contains { Int($0.x) == index } + } + + /// calculates the needed angle for a given value + private func calcAngle(_ value: Double) -> CGFloat + { + return calcAngle(value: value, yValueSum: (_data as! PieChartData).yValueSum) + } + + /// calculates the needed angle for a given value + private func calcAngle(value: Double, yValueSum: Double) -> CGFloat + { + return CGFloat(value) / CGFloat(yValueSum) * _maxAngle + } + + /// This will throw an exception, PieChart has no XAxis object. + open override var xAxis: XAxis + { + fatalError("PieChart has no XAxis") + } + + open override func indexForAngle(_ angle: CGFloat) -> Int + { + // TODO: Return nil instead of -1 + // take the current angle of the chart into consideration + let a = (angle - self.rotationAngle).normalizedAngle + return _absoluteAngles.firstIndex { $0 > a } ?? -1 + } + + /// - Returns: The index of the DataSet this x-index belongs to. + @objc open func dataSetIndexForIndex(_ xValue: Double) -> Int + { + // TODO: Return nil instead of -1 + return _data?.dataSets.firstIndex { + $0.entryForXValue(xValue, closestToY: .nan) != nil + } ?? -1 + } + + /// - Returns: An integer array of all the different angles the chart slices + /// have the angles in the returned array determine how much space (of 360°) + /// each slice takes + @objc open var drawAngles: [CGFloat] + { + return _drawAngles + } + + /// - Returns: The absolute angles of the different chart slices (where the + /// slices end) + @objc open var absoluteAngles: [CGFloat] + { + return _absoluteAngles + } + + /// The color for the hole that is drawn in the center of the PieChart (if enabled). + /// + /// - Note: Use holeTransparent with holeColor = nil to make the hole transparent.* + @objc open var holeColor: NSUIColor? + { + get + { + return _holeColor + } + set + { + _holeColor = newValue + setNeedsDisplay() + } + } + + /// if true, the hole will see-through to the inner tips of the slices + /// + /// **default**: `false` + @objc open var drawSlicesUnderHoleEnabled: Bool + { + get + { + return _drawSlicesUnderHoleEnabled + } + set + { + _drawSlicesUnderHoleEnabled = newValue + setNeedsDisplay() + } + } + + /// `true` if the inner tips of the slices are visible behind the hole, `false` if not. + @objc open var isDrawSlicesUnderHoleEnabled: Bool + { + return drawSlicesUnderHoleEnabled + } + + /// `true` if the hole in the center of the pie-chart is set to be visible, `false` ifnot + @objc open var drawHoleEnabled: Bool + { + get + { + return _drawHoleEnabled + } + set + { + _drawHoleEnabled = newValue + setNeedsDisplay() + } + } + + /// `true` if the hole in the center of the pie-chart is set to be visible, `false` ifnot + @objc open var isDrawHoleEnabled: Bool + { + get + { + return drawHoleEnabled + } + } + + /// the text that is displayed in the center of the pie-chart + @objc open var centerText: String? + { + get + { + return self.centerAttributedText?.string + } + set + { + var attrString: NSMutableAttributedString? + if newValue == nil + { + attrString = nil + } + else + { + let paragraphStyle = NSParagraphStyle.default.mutableCopy() as! NSMutableParagraphStyle + paragraphStyle.lineBreakMode = .byTruncatingTail + paragraphStyle.alignment = .center + + attrString = NSMutableAttributedString(string: newValue!) + attrString?.setAttributes([ + .foregroundColor: NSUIColor.black, + .font: NSUIFont.systemFont(ofSize: 12.0), + .paragraphStyle: paragraphStyle + ], range: NSMakeRange(0, attrString!.length)) + } + self.centerAttributedText = attrString + } + } + + /// the text that is displayed in the center of the pie-chart + @objc open var centerAttributedText: NSAttributedString? + { + get + { + return _centerAttributedText + } + set + { + _centerAttributedText = newValue + setNeedsDisplay() + } + } + + /// Sets the offset the center text should have from it's original position in dp. Default x = 0, y = 0 + @objc open var centerTextOffset: CGPoint + { + get + { + return _centerTextOffset + } + set + { + _centerTextOffset = newValue + setNeedsDisplay() + } + } + + /// `true` if drawing the center text is enabled + @objc open var drawCenterTextEnabled: Bool + { + get + { + return _drawCenterTextEnabled + } + set + { + _drawCenterTextEnabled = newValue + setNeedsDisplay() + } + } + + /// `true` if drawing the center text is enabled + @objc open var isDrawCenterTextEnabled: Bool + { + get + { + return drawCenterTextEnabled + } + } + + internal override var requiredLegendOffset: CGFloat + { + return _legend.font.pointSize * 2.0 + } + + internal override var requiredBaseOffset: CGFloat + { + return 0.0 + } + + open override var radius: CGFloat + { + return _circleBox.width / 2.0 + } + + /// The circlebox, the boundingbox of the pie-chart slices + @objc open var circleBox: CGRect + { + return _circleBox + } + + /// The center of the circlebox + @objc open var centerCircleBox: CGPoint + { + return CGPoint(x: _circleBox.midX, y: _circleBox.midY) + } + + /// the radius of the hole in the center of the piechart in percent of the maximum radius (max = the radius of the whole chart) + /// + /// **default**: 0.5 (50%) (half the pie) + @objc open var holeRadiusPercent: CGFloat + { + get + { + return _holeRadiusPercent + } + set + { + _holeRadiusPercent = newValue + setNeedsDisplay() + } + } + + /// The color that the transparent-circle should have. + /// + /// **default**: `nil` + @objc open var transparentCircleColor: NSUIColor? + { + get + { + return _transparentCircleColor + } + set + { + _transparentCircleColor = newValue + setNeedsDisplay() + } + } + + /// the radius of the transparent circle that is drawn next to the hole in the piechart in percent of the maximum radius (max = the radius of the whole chart) + /// + /// **default**: 0.55 (55%) -> means 5% larger than the center-hole by default + @objc open var transparentCircleRadiusPercent: CGFloat + { + get + { + return _transparentCircleRadiusPercent + } + set + { + _transparentCircleRadiusPercent = newValue + setNeedsDisplay() + } + } + + /// The color the entry labels are drawn with. + @objc open var entryLabelColor: NSUIColor? + { + get { return _entryLabelColor } + set + { + _entryLabelColor = newValue + setNeedsDisplay() + } + } + + /// The font the entry labels are drawn with. + @objc open var entryLabelFont: NSUIFont? + { + get { return _entryLabelFont } + set + { + _entryLabelFont = newValue + setNeedsDisplay() + } + } + + /// Set this to true to draw the enrty labels into the pie slices + @objc open var drawEntryLabelsEnabled: Bool + { + get + { + return _drawEntryLabelsEnabled + } + set + { + _drawEntryLabelsEnabled = newValue + setNeedsDisplay() + } + } + + /// `true` if drawing entry labels is enabled, `false` ifnot + @objc open var isDrawEntryLabelsEnabled: Bool + { + get + { + return drawEntryLabelsEnabled + } + } + + /// If this is enabled, values inside the PieChart are drawn in percent and not with their original value. Values provided for the ValueFormatter to format are then provided in percent. + @objc open var usePercentValuesEnabled: Bool + { + get + { + return _usePercentValuesEnabled + } + set + { + _usePercentValuesEnabled = newValue + setNeedsDisplay() + } + } + + /// `true` if drawing x-values is enabled, `false` ifnot + @objc open var isUsePercentValuesEnabled: Bool + { + get + { + return usePercentValuesEnabled + } + } + + /// the rectangular radius of the bounding box for the center text, as a percentage of the pie hole + @objc open var centerTextRadiusPercent: CGFloat + { + get + { + return _centerTextRadiusPercent + } + set + { + _centerTextRadiusPercent = newValue + setNeedsDisplay() + } + } + + /// The max angle that is used for calculating the pie-circle. + /// 360 means it's a full pie-chart, 180 results in a half-pie-chart. + /// **default**: 360.0 + @objc open var maxAngle: CGFloat + { + get + { + return _maxAngle + } + set + { + _maxAngle = newValue + + if _maxAngle > 360.0 + { + _maxAngle = 360.0 + } + + if _maxAngle < 90.0 + { + _maxAngle = 90.0 + } + } + } +} diff --git a/Pods/Charts/Source/Charts/Charts/PieRadarChartViewBase.swift b/Pods/Charts/Source/Charts/Charts/PieRadarChartViewBase.swift new file mode 100644 index 00000000..bbdc8d82 --- /dev/null +++ b/Pods/Charts/Source/Charts/Charts/PieRadarChartViewBase.swift @@ -0,0 +1,837 @@ +// +// PieRadarChartViewBase.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + +/// Base class of PieChartView and RadarChartView. +open class PieRadarChartViewBase: ChartViewBase +{ + /// holds the normalized version of the current rotation angle of the chart + private var _rotationAngle = CGFloat(270.0) + + /// holds the raw version of the current rotation angle of the chart + private var _rawRotationAngle = CGFloat(270.0) + + /// flag that indicates if rotation is enabled or not + @objc open var rotationEnabled = true + + /// Sets the minimum offset (padding) around the chart, defaults to 0.0 + @objc open var minOffset = CGFloat(0.0) + + /// iOS && OSX only: Enabled multi-touch rotation using two fingers. + private var _rotationWithTwoFingers = false + + private var _tapGestureRecognizer: NSUITapGestureRecognizer! + #if !os(tvOS) + private var _rotationGestureRecognizer: NSUIRotationGestureRecognizer! + #endif + + public override init(frame: CGRect) + { + super.init(frame: frame) + } + + public required init?(coder aDecoder: NSCoder) + { + super.init(coder: aDecoder) + } + + deinit + { + stopDeceleration() + } + + internal override func initialize() + { + super.initialize() + + _tapGestureRecognizer = NSUITapGestureRecognizer(target: self, action: #selector(tapGestureRecognized(_:))) + + self.addGestureRecognizer(_tapGestureRecognizer) + + #if !os(tvOS) + _rotationGestureRecognizer = NSUIRotationGestureRecognizer(target: self, action: #selector(rotationGestureRecognized(_:))) + self.addGestureRecognizer(_rotationGestureRecognizer) + _rotationGestureRecognizer.isEnabled = rotationWithTwoFingers + #endif + } + + internal override func calcMinMax() + { + /*_xAxis.axisRange = Double((_data?.xVals.count ?? 0) - 1)*/ + } + + open override var maxVisibleCount: Int + { + get + { + return data?.entryCount ?? 0 + } + } + + open override func notifyDataSetChanged() + { + calcMinMax() + + if let data = _data , _legend !== nil + { + legendRenderer.computeLegend(data: data) + } + + calculateOffsets() + + setNeedsDisplay() + } + + internal override func calculateOffsets() + { + var legendLeft = CGFloat(0.0) + var legendRight = CGFloat(0.0) + var legendBottom = CGFloat(0.0) + var legendTop = CGFloat(0.0) + + if _legend != nil && _legend.enabled && !_legend.drawInside + { + let fullLegendWidth = min(_legend.neededWidth, _viewPortHandler.chartWidth * _legend.maxSizePercent) + + switch _legend.orientation + { + case .vertical: + + var xLegendOffset: CGFloat = 0.0 + + if _legend.horizontalAlignment == .left + || _legend.horizontalAlignment == .right + { + if _legend.verticalAlignment == .center + { + // this is the space between the legend and the chart + let spacing = CGFloat(13.0) + + xLegendOffset = fullLegendWidth + spacing + } + else + { + // this is the space between the legend and the chart + let spacing = CGFloat(8.0) + + let legendWidth = fullLegendWidth + spacing + let legendHeight = _legend.neededHeight + _legend.textHeightMax + + let c = self.midPoint + + let bottomX = _legend.horizontalAlignment == .right + ? self.bounds.width - legendWidth + 15.0 + : legendWidth - 15.0 + let bottomY = legendHeight + 15 + let distLegend = distanceToCenter(x: bottomX, y: bottomY) + + let reference = getPosition(center: c, dist: self.radius, + angle: angleForPoint(x: bottomX, y: bottomY)) + + let distReference = distanceToCenter(x: reference.x, y: reference.y) + let minOffset = CGFloat(5.0) + + if bottomY >= c.y + && self.bounds.height - legendWidth > self.bounds.width + { + xLegendOffset = legendWidth + } + else if distLegend < distReference + { + let diff = distReference - distLegend + xLegendOffset = minOffset + diff + } + } + } + + switch _legend.horizontalAlignment + { + case .left: + legendLeft = xLegendOffset + + case .right: + legendRight = xLegendOffset + + case .center: + + switch _legend.verticalAlignment + { + case .top: + legendTop = min(_legend.neededHeight, _viewPortHandler.chartHeight * _legend.maxSizePercent) + + case .bottom: + legendBottom = min(_legend.neededHeight, _viewPortHandler.chartHeight * _legend.maxSizePercent) + + default: + break + } + } + + case .horizontal: + + var yLegendOffset: CGFloat = 0.0 + + if _legend.verticalAlignment == .top + || _legend.verticalAlignment == .bottom + { + // It's possible that we do not need this offset anymore as it + // is available through the extraOffsets, but changing it can mean + // changing default visibility for existing apps. + let yOffset = self.requiredLegendOffset + + yLegendOffset = min( + _legend.neededHeight + yOffset, + _viewPortHandler.chartHeight * _legend.maxSizePercent) + } + + switch _legend.verticalAlignment + { + case .top: + + legendTop = yLegendOffset + + case .bottom: + + legendBottom = yLegendOffset + + default: + break + } + } + + legendLeft += self.requiredBaseOffset + legendRight += self.requiredBaseOffset + legendTop += self.requiredBaseOffset + legendBottom += self.requiredBaseOffset + } + + legendTop += self.extraTopOffset + legendRight += self.extraRightOffset + legendBottom += self.extraBottomOffset + legendLeft += self.extraLeftOffset + + var minOffset = self.minOffset + + if self is RadarChartView + { + let x = self.xAxis + + if x.isEnabled && x.drawLabelsEnabled + { + minOffset = max(minOffset, x.labelRotatedWidth) + } + } + + let offsetLeft = max(minOffset, legendLeft) + let offsetTop = max(minOffset, legendTop) + let offsetRight = max(minOffset, legendRight) + let offsetBottom = max(minOffset, max(self.requiredBaseOffset, legendBottom)) + + _viewPortHandler.restrainViewPort(offsetLeft: offsetLeft, offsetTop: offsetTop, offsetRight: offsetRight, offsetBottom: offsetBottom) + } + + /// - Returns: The angle relative to the chart center for the given point on the chart in degrees. + /// The angle is always between 0 and 360°, 0° is NORTH, 90° is EAST, ... + @objc open func angleForPoint(x: CGFloat, y: CGFloat) -> CGFloat + { + let c = centerOffsets + + let tx = Double(x - c.x) + let ty = Double(y - c.y) + let length = sqrt(tx * tx + ty * ty) + let r = acos(ty / length) + + var angle = r.RAD2DEG + + if x > c.x + { + angle = 360.0 - angle + } + + // add 90° because chart starts EAST + angle = angle + 90.0 + + // neutralize overflow + if angle > 360.0 + { + angle = angle - 360.0 + } + + return CGFloat(angle) + } + + /// Calculates the position around a center point, depending on the distance + /// from the center, and the angle of the position around the center. + @objc open func getPosition(center: CGPoint, dist: CGFloat, angle: CGFloat) -> CGPoint + { + return CGPoint(x: center.x + dist * cos(angle.DEG2RAD), + y: center.y + dist * sin(angle.DEG2RAD)) + } + + /// - Returns: The distance of a certain point on the chart to the center of the chart. + @objc open func distanceToCenter(x: CGFloat, y: CGFloat) -> CGFloat + { + let c = self.centerOffsets + + var dist = CGFloat(0.0) + + var xDist = CGFloat(0.0) + var yDist = CGFloat(0.0) + + if x > c.x + { + xDist = x - c.x + } + else + { + xDist = c.x - x + } + + if y > c.y + { + yDist = y - c.y + } + else + { + yDist = c.y - y + } + + // pythagoras + dist = sqrt(pow(xDist, 2.0) + pow(yDist, 2.0)) + + return dist + } + + /// - Returns: The xIndex for the given angle around the center of the chart. + /// -1 if not found / outofbounds. + @objc open func indexForAngle(_ angle: CGFloat) -> Int + { + fatalError("indexForAngle() cannot be called on PieRadarChartViewBase") + } + + /// current rotation angle of the pie chart + /// + /// **default**: 270 --> top (NORTH) + /// Will always return a normalized value, which will be between 0.0 < 360.0 + @objc open var rotationAngle: CGFloat + { + get + { + return _rotationAngle + } + set + { + _rawRotationAngle = newValue + _rotationAngle = newValue.normalizedAngle + setNeedsDisplay() + } + } + + /// gets the raw version of the current rotation angle of the pie chart the returned value could be any value, negative or positive, outside of the 360 degrees. + /// this is used when working with rotation direction, mainly by gestures and animations. + @objc open var rawRotationAngle: CGFloat + { + return _rawRotationAngle + } + + /// The diameter of the pie- or radar-chart + @objc open var diameter: CGFloat + { + var content = _viewPortHandler.contentRect + content.origin.x += extraLeftOffset + content.origin.y += extraTopOffset + content.size.width -= extraLeftOffset + extraRightOffset + content.size.height -= extraTopOffset + extraBottomOffset + return min(content.width, content.height) + } + + /// The radius of the chart in pixels. + @objc open var radius: CGFloat + { + fatalError("radius cannot be called on PieRadarChartViewBase") + } + + /// The required offset for the chart legend. + internal var requiredLegendOffset: CGFloat + { + fatalError("requiredLegendOffset cannot be called on PieRadarChartViewBase") + } + + /// - Returns: The base offset needed for the chart without calculating the + /// legend size. + internal var requiredBaseOffset: CGFloat + { + fatalError("requiredBaseOffset cannot be called on PieRadarChartViewBase") + } + + open override var chartYMax: Double + { + return 0.0 + } + + open override var chartYMin: Double + { + return 0.0 + } + + @objc open var isRotationEnabled: Bool { return rotationEnabled } + + /// flag that indicates if rotation is done with two fingers or one. + /// when the chart is inside a scrollview, you need a two-finger rotation because a one-finger rotation eats up all touch events. + /// + /// On iOS this will disable one-finger rotation. + /// On OSX this will keep two-finger multitouch rotation, and one-pointer mouse rotation. + /// + /// **default**: false + @objc open var rotationWithTwoFingers: Bool + { + get + { + return _rotationWithTwoFingers + } + set + { + _rotationWithTwoFingers = newValue + #if !os(tvOS) + _rotationGestureRecognizer.isEnabled = _rotationWithTwoFingers + #endif + } + } + + /// flag that indicates if rotation is done with two fingers or one. + /// when the chart is inside a scrollview, you need a two-finger rotation because a one-finger rotation eats up all touch events. + /// + /// On iOS this will disable one-finger rotation. + /// On OSX this will keep two-finger multitouch rotation, and one-pointer mouse rotation. + /// + /// **default**: false + @objc open var isRotationWithTwoFingers: Bool + { + return _rotationWithTwoFingers + } + + // MARK: - Animation + + private var _spinAnimator: Animator! + + /// Applys a spin animation to the Chart. + @objc open func spin(duration: TimeInterval, fromAngle: CGFloat, toAngle: CGFloat, easing: ChartEasingFunctionBlock?) + { + if _spinAnimator != nil + { + _spinAnimator.stop() + } + + _spinAnimator = Animator() + _spinAnimator.updateBlock = { + self.rotationAngle = (toAngle - fromAngle) * CGFloat(self._spinAnimator.phaseX) + fromAngle + } + _spinAnimator.stopBlock = { self._spinAnimator = nil } + + _spinAnimator.animate(xAxisDuration: duration, easing: easing) + } + + @objc open func spin(duration: TimeInterval, fromAngle: CGFloat, toAngle: CGFloat, easingOption: ChartEasingOption) + { + spin(duration: duration, fromAngle: fromAngle, toAngle: toAngle, easing: easingFunctionFromOption(easingOption)) + } + + @objc open func spin(duration: TimeInterval, fromAngle: CGFloat, toAngle: CGFloat) + { + spin(duration: duration, fromAngle: fromAngle, toAngle: toAngle, easing: nil) + } + + @objc open func stopSpinAnimation() + { + if _spinAnimator != nil + { + _spinAnimator.stop() + } + } + + // MARK: - Gestures + + private var _rotationGestureStartPoint: CGPoint! + private var _isRotating = false + private var _startAngle = CGFloat(0.0) + + private struct AngularVelocitySample + { + var time: TimeInterval + var angle: CGFloat + } + + private var velocitySamples = [AngularVelocitySample]() + + private var _decelerationLastTime: TimeInterval = 0.0 + private var _decelerationDisplayLink: NSUIDisplayLink! + private var _decelerationAngularVelocity: CGFloat = 0.0 + + internal final func processRotationGestureBegan(location: CGPoint) + { + self.resetVelocity() + + if rotationEnabled + { + self.sampleVelocity(touchLocation: location) + } + + self.setGestureStartAngle(x: location.x, y: location.y) + + _rotationGestureStartPoint = location + } + + internal final func processRotationGestureMoved(location: CGPoint) + { + if isDragDecelerationEnabled + { + sampleVelocity(touchLocation: location) + } + + if !_isRotating && + distance( + eventX: location.x, + startX: _rotationGestureStartPoint.x, + eventY: location.y, + startY: _rotationGestureStartPoint.y) > CGFloat(8.0) + { + _isRotating = true + } + else + { + self.updateGestureRotation(x: location.x, y: location.y) + setNeedsDisplay() + } + } + + internal final func processRotationGestureEnded(location: CGPoint) + { + if isDragDecelerationEnabled + { + stopDeceleration() + + sampleVelocity(touchLocation: location) + + _decelerationAngularVelocity = calculateVelocity() + + if _decelerationAngularVelocity != 0.0 + { + _decelerationLastTime = CACurrentMediaTime() + _decelerationDisplayLink = NSUIDisplayLink(target: self, selector: #selector(PieRadarChartViewBase.decelerationLoop)) + _decelerationDisplayLink.add(to: RunLoop.main, forMode: RunLoop.Mode.common) + } + } + } + + internal final func processRotationGestureCancelled() + { + if _isRotating + { + _isRotating = false + } + } + + #if !os(OSX) + open override func nsuiTouchesBegan(_ touches: Set, withEvent event: NSUIEvent?) + { + // if rotation by touch is enabled + if rotationEnabled + { + stopDeceleration() + + if !rotationWithTwoFingers, let touchLocation = touches.first?.location(in: self) + { + processRotationGestureBegan(location: touchLocation) + } + } + + if !_isRotating + { + super.nsuiTouchesBegan(touches, withEvent: event) + } + } + + open override func nsuiTouchesMoved(_ touches: Set, withEvent event: NSUIEvent?) + { + if rotationEnabled && !rotationWithTwoFingers, let touch = touches.first + { + let touchLocation = touch.location(in: self) + processRotationGestureMoved(location: touchLocation) + } + + if !_isRotating + { + super.nsuiTouchesMoved(touches, withEvent: event) + } + } + + open override func nsuiTouchesEnded(_ touches: Set, withEvent event: NSUIEvent?) + { + if !_isRotating + { + super.nsuiTouchesEnded(touches, withEvent: event) + } + + if rotationEnabled && !rotationWithTwoFingers, let touch = touches.first + { + let touchLocation = touch.location(in: self) + processRotationGestureEnded(location: touchLocation) + } + + if _isRotating + { + _isRotating = false + } + } + + open override func nsuiTouchesCancelled(_ touches: Set?, withEvent event: NSUIEvent?) + { + super.nsuiTouchesCancelled(touches, withEvent: event) + + processRotationGestureCancelled() + } + #endif + + #if os(OSX) + open override func mouseDown(with theEvent: NSEvent) + { + // if rotation by touch is enabled + if rotationEnabled + { + stopDeceleration() + + let location = self.convert(theEvent.locationInWindow, from: nil) + + processRotationGestureBegan(location: location) + } + + if !_isRotating + { + super.mouseDown(with: theEvent) + } + } + + open override func mouseDragged(with theEvent: NSEvent) + { + if rotationEnabled + { + let location = self.convert(theEvent.locationInWindow, from: nil) + + processRotationGestureMoved(location: location) + } + + if !_isRotating + { + super.mouseDragged(with: theEvent) + } + } + + open override func mouseUp(with theEvent: NSEvent) + { + if !_isRotating + { + super.mouseUp(with: theEvent) + } + + if rotationEnabled + { + let location = self.convert(theEvent.locationInWindow, from: nil) + + processRotationGestureEnded(location: location) + } + + if _isRotating + { + _isRotating = false + } + } + #endif + + private func resetVelocity() + { + velocitySamples.removeAll(keepingCapacity: false) + } + + private func sampleVelocity(touchLocation: CGPoint) + { + let currentSample: AngularVelocitySample = { + let time = CACurrentMediaTime() + let angle = angleForPoint(x: touchLocation.x, y: touchLocation.y) + return AngularVelocitySample(time: time, angle: angle) + }() + + // Remove samples older than our sample time - 1 seconds + // while keeping at least one samples + let index = velocitySamples + .dropLast() + .lastIndex { $0.time < currentSample.time - 1 } + if let index = index { + velocitySamples.remove(at: index) + } + velocitySamples.append(currentSample) + } + + private func calculateVelocity() -> CGFloat + { + guard var firstSample = velocitySamples.first, + var lastSample = velocitySamples.last + else { return 0 } + + // Look for a sample that's closest to the latest sample, but not the same, so we can deduce the direction + let beforeLastSample = velocitySamples.last { $0.angle != lastSample.angle } + ?? firstSample + + // Calculate the sampling time + let timeDelta: CGFloat = { + let delta = CGFloat(lastSample.time - firstSample.time) + return delta == 0 ? 0.1 : delta + }() + + // Calculate clockwise/ccw by choosing two values that should be closest to each other, + // so if the angles are two far from each other we know they are inverted "for sure" + let isClockwise: Bool = { + let isClockwise = lastSample.angle >= beforeLastSample.angle + let isInverted = abs(lastSample.angle - beforeLastSample.angle) > 270.0 + return isInverted ? !isClockwise : isClockwise + }() + + // Now if the "gesture" is over a too big of an angle - then we know the angles are inverted, and we need to move them closer to each other from both sides of the 360.0 wrapping point + if lastSample.angle - firstSample.angle > 180.0 + { + firstSample.angle += 360.0 + } + else if firstSample.angle - lastSample.angle > 180.0 + { + lastSample.angle += 360.0 + } + + // The velocity + let velocity = abs((lastSample.angle - firstSample.angle) / timeDelta) + return isClockwise ? velocity : -velocity + } + + /// sets the starting angle of the rotation, this is only used by the touch listener, x and y is the touch position + private func setGestureStartAngle(x: CGFloat, y: CGFloat) + { + _startAngle = angleForPoint(x: x, y: y) + + // take the current angle into consideration when starting a new drag + _startAngle -= _rotationAngle + } + + /// updates the view rotation depending on the given touch position, also takes the starting angle into consideration + private func updateGestureRotation(x: CGFloat, y: CGFloat) + { + self.rotationAngle = angleForPoint(x: x, y: y) - _startAngle + } + + @objc open func stopDeceleration() + { + if _decelerationDisplayLink !== nil + { + _decelerationDisplayLink.remove(from: RunLoop.main, forMode: RunLoop.Mode.common) + _decelerationDisplayLink = nil + } + } + + @objc private func decelerationLoop() + { + let currentTime = CACurrentMediaTime() + + _decelerationAngularVelocity *= self.dragDecelerationFrictionCoef + + let timeInterval = CGFloat(currentTime - _decelerationLastTime) + + self.rotationAngle += _decelerationAngularVelocity * timeInterval + + _decelerationLastTime = currentTime + + if(abs(_decelerationAngularVelocity) < 0.001) + { + stopDeceleration() + } + } + + /// - Returns: The distance between two points + private func distance(eventX: CGFloat, startX: CGFloat, eventY: CGFloat, startY: CGFloat) -> CGFloat + { + let dx = eventX - startX + let dy = eventY - startY + return sqrt(dx * dx + dy * dy) + } + + /// - Returns: The distance between two points + private func distance(from: CGPoint, to: CGPoint) -> CGFloat + { + let dx = from.x - to.x + let dy = from.y - to.y + return sqrt(dx * dx + dy * dy) + } + + /// reference to the last highlighted object + private var _lastHighlight: Highlight! + + @objc private func tapGestureRecognized(_ recognizer: NSUITapGestureRecognizer) + { + if recognizer.state == NSUIGestureRecognizerState.ended + { + if !self.isHighLightPerTapEnabled { return } + + let location = recognizer.location(in: self) + + let high = self.getHighlightByTouchPoint(location) + self.highlightValue(high, callDelegate: true) + } + } + + #if !os(tvOS) + @objc private func rotationGestureRecognized(_ recognizer: NSUIRotationGestureRecognizer) + { + if recognizer.state == NSUIGestureRecognizerState.began + { + stopDeceleration() + + _startAngle = self.rawRotationAngle + } + + if recognizer.state == NSUIGestureRecognizerState.began || recognizer.state == NSUIGestureRecognizerState.changed + { + let angle = recognizer.nsuiRotation.RAD2DEG + + self.rotationAngle = _startAngle + angle + setNeedsDisplay() + } + else if recognizer.state == NSUIGestureRecognizerState.ended + { + let angle = recognizer.nsuiRotation.RAD2DEG + + self.rotationAngle = _startAngle + angle + setNeedsDisplay() + + if isDragDecelerationEnabled + { + stopDeceleration() + + _decelerationAngularVelocity = recognizer.velocity.RAD2DEG + + if _decelerationAngularVelocity != 0.0 + { + _decelerationLastTime = CACurrentMediaTime() + _decelerationDisplayLink = NSUIDisplayLink(target: self, selector: #selector(PieRadarChartViewBase.decelerationLoop)) + _decelerationDisplayLink.add(to: RunLoop.main, forMode: RunLoop.Mode.common) + } + } + } + } + #endif +} diff --git a/Pods/Charts/Source/Charts/Charts/RadarChartView.swift b/Pods/Charts/Source/Charts/Charts/RadarChartView.swift new file mode 100644 index 00000000..85892bff --- /dev/null +++ b/Pods/Charts/Source/Charts/Charts/RadarChartView.swift @@ -0,0 +1,220 @@ +// +// 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) + + 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.. 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 } +} diff --git a/Pods/Charts/Source/Charts/Charts/ScatterChartView.swift b/Pods/Charts/Source/Charts/Charts/ScatterChartView.swift new file mode 100644 index 00000000..22c710ad --- /dev/null +++ b/Pods/Charts/Source/Charts/Charts/ScatterChartView.swift @@ -0,0 +1,31 @@ +// +// ScatterChartView.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + +/// The ScatterChart. Draws dots, triangles, squares and custom shapes into the chartview. +open class ScatterChartView: BarLineChartViewBase, ScatterChartDataProvider +{ + open override func initialize() + { + super.initialize() + + renderer = ScatterChartRenderer(dataProvider: self, animator: _animator, viewPortHandler: _viewPortHandler) + + xAxis.spaceMin = 0.5 + xAxis.spaceMax = 0.5 + } + + // MARK: - ScatterChartDataProvider + + open var scatterData: ScatterChartData? { return _data as? ScatterChartData } +} diff --git a/Pods/Charts/Source/Charts/Components/AxisBase.swift b/Pods/Charts/Source/Charts/Components/AxisBase.swift new file mode 100644 index 00000000..437d4afa --- /dev/null +++ b/Pods/Charts/Source/Charts/Components/AxisBase.swift @@ -0,0 +1,359 @@ +// +// AxisBase.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + +/// Base class for all axes +@objc(ChartAxisBase) +open class AxisBase: ComponentBase +{ + public override init() + { + super.init() + } + + /// Custom formatter that is used instead of the auto-formatter if set + private var _axisValueFormatter: IAxisValueFormatter? + + @objc open var labelFont = NSUIFont.systemFont(ofSize: 10.0) + @objc open var labelTextColor = NSUIColor.black + + @objc open var axisLineColor = NSUIColor.gray + @objc open var axisLineWidth = CGFloat(0.5) + @objc open var axisLineDashPhase = CGFloat(0.0) + @objc open var axisLineDashLengths: [CGFloat]! + + @objc open var gridColor = NSUIColor.gray.withAlphaComponent(0.9) + @objc open var gridLineWidth = CGFloat(0.5) + @objc open var gridLineDashPhase = CGFloat(0.0) + @objc open var gridLineDashLengths: [CGFloat]! + @objc open var gridLineCap = CGLineCap.butt + + @objc open var drawGridLinesEnabled = true + @objc open var drawAxisLineEnabled = true + + /// flag that indicates of the labels of this axis should be drawn or not + @objc open var drawLabelsEnabled = true + + private var _centerAxisLabelsEnabled = false + + /// Centers the axis labels instead of drawing them at their original position. + /// This is useful especially for grouped BarChart. + @objc open var centerAxisLabelsEnabled: Bool + { + get { return _centerAxisLabelsEnabled && entryCount > 0 } + set { _centerAxisLabelsEnabled = newValue } + } + + @objc open var isCenterAxisLabelsEnabled: Bool + { + get { return centerAxisLabelsEnabled } + } + + /// array of limitlines that can be set for the axis + private var _limitLines = [ChartLimitLine]() + + /// Are the LimitLines drawn behind the data or in front of the data? + /// + /// **default**: false + @objc open var drawLimitLinesBehindDataEnabled = false + + /// the flag can be used to turn off the antialias for grid lines + @objc open var gridAntialiasEnabled = true + + /// the actual array of entries + @objc open var entries = [Double]() + + /// axis label entries only used for centered labels + @objc open var centeredEntries = [Double]() + + /// the number of entries the legend contains + @objc open var entryCount: Int { return entries.count } + + /// the number of label entries the axis should have + /// + /// **default**: 6 + private var _labelCount = Int(6) + + /// the number of decimal digits to use (for the default formatter + @objc open var decimals: Int = 0 + + /// When true, axis labels are controlled by the `granularity` property. + /// When false, axis values could possibly be repeated. + /// This could happen if two adjacent axis values are rounded to same value. + /// If using granularity this could be avoided by having fewer axis values visible. + @objc open var granularityEnabled = false + + private var _granularity = Double(1.0) + + /// The minimum interval between axis values. + /// This can be used to avoid label duplicating when zooming in. + /// + /// **default**: 1.0 + @objc open var granularity: Double + { + get + { + return _granularity + } + set + { + _granularity = newValue + + // set this to `true` if it was disabled, as it makes no sense to set this property with granularity disabled + granularityEnabled = true + } + } + + /// The minimum interval between axis values. + @objc open var isGranularityEnabled: Bool + { + get + { + return granularityEnabled + } + } + + /// if true, the set number of y-labels will be forced + @objc open var forceLabelsEnabled = false + + @objc open func getLongestLabel() -> String + { + var longest = "" + + for i in 0 ..< entries.count + { + let text = getFormattedLabel(i) + + if longest.count < text.count + { + longest = text + } + } + + return longest + } + + /// - Returns: The formatted label at the specified index. This will either use the auto-formatter or the custom formatter (if one is set). + @objc open func getFormattedLabel(_ index: Int) -> String + { + if index < 0 || index >= entries.count + { + return "" + } + + return valueFormatter?.stringForValue(entries[index], axis: self) ?? "" + } + + /// Sets the formatter to be used for formatting the axis labels. + /// If no formatter is set, the chart will automatically determine a reasonable formatting (concerning decimals) for all the values that are drawn inside the chart. + /// Use `nil` to use the formatter calculated by the chart. + @objc open var valueFormatter: IAxisValueFormatter? + { + get + { + if _axisValueFormatter == nil || + (_axisValueFormatter is DefaultAxisValueFormatter && + (_axisValueFormatter as! DefaultAxisValueFormatter).hasAutoDecimals && + (_axisValueFormatter as! DefaultAxisValueFormatter).decimals != decimals) + { + _axisValueFormatter = DefaultAxisValueFormatter(decimals: decimals) + } + + return _axisValueFormatter + } + set + { + _axisValueFormatter = newValue ?? DefaultAxisValueFormatter(decimals: decimals) + } + } + + @objc open var isDrawGridLinesEnabled: Bool { return drawGridLinesEnabled } + + @objc open var isDrawAxisLineEnabled: Bool { return drawAxisLineEnabled } + + @objc open var isDrawLabelsEnabled: Bool { return drawLabelsEnabled } + + /// Are the LimitLines drawn behind the data or in front of the data? + /// + /// **default**: false + @objc open var isDrawLimitLinesBehindDataEnabled: Bool { return drawLimitLinesBehindDataEnabled } + + /// Extra spacing for `axisMinimum` to be added to automatically calculated `axisMinimum` + @objc open var spaceMin: Double = 0.0 + + /// Extra spacing for `axisMaximum` to be added to automatically calculated `axisMaximum` + @objc open var spaceMax: Double = 0.0 + + /// Flag indicating that the axis-min value has been customized + internal var _customAxisMin: Bool = false + + /// Flag indicating that the axis-max value has been customized + internal var _customAxisMax: Bool = false + + /// Do not touch this directly, instead, use axisMinimum. + /// This is automatically calculated to represent the real min value, + /// and is used when calculating the effective minimum. + internal var _axisMinimum = Double(0) + + /// Do not touch this directly, instead, use axisMaximum. + /// This is automatically calculated to represent the real max value, + /// and is used when calculating the effective maximum. + internal var _axisMaximum = Double(0) + + /// the total range of values this axis covers + @objc open var axisRange = Double(0) + + /// The minumum number of labels on the axis + @objc open var axisMinLabels = Int(2) { + didSet { axisMinLabels = axisMinLabels > 0 ? axisMinLabels : oldValue } + } + + /// The maximum number of labels on the axis + @objc open var axisMaxLabels = Int(25) { + didSet { axisMaxLabels = axisMaxLabels > 0 ? axisMaxLabels : oldValue } + } + + /// the number of label entries the axis should have + /// max = 25, + /// min = 2, + /// default = 6, + /// be aware that this number is not fixed and can only be approximated + @objc open var labelCount: Int + { + get + { + return _labelCount + } + set + { + let range = axisMinLabels...axisMaxLabels as ClosedRange + _labelCount = newValue.clamped(to: range) + + forceLabelsEnabled = false + } + } + + @objc open func setLabelCount(_ count: Int, force: Bool) + { + self.labelCount = count + forceLabelsEnabled = force + } + + /// `true` if focing the y-label count is enabled. Default: false + @objc open var isForceLabelsEnabled: Bool { return forceLabelsEnabled } + + /// Adds a new ChartLimitLine to this axis. + @objc open func addLimitLine(_ line: ChartLimitLine) + { + _limitLines.append(line) + } + + /// Removes the specified ChartLimitLine from the axis. + @objc open func removeLimitLine(_ line: ChartLimitLine) + { + guard let i = _limitLines.firstIndex(of: line) else { return } + _limitLines.remove(at: i) + } + + /// Removes all LimitLines from the axis. + @objc open func removeAllLimitLines() + { + _limitLines.removeAll(keepingCapacity: false) + } + + /// The LimitLines of this axis. + @objc open var limitLines : [ChartLimitLine] + { + return _limitLines + } + + // MARK: Custom axis ranges + + /// By calling this method, any custom minimum value that has been previously set is reseted, and the calculation is done automatically. + @objc open func resetCustomAxisMin() + { + _customAxisMin = false + } + + @objc open var isAxisMinCustom: Bool { return _customAxisMin } + + /// By calling this method, any custom maximum value that has been previously set is reseted, and the calculation is done automatically. + @objc open func resetCustomAxisMax() + { + _customAxisMax = false + } + + @objc open var isAxisMaxCustom: Bool { return _customAxisMax } + + /// The minimum value for this axis. + /// If set, this value will not be calculated automatically depending on the provided data. + /// Use `resetCustomAxisMin()` to undo this. + @objc open var axisMinimum: Double + { + get + { + return _axisMinimum + } + set + { + _customAxisMin = true + _axisMinimum = newValue + axisRange = abs(_axisMaximum - newValue) + } + } + + /// The maximum value for this axis. + /// If set, this value will not be calculated automatically depending on the provided data. + /// Use `resetCustomAxisMax()` to undo this. + @objc open var axisMaximum: Double + { + get + { + return _axisMaximum + } + set + { + _customAxisMax = true + _axisMaximum = newValue + axisRange = abs(newValue - _axisMinimum) + } + } + + /// Calculates the minimum, maximum and range values of the YAxis with the given minimum and maximum values from the chart data. + /// + /// - Parameters: + /// - dataMin: the y-min value according to chart data + /// - dataMax: the y-max value according to chart + @objc open func calculate(min dataMin: Double, max dataMax: Double) + { + // if custom, use value as is, else use data value + var min = _customAxisMin ? _axisMinimum : (dataMin - spaceMin) + var max = _customAxisMax ? _axisMaximum : (dataMax + spaceMax) + + // temporary range (before calculations) + let range = abs(max - min) + + // in case all values are equal + if range == 0.0 + { + max = max + 1.0 + min = min - 1.0 + } + + _axisMinimum = min + _axisMaximum = max + + // actual range + axisRange = abs(max - min) + } +} diff --git a/Pods/Charts/Source/Charts/Components/ChartLimitLine.swift b/Pods/Charts/Source/Charts/Components/ChartLimitLine.swift new file mode 100644 index 00000000..41a2fe07 --- /dev/null +++ b/Pods/Charts/Source/Charts/Components/ChartLimitLine.swift @@ -0,0 +1,74 @@ +// +// ChartLimitLine.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + + +/// The limit line is an additional feature for all Line, Bar and ScatterCharts. +/// It allows the displaying of an additional line in the chart that marks a certain maximum / limit on the specified axis (x- or y-axis). +open class ChartLimitLine: ComponentBase +{ + @objc(ChartLimitLabelPosition) + public enum LabelPosition: Int + { + case topLeft + case topRight + case bottomLeft + case bottomRight + } + + /// limit / maximum (the y-value or xIndex) + @objc open var limit = Double(0.0) + + private var _lineWidth = CGFloat(2.0) + @objc open var lineColor = NSUIColor(red: 237.0/255.0, green: 91.0/255.0, blue: 91.0/255.0, alpha: 1.0) + @objc open var lineDashPhase = CGFloat(0.0) + @objc open var lineDashLengths: [CGFloat]? + + @objc open var valueTextColor = NSUIColor.black + @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) + } + } +} diff --git a/Pods/Charts/Source/Charts/Components/ComponentBase.swift b/Pods/Charts/Source/Charts/Components/ComponentBase.swift new file mode 100644 index 00000000..6014a175 --- /dev/null +++ b/Pods/Charts/Source/Charts/Components/ComponentBase.swift @@ -0,0 +1,37 @@ +// +// ComponentBase.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + + +/// This class encapsulates everything both Axis, Legend and LimitLines have in common +@objc(ChartComponentBase) +open class ComponentBase: NSObject +{ + /// flag that indicates if this component is enabled or not + @objc open var enabled = true + + /// The offset this component has on the x-axis + /// **default**: 5.0 + @objc open var xOffset = CGFloat(5.0) + + /// The offset this component has on the x-axis + /// **default**: 5.0 (or 0.0 on ChartYAxis) + @objc open var yOffset = CGFloat(5.0) + + public override init() + { + super.init() + } + + @objc open var isEnabled: Bool { return enabled } +} diff --git a/Pods/Charts/Source/Charts/Components/Description.swift b/Pods/Charts/Source/Charts/Components/Description.swift new file mode 100644 index 00000000..84990885 --- /dev/null +++ b/Pods/Charts/Source/Charts/Components/Description.swift @@ -0,0 +1,46 @@ +// +// 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 + +@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.black +} diff --git a/Pods/Charts/Source/Charts/Components/IMarker.swift b/Pods/Charts/Source/Charts/Components/IMarker.swift new file mode 100644 index 00000000..a4b75260 --- /dev/null +++ b/Pods/Charts/Source/Charts/Components/IMarker.swift @@ -0,0 +1,39 @@ +// +// ChartMarker.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + +@objc(IChartMarker) +public protocol IMarker: class +{ + /// - Returns: The desired (general) offset you wish the IMarker to have on the x-axis. + /// By returning x: -(width / 2) you will center the IMarker horizontally. + /// By returning y: -(height / 2) you will center the IMarker vertically. + var offset: CGPoint { get } + + /// - Parameters: + /// - point: This is the point at which the marker wants to be drawn. You can adjust the offset conditionally based on this argument. + /// - Returns: The offset for drawing at the specific `point`. + /// This allows conditional adjusting of the Marker position. + /// If you have no adjustments to make, return self.offset(). + func offsetForDrawing(atPoint: CGPoint) -> CGPoint + + /// This method enables a custom IMarker to update it's content every time the IMarker is redrawn according to the data entry it points to. + /// + /// - Parameters: + /// - entry: The Entry the IMarker belongs to. This can also be any subclass of Entry, like BarEntry or CandleEntry, simply cast it at runtime. + /// - highlight: The highlight object contains information about the highlighted value such as it's dataset-index, the selected range or stack-index (only stacked bar entries). + func refreshContent(entry: ChartDataEntry, highlight: Highlight) + + /// Draws the IMarker on the given position on the given context + func draw(context: CGContext, point: CGPoint) +} diff --git a/Pods/Charts/Source/Charts/Components/Legend.swift b/Pods/Charts/Source/Charts/Components/Legend.swift new file mode 100644 index 00000000..f50676ef --- /dev/null +++ b/Pods/Charts/Source/Charts/Components/Legend.swift @@ -0,0 +1,420 @@ +// +// Legend.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + +@objc(ChartLegend) +open class Legend: ComponentBase +{ + @objc(ChartLegendForm) + public enum Form: Int + { + /// Avoid drawing a form + case none + + /// Do not draw the a form, but leave space for it + case empty + + /// Use default (default dataset's form to the legend's form) + case `default` + + /// Draw a square + case square + + /// Draw a circle + case circle + + /// Draw a horizontal line + case line + } + + @objc(ChartLegendHorizontalAlignment) + public enum HorizontalAlignment: Int + { + case left + case center + case right + } + + @objc(ChartLegendVerticalAlignment) + public enum VerticalAlignment: Int + { + case top + case center + case bottom + } + + @objc(ChartLegendOrientation) + public enum Orientation: Int + { + case horizontal + case vertical + } + + @objc(ChartLegendDirection) + public enum Direction: Int + { + case leftToRight + case rightToLeft + } + + /// The legend entries array + @objc open var entries = [LegendEntry]() + + /// Entries that will be appended to the end of the auto calculated entries after calculating the legend. + /// (if the legend has already been calculated, you will need to call notifyDataSetChanged() to let the changes take effect) + @objc open var extraEntries = [LegendEntry]() + + /// Are the legend labels/colors a custom value or auto calculated? If false, then it's auto, if true, then custom. + /// + /// **default**: false (automatic legend) + private var _isLegendCustom = false + + /// The horizontal alignment of the legend + @objc open var horizontalAlignment: HorizontalAlignment = HorizontalAlignment.left + + /// The vertical alignment of the legend + @objc open var verticalAlignment: VerticalAlignment = VerticalAlignment.bottom + + /// The orientation of the legend + @objc open var orientation: Orientation = Orientation.horizontal + + /// Flag indicating whether the legend will draw inside the chart or outside + @objc open var drawInside: Bool = false + + /// Flag indicating whether the legend will draw inside the chart or outside + @objc open var isDrawInsideEnabled: Bool { return drawInside } + + /// The text direction of the legend + @objc open var direction: Direction = Direction.leftToRight + + @objc open var font: NSUIFont = NSUIFont.systemFont(ofSize: 10.0) + @objc open var textColor = NSUIColor.black + + /// The form/shape of the legend forms + @objc open var form = Form.square + + /// The size of the legend forms + @objc open var formSize = CGFloat(8.0) + + /// The line width for forms that consist of lines + @objc open var formLineWidth = CGFloat(3.0) + + /// Line dash configuration for shapes that consist of lines. + /// + /// This is how much (in pixels) into the dash pattern are we starting from. + @objc open var formLineDashPhase: CGFloat = 0.0 + + /// Line dash configuration for shapes that consist of lines. + /// + /// This is the actual dash pattern. + /// I.e. [2, 3] will paint [-- -- ] + /// [1, 3, 4, 2] will paint [- ---- - ---- ] + @objc open var formLineDashLengths: [CGFloat]? + + @objc open var xEntrySpace = CGFloat(6.0) + @objc open var yEntrySpace = CGFloat(0.0) + @objc open var formToTextSpace = CGFloat(5.0) + @objc open var stackSpace = CGFloat(3.0) + + @objc open var calculatedLabelSizes = [CGSize]() + @objc open var calculatedLabelBreakPoints = [Bool]() + @objc open var calculatedLineSizes = [CGSize]() + + public override init() + { + super.init() + + self.xOffset = 5.0 + self.yOffset = 3.0 + } + + @objc public init(entries: [LegendEntry]) + { + super.init() + + self.entries = entries + } + + @objc open func getMaximumEntrySize(withFont font: NSUIFont) -> CGSize + { + var maxW = CGFloat(0.0) + var maxH = CGFloat(0.0) + + var maxFormSize: CGFloat = 0.0 + + for entry in entries + { + let formSize = entry.formSize.isNaN ? self.formSize : entry.formSize + if formSize > maxFormSize + { + maxFormSize = formSize + } + + guard let label = entry.label + else { continue } + + let size = (label as NSString).size(withAttributes: [.font: font]) + + if size.width > maxW + { + maxW = size.width + } + if size.height > maxH + { + maxH = size.height + } + } + + return CGSize( + width: maxW + maxFormSize + formToTextSpace, + height: maxH + ) + } + + @objc open var neededWidth = CGFloat(0.0) + @objc open var neededHeight = CGFloat(0.0) + @objc open var textWidthMax = CGFloat(0.0) + @objc open var textHeightMax = CGFloat(0.0) + + /// flag that indicates if word wrapping is enabled + /// this is currently supported only for `orientation == Horizontal`. + /// you may want to set maxSizePercent when word wrapping, to set the point where the text wraps. + /// + /// **default**: true + @objc open var wordWrapEnabled = true + + /// if this is set, then word wrapping the legend is enabled. + @objc open var isWordWrapEnabled: Bool { return wordWrapEnabled } + + /// The maximum relative size out of the whole chart view in percent. + /// If the legend is to the right/left of the chart, then this affects the width of the legend. + /// If the legend is to the top/bottom of the chart, then this affects the height of the legend. + /// + /// **default**: 0.95 (95%) + @objc open var maxSizePercent: CGFloat = 0.95 + + @objc open func calculateDimensions(labelFont: NSUIFont, viewPortHandler: ViewPortHandler) + { + let maxEntrySize = getMaximumEntrySize(withFont: labelFont) + let defaultFormSize = self.formSize + let stackSpace = self.stackSpace + let formToTextSpace = self.formToTextSpace + let xEntrySpace = self.xEntrySpace + let yEntrySpace = self.yEntrySpace + let wordWrapEnabled = self.wordWrapEnabled + let entries = self.entries + let entryCount = entries.count + + textWidthMax = maxEntrySize.width + textHeightMax = maxEntrySize.height + + switch orientation + { + case .vertical: + + var maxWidth = CGFloat(0.0) + var width = CGFloat(0.0) + var maxHeight = CGFloat(0.0) + let labelLineHeight = labelFont.lineHeight + + var wasStacked = false + + for i in 0 ..< entryCount + { + let e = entries[i] + let drawingForm = e.form != .none + let formSize = e.formSize.isNaN ? defaultFormSize : e.formSize + let label = e.label + + if !wasStacked + { + width = 0.0 + } + + if drawingForm + { + if wasStacked + { + width += stackSpace + } + width += formSize + } + + if label != nil + { + let size = (label! as NSString).size(withAttributes: [.font: labelFont]) + + if drawingForm && !wasStacked + { + width += formToTextSpace + } + else if wasStacked + { + maxWidth = max(maxWidth, width) + maxHeight += labelLineHeight + yEntrySpace + width = 0.0 + wasStacked = false + } + + width += size.width + maxHeight += labelLineHeight + yEntrySpace + } + else + { + wasStacked = true + width += formSize + + if i < entryCount - 1 + { + width += stackSpace + } + } + + maxWidth = max(maxWidth, width) + } + + neededWidth = maxWidth + neededHeight = maxHeight + + case .horizontal: + + let labelLineHeight = labelFont.lineHeight + + let contentWidth: CGFloat = viewPortHandler.contentWidth * maxSizePercent + + // Prepare arrays for calculated layout + if calculatedLabelSizes.count != entryCount + { + calculatedLabelSizes = [CGSize](repeating: CGSize(), count: entryCount) + } + + if calculatedLabelBreakPoints.count != entryCount + { + calculatedLabelBreakPoints = [Bool](repeating: false, count: entryCount) + } + + calculatedLineSizes.removeAll(keepingCapacity: true) + + // Start calculating layout + + let labelAttrs = [NSAttributedString.Key.font: labelFont] + var maxLineWidth: CGFloat = 0.0 + var currentLineWidth: CGFloat = 0.0 + var requiredWidth: CGFloat = 0.0 + var stackedStartIndex: Int = -1 + + for i in 0 ..< entryCount + { + let e = entries[i] + let drawingForm = e.form != .none + let label = e.label + + calculatedLabelBreakPoints[i] = false + + if stackedStartIndex == -1 + { + // we are not stacking, so required width is for this label only + requiredWidth = 0.0 + } + else + { + // add the spacing appropriate for stacked labels/forms + requiredWidth += stackSpace + } + + // grouped forms have null labels + if label != nil + { + calculatedLabelSizes[i] = (label! as NSString).size(withAttributes: labelAttrs) + requiredWidth += drawingForm ? formToTextSpace + formSize : 0.0 + requiredWidth += calculatedLabelSizes[i].width + } + else + { + calculatedLabelSizes[i] = CGSize() + requiredWidth += drawingForm ? formSize : 0.0 + + if stackedStartIndex == -1 + { + // mark this index as we might want to break here later + stackedStartIndex = i + } + } + + if label != nil || i == entryCount - 1 + { + let requiredSpacing = currentLineWidth == 0.0 ? 0.0 : xEntrySpace + + if (!wordWrapEnabled || // No word wrapping, it must fit. + currentLineWidth == 0.0 || // The line is empty, it must fit. + (contentWidth - currentLineWidth >= requiredSpacing + requiredWidth)) // It simply fits + { + // Expand current line + currentLineWidth += requiredSpacing + requiredWidth + } + else + { // It doesn't fit, we need to wrap a line + + // Add current line size to array + calculatedLineSizes.append(CGSize(width: currentLineWidth, height: labelLineHeight)) + maxLineWidth = max(maxLineWidth, currentLineWidth) + + // Start a new line + calculatedLabelBreakPoints[stackedStartIndex > -1 ? stackedStartIndex : i] = true + currentLineWidth = requiredWidth + } + + if i == entryCount - 1 + { // Add last line size to array + calculatedLineSizes.append(CGSize(width: currentLineWidth, height: labelLineHeight)) + maxLineWidth = max(maxLineWidth, currentLineWidth) + } + } + + stackedStartIndex = label != nil ? -1 : stackedStartIndex + } + + neededWidth = maxLineWidth + neededHeight = labelLineHeight * CGFloat(calculatedLineSizes.count) + + yEntrySpace * CGFloat(calculatedLineSizes.count == 0 ? 0 : (calculatedLineSizes.count - 1)) + } + + neededWidth += xOffset + neededHeight += yOffset + } + + /// MARK: - Custom legend + + /// Sets a custom legend's entries array. + /// * A nil label will start a group. + /// This will disable the feature that automatically calculates the legend entries from the datasets. + /// Call `resetCustom(...)` to re-enable automatic calculation (and then `notifyDataSetChanged()` is needed). + @objc open func setCustom(entries: [LegendEntry]) + { + self.entries = entries + _isLegendCustom = true + } + + /// Calling this will disable the custom legend entries (set by `setLegend(...)`). Instead, the entries will again be calculated automatically (after `notifyDataSetChanged()` is called). + @objc open func resetCustom() + { + _isLegendCustom = false + } + + /// **default**: false (automatic legend) + /// `true` if a custom legend entries has been set + @objc open var isLegendCustom: Bool + { + return _isLegendCustom + } +} diff --git a/Pods/Charts/Source/Charts/Components/LegendEntry.swift b/Pods/Charts/Source/Charts/Components/LegendEntry.swift new file mode 100644 index 00000000..5868137e --- /dev/null +++ b/Pods/Charts/Source/Charts/Components/LegendEntry.swift @@ -0,0 +1,88 @@ +// +// LegendEntry.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + +@objc(ChartLegendEntry) +open class LegendEntry: NSObject +{ + public override init() + { + super.init() + } + + /// - Parameters: + /// - label: The legend entry text. + /// A `nil` label will start a group. + /// - form: The form to draw for this entry. + /// - formSize: Set to NaN to use the legend's default. + /// - formLineWidth: Set to NaN to use the legend's default. + /// - formLineDashPhase: Line dash configuration. + /// - formLineDashLengths: Line dash configurationas NaN to use the legend's default. + /// - formColor: The color for drawing the form. + @objc public init(label: String?, + form: Legend.Form, + formSize: CGFloat, + formLineWidth: CGFloat, + formLineDashPhase: CGFloat, + formLineDashLengths: [CGFloat]?, + formColor: NSUIColor?) + { + self.label = label + self.form = form + self.formSize = formSize + self.formLineWidth = formLineWidth + self.formLineDashPhase = formLineDashPhase + self.formLineDashLengths = formLineDashLengths + self.formColor = formColor + } + + /// The legend entry text. + /// A `nil` label will start a group. + @objc open var label: String? + + /// The form to draw for this entry. + /// + /// `None` will avoid drawing a form, and any related space. + /// `Empty` will avoid drawing a form, but keep its space. + /// `Default` will use the Legend's default. + @objc open var form: Legend.Form = .default + + /// Form size will be considered except for when .None is used + /// + /// Set as NaN to use the legend's default + @objc open var formSize: CGFloat = CGFloat.nan + + /// Line width used for shapes that consist of lines. + /// + /// Set to NaN to use the legend's default. + @objc open var formLineWidth: CGFloat = CGFloat.nan + + /// Line dash configuration for shapes that consist of lines. + /// + /// This is how much (in pixels) into the dash pattern are we starting from. + /// + /// Set to NaN to use the legend's default. + @objc open var formLineDashPhase: CGFloat = 0.0 + + /// Line dash configuration for shapes that consist of lines. + /// + /// This is the actual dash pattern. + /// I.e. [2, 3] will paint [-- -- ] + /// [1, 3, 4, 2] will paint [- ---- - ---- ] + /// + /// Set to nil to use the legend's default. + @objc open var formLineDashLengths: [CGFloat]? + + /// The color for drawing the form + @objc open var formColor: NSUIColor? +} diff --git a/Pods/Charts/Source/Charts/Components/MarkerImage.swift b/Pods/Charts/Source/Charts/Components/MarkerImage.swift new file mode 100644 index 00000000..341b1186 --- /dev/null +++ b/Pods/Charts/Source/Charts/Components/MarkerImage.swift @@ -0,0 +1,106 @@ +// +// ChartMarkerImage.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + +@objc(ChartMarkerImage) +open class MarkerImage: NSObject, IMarker +{ + /// The marker image to render + @objc open var image: NSUIImage? + + open var offset: CGPoint = CGPoint() + + @objc open weak var chartView: ChartViewBase? + + /// As long as size is 0.0/0.0 - it will default to the image's size + @objc open var size: CGSize = CGSize() + + public override init() + { + super.init() + } + + open func offsetForDrawing(atPoint point: CGPoint) -> CGPoint + { + var offset = self.offset + + let chart = self.chartView + + var size = self.size + + if size.width == 0.0 && image != nil + { + size.width = image?.size.width ?? 0.0 + } + if size.height == 0.0 && image != nil + { + size.height = image?.size.height ?? 0.0 + } + + let width = size.width + let height = size.height + + if point.x + offset.x < 0.0 + { + offset.x = -point.x + } + else if chart != nil && point.x + width + offset.x > chart!.bounds.size.width + { + offset.x = chart!.bounds.size.width - point.x - width + } + + if point.y + offset.y < 0 + { + offset.y = -point.y + } + else if chart != nil && point.y + height + offset.y > chart!.bounds.size.height + { + offset.y = chart!.bounds.size.height - point.y - height + } + + return offset + } + + open func refreshContent(entry: ChartDataEntry, highlight: Highlight) + { + // Do nothing here... + } + + open func draw(context: CGContext, point: CGPoint) + { + guard let image = image else { return } + + let offset = offsetForDrawing(atPoint: point) + + var size = self.size + + if size.width == 0.0 + { + size.width = image.size.width + } + if size.height == 0.0 + { + size.height = image.size.height + } + + let rect = CGRect( + x: point.x + offset.x, + y: point.y + offset.y, + width: size.width, + height: size.height) + + NSUIGraphicsPushContext(context) + image.draw(in: rect) + NSUIGraphicsPopContext() + } +} diff --git a/Pods/Charts/Source/Charts/Components/MarkerView.swift b/Pods/Charts/Source/Charts/Components/MarkerView.swift new file mode 100644 index 00000000..e4d682ce --- /dev/null +++ b/Pods/Charts/Source/Charts/Components/MarkerView.swift @@ -0,0 +1,95 @@ +// +// 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 + +@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(&loadedObjects) + + if bundle.loadNibNamed( + NSNib.Name(String(describing: self)), + owner: nil, + topLevelObjects: loadedObjectsPointer) + { + return loadedObjects[0] as? MarkerView + } + + return nil + #endif + } + +} diff --git a/Pods/Charts/Source/Charts/Components/XAxis.swift b/Pods/Charts/Source/Charts/Components/XAxis.swift new file mode 100644 index 00000000..77dbbd69 --- /dev/null +++ b/Pods/Charts/Source/Charts/Components/XAxis.swift @@ -0,0 +1,75 @@ +// +// XAxis.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + +@objc(ChartXAxis) +open class XAxis: AxisBase +{ + @objc(XAxisLabelPosition) + public enum LabelPosition: Int + { + case top + case bottom + case bothSided + case topInside + case bottomInside + } + + /// width of the x-axis labels in pixels - this is automatically calculated by the `computeSize()` methods in the renderers + @objc open var labelWidth = CGFloat(1.0) + + /// height of the x-axis labels in pixels - this is automatically calculated by the `computeSize()` methods in the renderers + @objc open var labelHeight = CGFloat(1.0) + + /// width of the (rotated) x-axis labels in pixels - this is automatically calculated by the `computeSize()` methods in the renderers + @objc open var labelRotatedWidth = CGFloat(1.0) + + /// height of the (rotated) x-axis labels in pixels - this is automatically calculated by the `computeSize()` methods in the renderers + @objc open var labelRotatedHeight = CGFloat(1.0) + + /// This is the angle for drawing the X axis labels (in degrees) + @objc open var labelRotationAngle = CGFloat(0.0) + + /// if set to true, the chart will avoid that the first and last label entry in the chart "clip" off the edge of the chart + @objc open var avoidFirstLastClippingEnabled = false + + /// the position of the x-labels relative to the chart + @objc open var labelPosition = LabelPosition.top + + /// if set to true, word wrapping the labels will be enabled. + /// word wrapping is done using `(value width * labelRotatedWidth)` + /// + /// - Note: currently supports all charts except pie/radar/horizontal-bar* + @objc open var wordWrapEnabled = false + + /// `true` if word wrapping the labels is enabled + @objc open var isWordWrapEnabled: Bool { return wordWrapEnabled } + + /// the width for wrapping the labels, as percentage out of one value width. + /// used only when isWordWrapEnabled = true. + /// + /// **default**: 1.0 + @objc open var wordWrapWidthPercent: CGFloat = 1.0 + + public override init() + { + super.init() + + self.yOffset = 4.0 + } + + @objc open var isAvoidFirstLastClippingEnabled: Bool + { + return avoidFirstLastClippingEnabled + } +} diff --git a/Pods/Charts/Source/Charts/Components/YAxis.swift b/Pods/Charts/Source/Charts/Components/YAxis.swift new file mode 100644 index 00000000..01e41b51 --- /dev/null +++ b/Pods/Charts/Source/Charts/Components/YAxis.swift @@ -0,0 +1,198 @@ +// +// 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 + + +/// 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 = 10.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 } + +} diff --git a/Pods/Charts/Source/Charts/Data/Implementations/ChartBaseDataSet.swift b/Pods/Charts/Source/Charts/Data/Implementations/ChartBaseDataSet.swift new file mode 100644 index 00000000..b331405b --- /dev/null +++ b/Pods/Charts/Source/Charts/Data/Implementations/ChartBaseDataSet.swift @@ -0,0 +1,435 @@ +// +// BaseDataSet.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + + +open class ChartBaseDataSet: NSObject, IChartDataSet, NSCopying +{ + public required override init() + { + super.init() + + // default color + colors.append(NSUIColor(red: 140.0/255.0, green: 234.0/255.0, blue: 255.0/255.0, alpha: 1.0)) + valueColors.append(NSUIColor.black) + } + + @objc public init(label: String?) + { + super.init() + + // default color + colors.append(NSUIColor(red: 140.0/255.0, green: 234.0/255.0, blue: 255.0/255.0, alpha: 1.0)) + valueColors.append(NSUIColor.black) + + self.label = label + } + + // MARK: - Data functions and accessors + + /// Use this method to tell the data set that the underlying data has changed + open func notifyDataSetChanged() + { + calcMinMax() + } + + open func calcMinMax() + { + fatalError("calcMinMax is not implemented in ChartBaseDataSet") + } + + open func calcMinMaxY(fromX: Double, toX: Double) + { + fatalError("calcMinMaxY(fromX:, toX:) is not implemented in ChartBaseDataSet") + } + + open var yMin: Double + { + fatalError("yMin is not implemented in ChartBaseDataSet") + } + + open var yMax: Double + { + fatalError("yMax is not implemented in ChartBaseDataSet") + } + + open var xMin: Double + { + fatalError("xMin is not implemented in ChartBaseDataSet") + } + + open var xMax: Double + { + fatalError("xMax is not implemented in ChartBaseDataSet") + } + + open var entryCount: Int + { + fatalError("entryCount is not implemented in ChartBaseDataSet") + } + + open func entryForIndex(_ i: Int) -> ChartDataEntry? + { + fatalError("entryForIndex is not implemented in ChartBaseDataSet") + } + + open func entryForXValue( + _ x: Double, + closestToY y: Double, + rounding: ChartDataSetRounding) -> ChartDataEntry? + { + fatalError("entryForXValue(x, closestToY, rounding) is not implemented in ChartBaseDataSet") + } + + open func entryForXValue( + _ x: Double, + closestToY y: Double) -> ChartDataEntry? + { + fatalError("entryForXValue(x, closestToY) is not implemented in ChartBaseDataSet") + } + + open func entriesForXValue(_ x: Double) -> [ChartDataEntry] + { + fatalError("entriesForXValue is not implemented in ChartBaseDataSet") + } + + open func entryIndex( + x xValue: Double, + closestToY y: Double, + rounding: ChartDataSetRounding) -> Int + { + fatalError("entryIndex(x, closestToY, rounding) is not implemented in ChartBaseDataSet") + } + + open func entryIndex(entry e: ChartDataEntry) -> Int + { + fatalError("entryIndex(entry) is not implemented in ChartBaseDataSet") + } + + open func addEntry(_ e: ChartDataEntry) -> Bool + { + fatalError("addEntry is not implemented in ChartBaseDataSet") + } + + open func addEntryOrdered(_ e: ChartDataEntry) -> Bool + { + fatalError("addEntryOrdered is not implemented in ChartBaseDataSet") + } + + @discardableResult open func removeEntry(_ entry: ChartDataEntry) -> Bool + { + fatalError("removeEntry is not implemented in ChartBaseDataSet") + } + + @discardableResult open func removeEntry(index: Int) -> Bool + { + if let entry = entryForIndex(index) + { + return removeEntry(entry) + } + return false + } + + @discardableResult open func removeEntry(x: Double) -> Bool + { + if let entry = entryForXValue(x, closestToY: Double.nan) + { + return removeEntry(entry) + } + return false + } + + @discardableResult open func removeFirst() -> Bool + { + if entryCount > 0 + { + if let entry = entryForIndex(0) + { + return removeEntry(entry) + } + } + return false + } + + @discardableResult open func removeLast() -> Bool + { + if entryCount > 0 + { + if let entry = entryForIndex(entryCount - 1) + { + return removeEntry(entry) + } + } + return false + } + + open func contains(_ e: ChartDataEntry) -> Bool + { + fatalError("removeEntry is not implemented in ChartBaseDataSet") + } + + open func clear() + { + fatalError("clear is not implemented in ChartBaseDataSet") + } + + // MARK: - Styling functions and accessors + + /// All the colors that are used for this DataSet. + /// Colors are reused as soon as the number of Entries the DataSet represents is higher than the size of the colors array. + open var colors = [NSUIColor]() + + /// List representing all colors that are used for drawing the actual values for this DataSet + open var valueColors = [NSUIColor]() + + /// The label string that describes the DataSet. + open var label: String? = "DataSet" + + /// The axis this DataSet should be plotted against. + open var axisDependency = YAxis.AxisDependency.left + + /// - Returns: The color at the given index of the DataSet's color array. + /// This prevents out-of-bounds by performing a modulus on the color index, so colours will repeat themselves. + open func color(atIndex index: Int) -> NSUIColor + { + var index = index + if index < 0 + { + index = 0 + } + return colors[index % colors.count] + } + + /// Resets all colors of this DataSet and recreates the colors array. + open func resetColors() + { + colors.removeAll(keepingCapacity: false) + } + + /// Adds a new color to the colors array of the DataSet. + /// + /// - Parameters: + /// - color: the color to add + open func addColor(_ color: NSUIColor) + { + colors.append(color) + } + + /// Sets the one and **only** color that should be used for this DataSet. + /// Internally, this recreates the colors array and adds the specified color. + /// + /// - Parameters: + /// - color: the color to set + open func setColor(_ color: NSUIColor) + { + colors.removeAll(keepingCapacity: false) + colors.append(color) + } + + /// Sets colors to a single color a specific alpha value. + /// + /// - Parameters: + /// - color: the color to set + /// - alpha: alpha to apply to the set `color` + @objc open func setColor(_ color: NSUIColor, alpha: CGFloat) + { + setColor(color.withAlphaComponent(alpha)) + } + + /// Sets colors with a specific alpha value. + /// + /// - Parameters: + /// - colors: the colors to set + /// - alpha: alpha to apply to the set `colors` + @objc open func setColors(_ colors: [NSUIColor], alpha: CGFloat) + { + self.colors = colors.map { $0.withAlphaComponent(alpha) } + } + + /// Sets colors with a specific alpha value. + /// + /// - Parameters: + /// - colors: the colors to set + /// - alpha: alpha to apply to the set `colors` + open func setColors(_ colors: NSUIColor...) + { + self.colors = colors + } + + /// if true, value highlighting is enabled + open var highlightEnabled = true + + /// `true` if value highlighting is enabled for this dataset + open var isHighlightEnabled: Bool { return highlightEnabled } + + /// Custom formatter that is used instead of the auto-formatter if set + internal var _valueFormatter: IValueFormatter? + + /// Custom formatter that is used instead of the auto-formatter if set + open var valueFormatter: IValueFormatter? + { + get + { + if needsFormatter + { + return ChartUtils.defaultValueFormatter() + } + + return _valueFormatter + } + set + { + if newValue == nil { return } + + _valueFormatter = newValue + } + } + + open var needsFormatter: Bool + { + return _valueFormatter == nil + } + + /// Sets/get a single color for value text. + /// Setting the color clears the colors array and adds a single color. + /// Getting will return the first color in the array. + open var valueTextColor: NSUIColor + { + get + { + return valueColors[0] + } + set + { + valueColors.removeAll(keepingCapacity: false) + valueColors.append(newValue) + } + } + + /// - Returns: The color at the specified index that is used for drawing the values inside the chart. Uses modulus internally. + open func valueTextColorAt(_ index: Int) -> NSUIColor + { + var index = index + if index < 0 + { + index = 0 + } + return valueColors[index % valueColors.count] + } + + /// the font for the value-text labels + open var valueFont: NSUIFont = NSUIFont.systemFont(ofSize: 7.0) + + /// The form to draw for this dataset in the legend. + open var form = Legend.Form.default + + /// The form size to draw for this dataset in the legend. + /// + /// Return `NaN` to use the default legend form size. + open var formSize: CGFloat = CGFloat.nan + + /// The line width for drawing the form of this dataset in the legend + /// + /// Return `NaN` to use the default legend form line width. + open var formLineWidth: CGFloat = CGFloat.nan + + /// Line dash configuration for legend shapes that consist of lines. + /// + /// This is how much (in pixels) into the dash pattern are we starting from. + open var formLineDashPhase: CGFloat = 0.0 + + /// Line dash configuration for legend shapes that consist of lines. + /// + /// This is the actual dash pattern. + /// I.e. [2, 3] will paint [-- -- ] + /// [1, 3, 4, 2] will paint [- ---- - ---- ] + open var formLineDashLengths: [CGFloat]? = nil + + /// Set this to true to draw y-values on the chart. + /// + /// - Note: For bar and line charts: if `maxVisibleCount` is reached, no values will be drawn even if this is enabled. + open var drawValuesEnabled = true + + /// `true` if y-value drawing is enabled, `false` ifnot + open var isDrawValuesEnabled: Bool + { + return drawValuesEnabled + } + + /// Set this to true to draw y-icons on the chart. + /// + /// - Note: For bar and line charts: if `maxVisibleCount` is reached, no icons will be drawn even if this is enabled. + open var drawIconsEnabled = true + + /// Returns true if y-icon drawing is enabled, false if not + open var isDrawIconsEnabled: Bool + { + return drawIconsEnabled + } + + /// Offset of icons drawn on the chart. + /// + /// For all charts except Pie and Radar it will be ordinary (x offset, y offset). + /// + /// For Pie and Radar chart it will be (y offset, distance from center offset); so if you want icon to be rendered under value, you should increase X component of CGPoint, and if you want icon to be rendered closet to center, you should decrease height component of CGPoint. + open var iconsOffset = CGPoint(x: 0, y: 0) + + /// Set the visibility of this DataSet. If not visible, the DataSet will not be drawn to the chart upon refreshing it. + open var visible = true + + /// `true` if this DataSet is visible inside the chart, or `false` ifit is currently hidden. + open var isVisible: Bool + { + return visible + } + + // MARK: - NSObject + + open override var description: String + { + return String(format: "%@, label: %@, %i entries", arguments: [NSStringFromClass(type(of: self)), self.label ?? "", self.entryCount]) + } + + open override var debugDescription: String + { + return (0.. Any + { + let copy = type(of: self).init() + + copy.colors = colors + copy.valueColors = valueColors + copy.label = label + copy.axisDependency = axisDependency + copy.highlightEnabled = highlightEnabled + copy._valueFormatter = _valueFormatter + copy.valueFont = valueFont + copy.form = form + copy.formSize = formSize + copy.formLineWidth = formLineWidth + copy.formLineDashPhase = formLineDashPhase + copy.formLineDashLengths = formLineDashLengths + copy.drawValuesEnabled = drawValuesEnabled + copy.drawValuesEnabled = drawValuesEnabled + copy.iconsOffset = iconsOffset + copy.visible = visible + + return copy + } +} diff --git a/Pods/Charts/Source/Charts/Data/Implementations/Standard/BarChartData.swift b/Pods/Charts/Source/Charts/Data/Implementations/Standard/BarChartData.swift new file mode 100644 index 00000000..6697c32c --- /dev/null +++ b/Pods/Charts/Source/Charts/Data/Implementations/Standard/BarChartData.swift @@ -0,0 +1,107 @@ +// +// BarChartData.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + +open class BarChartData: BarLineScatterCandleBubbleChartData +{ + public override init() + { + super.init() + } + + public override init(dataSets: [IChartDataSet]?) + { + super.init(dataSets: dataSets) + } + + /// The width of the bars on the x-axis, in values (not pixels) + /// + /// **default**: 0.85 + @objc open var barWidth = Double(0.85) + + /// Groups all BarDataSet objects this data object holds together by modifying the x-value of their entries. + /// Previously set x-values of entries will be overwritten. Leaves space between bars and groups as specified by the parameters. + /// Do not forget to call notifyDataSetChanged() on your BarChart object after calling this method. + /// + /// - Parameters: + /// - fromX: the starting point on the x-axis where the grouping should begin + /// - groupSpace: The space between groups of bars in values (not pixels) e.g. 0.8f for bar width 1f + /// - barSpace: The space between individual bars in values (not pixels) e.g. 0.1f for bar width 1f + @objc open func groupBars(fromX: Double, groupSpace: Double, barSpace: Double) + { + let setCount = _dataSets.count + if setCount <= 1 + { + print("BarData needs to hold at least 2 BarDataSets to allow grouping.", terminator: "\n") + return + } + + let max = maxEntryCountSet + let maxEntryCount = max?.entryCount ?? 0 + + let groupSpaceWidthHalf = groupSpace / 2.0 + let barSpaceHalf = barSpace / 2.0 + let barWidthHalf = self.barWidth / 2.0 + + var fromX = fromX + + let interval = groupWidth(groupSpace: groupSpace, barSpace: barSpace) + + for i in stride(from: 0, to: maxEntryCount, by: 1) + { + let start = fromX + fromX += groupSpaceWidthHalf + + (_dataSets as? [IBarChartDataSet])?.forEach { set in + fromX += barSpaceHalf + fromX += barWidthHalf + + if i < set.entryCount + { + if let entry = set.entryForIndex(i) + { + entry.x = fromX + } + } + + fromX += barWidthHalf + fromX += barSpaceHalf + } + + fromX += groupSpaceWidthHalf + let end = fromX + let innerInterval = end - start + let diff = interval - innerInterval + + // correct rounding errors + if diff > 0 || diff < 0 + { + fromX += diff + } + + } + + notifyDataChanged() + } + + /// In case of grouped bars, this method returns the space an individual group of bar needs on the x-axis. + /// + /// - Parameters: + /// - groupSpace: + /// - barSpace: + @objc open func groupWidth(groupSpace: Double, barSpace: Double) -> Double + { + return Double(_dataSets.count) * (self.barWidth + barSpace) + groupSpace + } + +} diff --git a/Pods/Charts/Source/Charts/Data/Implementations/Standard/BarChartDataEntry.swift b/Pods/Charts/Source/Charts/Data/Implementations/Standard/BarChartDataEntry.swift new file mode 100644 index 00000000..31c51b0f --- /dev/null +++ b/Pods/Charts/Source/Charts/Data/Implementations/Standard/BarChartDataEntry.swift @@ -0,0 +1,230 @@ +// +// BarChartDataEntry.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation + +open class BarChartDataEntry: ChartDataEntry +{ + /// the values the stacked barchart holds + private var _yVals: [Double]? + + /// the ranges for the individual stack values - automatically calculated + private var _ranges: [Range]? + + /// the sum of all negative values this entry (if stacked) contains + private var _negativeSum: Double = 0.0 + + /// the sum of all positive values this entry (if stacked) contains + private var _positiveSum: Double = 0.0 + + public required init() + { + super.init() + } + + /// Constructor for normal bars (not stacked). + public override init(x: Double, y: Double) + { + super.init(x: x, y: y) + } + + /// Constructor for normal bars (not stacked). + public convenience init(x: Double, y: Double, data: Any?) + { + self.init(x: x, y: y) + self.data = data + } + + /// Constructor for normal bars (not stacked). + public convenience init(x: Double, y: Double, icon: NSUIImage?) + { + self.init(x: x, y: y) + self.icon = icon + } + + /// Constructor for normal bars (not stacked). + public convenience init(x: Double, y: Double, icon: NSUIImage?, data: Any?) + { + self.init(x: x, y: y) + self.icon = icon + self.data = data + } + + /// Constructor for stacked bar entries. + @objc public init(x: Double, yValues: [Double]) + { + super.init(x: x, y: BarChartDataEntry.calcSum(values: yValues)) + self._yVals = yValues + calcPosNegSum() + calcRanges() + } + + /// Constructor for stacked bar entries. One data object for whole stack + @objc public convenience init(x: Double, yValues: [Double], icon: NSUIImage?) + { + self.init(x: x, yValues: yValues) + self.icon = icon + } + + /// Constructor for stacked bar entries. One data object for whole stack + @objc public convenience init(x: Double, yValues: [Double], data: Any?) + { + self.init(x: x, yValues: yValues) + self.data = data + } + + /// Constructor for stacked bar entries. One data object for whole stack + @objc public convenience init(x: Double, yValues: [Double], icon: NSUIImage?, data: Any?) + { + self.init(x: x, yValues: yValues) + self.icon = icon + self.data = data + } + + @objc open func sumBelow(stackIndex :Int) -> Double + { + guard let yVals = _yVals else + { + return 0 + } + + var remainder: Double = 0.0 + var index = yVals.count - 1 + + while (index > stackIndex && index >= 0) + { + remainder += yVals[index] + index -= 1 + } + + return remainder + } + + /// The sum of all negative values this entry (if stacked) contains. (this is a positive number) + @objc open var negativeSum: Double + { + return _negativeSum + } + + /// The sum of all positive values this entry (if stacked) contains. + @objc open var positiveSum: Double + { + return _positiveSum + } + + @objc open func calcPosNegSum() + { + (_negativeSum, _positiveSum) = _yVals?.reduce(into: (0,0)) { (result, y) in + if y < 0 + { + result.0 += -y + } + else + { + result.1 += y + } + } ?? (0,0) + } + + /// Splits up the stack-values of the given bar-entry into Range objects. + /// + /// - Parameters: + /// - entry: + /// - Returns: + @objc open func calcRanges() + { + guard let values = yValues, !values.isEmpty else { return } + + if _ranges == nil + { + _ranges = [Range]() + } + else + { + _ranges!.removeAll() + } + + _ranges!.reserveCapacity(values.count) + + var negRemain = -negativeSum + var posRemain: Double = 0.0 + + for value in values + { + if value < 0 + { + _ranges!.append(Range(from: negRemain, to: negRemain - value)) + negRemain -= value + } + else + { + _ranges!.append(Range(from: posRemain, to: posRemain + value)) + posRemain += value + } + } + } + + // MARK: Accessors + + /// the values the stacked barchart holds + @objc open var isStacked: Bool { return _yVals != nil } + + /// the values the stacked barchart holds + @objc open var yValues: [Double]? + { + get { return self._yVals } + set + { + self.y = BarChartDataEntry.calcSum(values: newValue) + self._yVals = newValue + calcPosNegSum() + calcRanges() + } + } + + /// The ranges of the individual stack-entries. Will return null if this entry is not stacked. + @objc open var ranges: [Range]? + { + return _ranges + } + + // MARK: NSCopying + + open override func copy(with zone: NSZone? = nil) -> Any + { + let copy = super.copy(with: zone) as! BarChartDataEntry + copy._yVals = _yVals + copy.y = y + copy._negativeSum = _negativeSum + copy._positiveSum = _positiveSum + return copy + } + + /// Calculates the sum across all values of the given stack. + /// + /// - Parameters: + /// - vals: + /// - Returns: + private static func calcSum(values: [Double]?) -> Double + { + guard let values = values + else { return 0.0 } + + var sum = 0.0 + + for f in values + { + sum += f + } + + return sum + } +} diff --git a/Pods/Charts/Source/Charts/Data/Implementations/Standard/BarChartDataSet.swift b/Pods/Charts/Source/Charts/Data/Implementations/Standard/BarChartDataSet.swift new file mode 100644 index 00000000..2478aecc --- /dev/null +++ b/Pods/Charts/Source/Charts/Data/Implementations/Standard/BarChartDataSet.swift @@ -0,0 +1,167 @@ +// +// BarChartDataSet.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + + +open class BarChartDataSet: BarLineScatterCandleBubbleChartDataSet, IBarChartDataSet +{ + private func initialize() + { + self.highlightColor = NSUIColor.black + + self.calcStackSize(entries: entries as! [BarChartDataEntry]) + self.calcEntryCountIncludingStacks(entries: entries as! [BarChartDataEntry]) + } + + public required init() + { + super.init() + initialize() + } + + public override init(entries: [ChartDataEntry]?, label: String?) + { + super.init(entries: entries, label: label) + initialize() + } + + // MARK: - Data functions and accessors + + /// the maximum number of bars that are stacked upon each other, this value + /// is calculated from the Entries that are added to the DataSet + private var _stackSize = 1 + + /// the overall entry count, including counting each stack-value individually + private var _entryCountStacks = 0 + + /// Calculates the total number of entries this DataSet represents, including + /// stacks. All values belonging to a stack are calculated separately. + private func calcEntryCountIncludingStacks(entries: [BarChartDataEntry]) + { + _entryCountStacks = 0 + + for i in 0 ..< entries.count + { + if let vals = entries[i].yValues + { + _entryCountStacks += vals.count + } + else + { + _entryCountStacks += 1 + } + } + } + + /// calculates the maximum stacksize that occurs in the Entries array of this DataSet + private func calcStackSize(entries: [BarChartDataEntry]) + { + for i in 0 ..< entries.count + { + if let vals = entries[i].yValues + { + if vals.count > _stackSize + { + _stackSize = vals.count + } + } + } + } + + open override func calcMinMax(entry e: ChartDataEntry) + { + guard let e = e as? BarChartDataEntry + else { return } + + if !e.y.isNaN + { + if e.yValues == nil + { + if e.y < _yMin + { + _yMin = e.y + } + + if e.y > _yMax + { + _yMax = e.y + } + } + else + { + if -e.negativeSum < _yMin + { + _yMin = -e.negativeSum + } + + if e.positiveSum > _yMax + { + _yMax = e.positiveSum + } + } + + calcMinMaxX(entry: e) + } + } + + /// The maximum number of bars that can be stacked upon another in this DataSet. + open var stackSize: Int + { + return _stackSize + } + + /// `true` if this DataSet is stacked (stacksize > 1) or not. + open var isStacked: Bool + { + return _stackSize > 1 ? true : false + } + + /// The overall entry count, including counting each stack-value individually + @objc open var entryCountStacks: Int + { + return _entryCountStacks + } + + /// array of labels used to describe the different values of the stacked bars + open var stackLabels: [String] = [] + + // MARK: - Styling functions and accessors + + /// the color used for drawing the bar-shadows. The bar shadows is a surface behind the bar that indicates the maximum value + open var barShadowColor = NSUIColor(red: 215.0/255.0, green: 215.0/255.0, blue: 215.0/255.0, alpha: 1.0) + + /// the width used for drawing borders around the bars. If borderWidth == 0, no border will be drawn. + open var barBorderWidth : CGFloat = 0.0 + + /// the color drawing borders around the bars. + open var barBorderColor = NSUIColor.black + + /// the alpha value (transparency) that is used for drawing the highlight indicator bar. min = 0.0 (fully transparent), max = 1.0 (fully opaque) + open var highlightAlpha = CGFloat(120.0 / 255.0) + + // MARK: - NSCopying + + open override func copy(with zone: NSZone? = nil) -> Any + { + let copy = super.copy(with: zone) as! BarChartDataSet + copy._stackSize = _stackSize + copy._entryCountStacks = _entryCountStacks + copy.stackLabels = stackLabels + + copy.barShadowColor = barShadowColor + copy.barBorderWidth = barBorderWidth + copy.barBorderColor = barBorderColor + copy.highlightAlpha = highlightAlpha + return copy + } +} diff --git a/Pods/Charts/Source/Charts/Data/Implementations/Standard/BarLineScatterCandleBubbleChartData.swift b/Pods/Charts/Source/Charts/Data/Implementations/Standard/BarLineScatterCandleBubbleChartData.swift new file mode 100644 index 00000000..c98bb1d0 --- /dev/null +++ b/Pods/Charts/Source/Charts/Data/Implementations/Standard/BarLineScatterCandleBubbleChartData.swift @@ -0,0 +1,25 @@ +// +// BarLineScatterCandleBubbleChartData.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation + +open class BarLineScatterCandleBubbleChartData: ChartData +{ + public override init() + { + super.init() + } + + public override init(dataSets: [IChartDataSet]?) + { + super.init(dataSets: dataSets) + } +} diff --git a/Pods/Charts/Source/Charts/Data/Implementations/Standard/BarLineScatterCandleBubbleChartDataSet.swift b/Pods/Charts/Source/Charts/Data/Implementations/Standard/BarLineScatterCandleBubbleChartDataSet.swift new file mode 100644 index 00000000..91382515 --- /dev/null +++ b/Pods/Charts/Source/Charts/Data/Implementations/Standard/BarLineScatterCandleBubbleChartDataSet.swift @@ -0,0 +1,38 @@ +// +// BarLineScatterCandleBubbleChartDataSet.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + + +open class BarLineScatterCandleBubbleChartDataSet: ChartDataSet, IBarLineScatterCandleBubbleChartDataSet +{ + // MARK: - Data functions and accessors + + // MARK: - Styling functions and accessors + + open var highlightColor = NSUIColor(red: 255.0/255.0, green: 187.0/255.0, blue: 115.0/255.0, alpha: 1.0) + open var highlightLineWidth = CGFloat(0.5) + open var highlightLineDashPhase = CGFloat(0.0) + open var highlightLineDashLengths: [CGFloat]? + + // MARK: - NSCopying + + open override func copy(with zone: NSZone? = nil) -> Any + { + let copy = super.copy(with: zone) as! BarLineScatterCandleBubbleChartDataSet + copy.highlightColor = highlightColor + copy.highlightLineWidth = highlightLineWidth + copy.highlightLineDashPhase = highlightLineDashPhase + copy.highlightLineDashLengths = highlightLineDashLengths + return copy + } +} diff --git a/Pods/Charts/Source/Charts/Data/Implementations/Standard/BubbleChartData.swift b/Pods/Charts/Source/Charts/Data/Implementations/Standard/BubbleChartData.swift new file mode 100644 index 00000000..433f384f --- /dev/null +++ b/Pods/Charts/Source/Charts/Data/Implementations/Standard/BubbleChartData.swift @@ -0,0 +1,32 @@ +// +// BubbleChartData.swift +// Charts +// +// Bubble chart implementation: +// Copyright 2015 Pierre-Marc Airoldi +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + +open class BubbleChartData: BarLineScatterCandleBubbleChartData +{ + public override init() + { + super.init() + } + + public override init(dataSets: [IChartDataSet]?) + { + super.init(dataSets: dataSets) + } + + /// Sets the width of the circle that surrounds the bubble when highlighted for all DataSet objects this data object contains + @objc open func setHighlightCircleWidth(_ width: CGFloat) + { + (_dataSets as? [IBubbleChartDataSet])?.forEach { $0.highlightCircleWidth = width } + } +} diff --git a/Pods/Charts/Source/Charts/Data/Implementations/Standard/BubbleChartDataEntry.swift b/Pods/Charts/Source/Charts/Data/Implementations/Standard/BubbleChartDataEntry.swift new file mode 100644 index 00000000..01f9fc96 --- /dev/null +++ b/Pods/Charts/Source/Charts/Data/Implementations/Standard/BubbleChartDataEntry.swift @@ -0,0 +1,79 @@ +// +// BubbleDataEntry.swift +// Charts +// +// Bubble chart implementation: +// Copyright 2015 Pierre-Marc Airoldi +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + +open class BubbleChartDataEntry: ChartDataEntry +{ + /// The size of the bubble. + @objc open var size = CGFloat(0.0) + + public required init() + { + super.init() + } + + /// - Parameters: + /// - x: The index on the x-axis. + /// - y: The value on the y-axis. + /// - size: The size of the bubble. + @objc public init(x: Double, y: Double, size: CGFloat) + { + super.init(x: x, y: y) + + self.size = size + } + + /// - Parameters: + /// - x: The index on the x-axis. + /// - y: The value on the y-axis. + /// - size: The size of the bubble. + /// - data: Spot for additional data this Entry represents. + @objc public convenience init(x: Double, y: Double, size: CGFloat, data: Any?) + { + self.init(x: x, y: y, size: size) + self.data = data + } + + /// - Parameters: + /// - x: The index on the x-axis. + /// - y: The value on the y-axis. + /// - size: The size of the bubble. + /// - icon: icon image + @objc public convenience init(x: Double, y: Double, size: CGFloat, icon: NSUIImage?) + { + self.init(x: x, y: y, size: size) + self.icon = icon + } + + /// - Parameters: + /// - x: The index on the x-axis. + /// - y: The value on the y-axis. + /// - size: The size of the bubble. + /// - icon: icon image + /// - data: Spot for additional data this Entry represents. + @objc public convenience init(x: Double, y: Double, size: CGFloat, icon: NSUIImage?, data: Any?) + { + self.init(x: x, y: y, size: size) + self.icon = icon + self.data = data + } + + // MARK: NSCopying + + open override func copy(with zone: NSZone? = nil) -> Any + { + let copy = super.copy(with: zone) as! BubbleChartDataEntry + copy.size = size + return copy + } +} diff --git a/Pods/Charts/Source/Charts/Data/Implementations/Standard/BubbleChartDataSet.swift b/Pods/Charts/Source/Charts/Data/Implementations/Standard/BubbleChartDataSet.swift new file mode 100644 index 00000000..775fafb8 --- /dev/null +++ b/Pods/Charts/Source/Charts/Data/Implementations/Standard/BubbleChartDataSet.swift @@ -0,0 +1,58 @@ +// +// BubbleChartDataSet.swift +// Charts +// +// Bubble chart implementation: +// Copyright 2015 Pierre-Marc Airoldi +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + + +open class BubbleChartDataSet: BarLineScatterCandleBubbleChartDataSet, IBubbleChartDataSet +{ + // MARK: - Data functions and accessors + + internal var _maxSize = CGFloat(0.0) + + open var maxSize: CGFloat { return _maxSize } + @objc open var normalizeSizeEnabled: Bool = true + open var isNormalizeSizeEnabled: Bool { return normalizeSizeEnabled } + + open override func calcMinMax(entry e: ChartDataEntry) + { + guard let e = e as? BubbleChartDataEntry + else { return } + + super.calcMinMax(entry: e) + + let size = e.size + + if size > _maxSize + { + _maxSize = size + } + } + + // MARK: - Styling functions and accessors + + /// Sets/gets the width of the circle that surrounds the bubble when highlighted + open var highlightCircleWidth: CGFloat = 2.5 + + // MARK: - NSCopying + + open override func copy(with zone: NSZone? = nil) -> Any + { + let copy = super.copy(with: zone) as! BubbleChartDataSet + copy._xMin = _xMin + copy._xMax = _xMax + copy._maxSize = _maxSize + copy.normalizeSizeEnabled = normalizeSizeEnabled + copy.highlightCircleWidth = highlightCircleWidth + return copy + } +} diff --git a/Pods/Charts/Source/Charts/Data/Implementations/Standard/CandleChartData.swift b/Pods/Charts/Source/Charts/Data/Implementations/Standard/CandleChartData.swift new file mode 100644 index 00000000..5158668a --- /dev/null +++ b/Pods/Charts/Source/Charts/Data/Implementations/Standard/CandleChartData.swift @@ -0,0 +1,25 @@ +// +// CandleChartData.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation + +open class CandleChartData: BarLineScatterCandleBubbleChartData +{ + public override init() + { + super.init() + } + + public override init(dataSets: [IChartDataSet]?) + { + super.init(dataSets: dataSets) + } +} diff --git a/Pods/Charts/Source/Charts/Data/Implementations/Standard/CandleChartDataEntry.swift b/Pods/Charts/Source/Charts/Data/Implementations/Standard/CandleChartDataEntry.swift new file mode 100644 index 00000000..467bc168 --- /dev/null +++ b/Pods/Charts/Source/Charts/Data/Implementations/Standard/CandleChartDataEntry.swift @@ -0,0 +1,98 @@ +// +// CandleChartDataEntry.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation + +open class CandleChartDataEntry: ChartDataEntry +{ + /// shadow-high value + @objc open var high = Double(0.0) + + /// shadow-low value + @objc open var low = Double(0.0) + + /// close value + @objc open var close = Double(0.0) + + /// open value + @objc open var open = Double(0.0) + + public required init() + { + super.init() + } + + @objc public init(x: Double, shadowH: Double, shadowL: Double, open: Double, close: Double) + { + super.init(x: x, y: (shadowH + shadowL) / 2.0) + + self.high = shadowH + self.low = shadowL + self.open = open + self.close = close + } + + @objc public convenience init(x: Double, shadowH: Double, shadowL: Double, open: Double, close: Double, icon: NSUIImage?) + { + self.init(x: x, shadowH: shadowH, shadowL: shadowL, open: open, close: close) + self.icon = icon + } + + @objc public convenience init(x: Double, shadowH: Double, shadowL: Double, open: Double, close: Double, data: Any?) + { + self.init(x: x, shadowH: shadowH, shadowL: shadowL, open: open, close: close) + self.data = data + } + + @objc public convenience init(x: Double, shadowH: Double, shadowL: Double, open: Double, close: Double, icon: NSUIImage?, data: Any?) + { + self.init(x: x, shadowH: shadowH, shadowL: shadowL, open: open, close: close) + self.icon = icon + self.data = data + } + + /// The overall range (difference) between shadow-high and shadow-low. + @objc open var shadowRange: Double + { + return abs(high - low) + } + + /// The body size (difference between open and close). + @objc open var bodyRange: Double + { + return abs(open - close) + } + + /// the center value of the candle. (Middle value between high and low) + open override var y: Double + { + get + { + return super.y + } + set + { + super.y = (high + low) / 2.0 + } + } + + // MARK: NSCopying + + open override func copy(with zone: NSZone? = nil) -> Any + { + let copy = super.copy(with: zone) as! CandleChartDataEntry + copy.high = high + copy.low = low + copy.open = open + copy.close = close + return copy + } +} diff --git a/Pods/Charts/Source/Charts/Data/Implementations/Standard/CandleChartDataSet.swift b/Pods/Charts/Source/Charts/Data/Implementations/Standard/CandleChartDataSet.swift new file mode 100644 index 00000000..1c51da7d --- /dev/null +++ b/Pods/Charts/Source/Charts/Data/Implementations/Standard/CandleChartDataSet.swift @@ -0,0 +1,136 @@ +// +// CandleChartDataSet.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + + +open class CandleChartDataSet: LineScatterCandleRadarChartDataSet, ICandleChartDataSet +{ + + public required init() + { + super.init() + } + + public override init(entries: [ChartDataEntry]?, label: String?) + { + super.init(entries: entries, label: label) + } + + // MARK: - Data functions and accessors + + open override func calcMinMax(entry e: ChartDataEntry) + { + guard let e = e as? CandleChartDataEntry + else { return } + + if e.low < _yMin + { + _yMin = e.low + } + + if e.high > _yMax + { + _yMax = e.high + } + + calcMinMaxX(entry: e) + } + + open override func calcMinMaxY(entry e: ChartDataEntry) + { + guard let e = e as? CandleChartDataEntry + else { return } + + if e.high < _yMin + { + _yMin = e.high + } + if e.high > _yMax + { + _yMax = e.high + } + + if e.low < _yMin + { + _yMin = e.low + } + if e.low > _yMax + { + _yMax = e.low + } + } + + // MARK: - Styling functions and accessors + + /// the space between the candle entries + /// + /// **default**: 0.1 (10%) + private var _barSpace = CGFloat(0.1) + + /// the space that is left out on the left and right side of each candle, + /// **default**: 0.1 (10%), max 0.45, min 0.0 + open var barSpace: CGFloat + { + get + { + return _barSpace + } + set + { + _barSpace = newValue.clamped(to: 0...0.45) + } + } + + /// should the candle bars show? + /// when false, only "ticks" will show + /// + /// **default**: true + open var showCandleBar: Bool = true + + /// the width of the candle-shadow-line in pixels. + /// + /// **default**: 1.5 + open var shadowWidth = CGFloat(1.5) + + /// the color of the shadow line + open var shadowColor: NSUIColor? + + /// use candle color for the shadow + open var shadowColorSameAsCandle = false + + /// Is the shadow color same as the candle color? + open var isShadowColorSameAsCandle: Bool { return shadowColorSameAsCandle } + + /// color for open == close + open var neutralColor: NSUIColor? + + /// color for open > close + open var increasingColor: NSUIColor? + + /// color for open < close + open var decreasingColor: NSUIColor? + + /// Are increasing values drawn as filled? + /// increasing candlesticks are traditionally hollow + open var increasingFilled = false + + /// Are increasing values drawn as filled? + open var isIncreasingFilled: Bool { return increasingFilled } + + /// Are decreasing values drawn as filled? + /// descreasing candlesticks are traditionally filled + open var decreasingFilled = true + + /// Are decreasing values drawn as filled? + open var isDecreasingFilled: Bool { return decreasingFilled } +} diff --git a/Pods/Charts/Source/Charts/Data/Implementations/Standard/ChartData.swift b/Pods/Charts/Source/Charts/Data/Implementations/Standard/ChartData.swift new file mode 100644 index 00000000..1cb1fd93 --- /dev/null +++ b/Pods/Charts/Source/Charts/Data/Implementations/Standard/ChartData.swift @@ -0,0 +1,612 @@ +// +// ChartData.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation + +open class ChartData: NSObject +{ + internal var _yMax: Double = -Double.greatestFiniteMagnitude + internal var _yMin: Double = Double.greatestFiniteMagnitude + internal var _xMax: Double = -Double.greatestFiniteMagnitude + internal var _xMin: Double = Double.greatestFiniteMagnitude + internal var _leftAxisMax: Double = -Double.greatestFiniteMagnitude + internal var _leftAxisMin: Double = Double.greatestFiniteMagnitude + internal var _rightAxisMax: Double = -Double.greatestFiniteMagnitude + internal var _rightAxisMin: Double = Double.greatestFiniteMagnitude + + internal var _dataSets = [IChartDataSet]() + + public override init() + { + super.init() + + _dataSets = [IChartDataSet]() + } + + @objc public init(dataSets: [IChartDataSet]?) + { + super.init() + + _dataSets = dataSets ?? [IChartDataSet]() + + self.initialize(dataSets: _dataSets) + } + + @objc public convenience init(dataSet: IChartDataSet?) + { + self.init(dataSets: dataSet === nil ? nil : [dataSet!]) + } + + internal func initialize(dataSets: [IChartDataSet]) + { + notifyDataChanged() + } + + /// Call this method to let the ChartData know that the underlying data has changed. + /// Calling this performs all necessary recalculations needed when the contained data has changed. + @objc open func notifyDataChanged() + { + calcMinMax() + } + + @objc open func calcMinMaxY(fromX: Double, toX: Double) + { + _dataSets.forEach { $0.calcMinMaxY(fromX: fromX, toX: toX) } + // apply the new data + calcMinMax() + } + + /// calc minimum and maximum y value over all datasets + @objc open func calcMinMax() + { + _yMax = -Double.greatestFiniteMagnitude + _yMin = Double.greatestFiniteMagnitude + _xMax = -Double.greatestFiniteMagnitude + _xMin = Double.greatestFiniteMagnitude + + _dataSets.forEach { calcMinMax(dataSet: $0) } + + _leftAxisMax = -Double.greatestFiniteMagnitude + _leftAxisMin = Double.greatestFiniteMagnitude + _rightAxisMax = -Double.greatestFiniteMagnitude + _rightAxisMin = Double.greatestFiniteMagnitude + + // left axis + let firstLeft = getFirstLeft(dataSets: dataSets) + + if firstLeft !== nil + { + _leftAxisMax = firstLeft!.yMax + _leftAxisMin = firstLeft!.yMin + + for dataSet in _dataSets + { + if dataSet.axisDependency == .left + { + if dataSet.yMin < _leftAxisMin + { + _leftAxisMin = dataSet.yMin + } + + if dataSet.yMax > _leftAxisMax + { + _leftAxisMax = dataSet.yMax + } + } + } + } + + // right axis + let firstRight = getFirstRight(dataSets: dataSets) + + if firstRight !== nil + { + _rightAxisMax = firstRight!.yMax + _rightAxisMin = firstRight!.yMin + + for dataSet in _dataSets + { + if dataSet.axisDependency == .right + { + if dataSet.yMin < _rightAxisMin + { + _rightAxisMin = dataSet.yMin + } + + if dataSet.yMax > _rightAxisMax + { + _rightAxisMax = dataSet.yMax + } + } + } + } + } + + /// Adjusts the current minimum and maximum values based on the provided Entry object. + @objc open func calcMinMax(entry e: ChartDataEntry, axis: YAxis.AxisDependency) + { + if _yMax < e.y + { + _yMax = e.y + } + + if _yMin > e.y + { + _yMin = e.y + } + + if _xMax < e.x + { + _xMax = e.x + } + + if _xMin > e.x + { + _xMin = e.x + } + + if axis == .left + { + if _leftAxisMax < e.y + { + _leftAxisMax = e.y + } + + if _leftAxisMin > e.y + { + _leftAxisMin = e.y + } + } + else + { + if _rightAxisMax < e.y + { + _rightAxisMax = e.y + } + + if _rightAxisMin > e.y + { + _rightAxisMin = e.y + } + } + } + + /// Adjusts the minimum and maximum values based on the given DataSet. + @objc open func calcMinMax(dataSet d: IChartDataSet) + { + if _yMax < d.yMax + { + _yMax = d.yMax + } + + if _yMin > d.yMin + { + _yMin = d.yMin + } + + if _xMax < d.xMax + { + _xMax = d.xMax + } + + if _xMin > d.xMin + { + _xMin = d.xMin + } + + if d.axisDependency == .left + { + if _leftAxisMax < d.yMax + { + _leftAxisMax = d.yMax + } + + if _leftAxisMin > d.yMin + { + _leftAxisMin = d.yMin + } + } + else + { + if _rightAxisMax < d.yMax + { + _rightAxisMax = d.yMax + } + + if _rightAxisMin > d.yMin + { + _rightAxisMin = d.yMin + } + } + } + + /// The number of LineDataSets this object contains + @objc open var dataSetCount: Int + { + return _dataSets.count + } + + /// The smallest y-value the data object contains. + @objc open var yMin: Double + { + return _yMin + } + + @nonobjc + open func getYMin() -> Double + { + return _yMin + } + + @objc open func getYMin(axis: YAxis.AxisDependency) -> Double + { + if axis == .left + { + if _leftAxisMin == Double.greatestFiniteMagnitude + { + return _rightAxisMin + } + else + { + return _leftAxisMin + } + } + else + { + if _rightAxisMin == Double.greatestFiniteMagnitude + { + return _leftAxisMin + } + else + { + return _rightAxisMin + } + } + } + + /// The greatest y-value the data object contains. + @objc open var yMax: Double + { + return _yMax + } + + @nonobjc + open func getYMax() -> Double + { + return _yMax + } + + @objc open func getYMax(axis: YAxis.AxisDependency) -> Double + { + if axis == .left + { + if _leftAxisMax == -Double.greatestFiniteMagnitude + { + return _rightAxisMax + } + else + { + return _leftAxisMax + } + } + else + { + if _rightAxisMax == -Double.greatestFiniteMagnitude + { + return _leftAxisMax + } + else + { + return _rightAxisMax + } + } + } + + /// The minimum x-value the data object contains. + @objc open var xMin: Double + { + return _xMin + } + /// The maximum x-value the data object contains. + @objc open var xMax: Double + { + return _xMax + } + + /// All DataSet objects this ChartData object holds. + @objc open var dataSets: [IChartDataSet] + { + get + { + return _dataSets + } + set + { + _dataSets = newValue + notifyDataChanged() + } + } + + /// Retrieve the index of a ChartDataSet with a specific label from the ChartData. Search can be case sensitive or not. + /// + /// **IMPORTANT: This method does calculations at runtime, do not over-use in performance critical situations.** + /// + /// - Parameters: + /// - dataSets: the DataSet array to search + /// - type: + /// - ignorecase: if true, the search is not case-sensitive + /// - Returns: The index of the DataSet Object with the given label. Sensitive or not. + internal func getDataSetIndexByLabel(_ label: String, ignorecase: Bool) -> Int + { + // TODO: Return nil instead of -1 + if ignorecase + { + return dataSets.firstIndex { + guard let label = $0.label else { return false } + return label.caseInsensitiveCompare(label) == .orderedSame + } ?? -1 + } + else + { + return dataSets.firstIndex { $0.label == label } + ?? -1 + } + } + + /// Get the Entry for a corresponding highlight object + /// + /// - Parameters: + /// - highlight: + /// - Returns: The entry that is highlighted + @objc open func entryForHighlight(_ highlight: Highlight) -> ChartDataEntry? + { + if highlight.dataSetIndex >= dataSets.count + { + return nil + } + else + { + return dataSets[highlight.dataSetIndex].entryForXValue(highlight.x, closestToY: highlight.y) + } + } + + /// **IMPORTANT: This method does calculations at runtime. Use with care in performance critical situations.** + /// + /// - Parameters: + /// - label: + /// - ignorecase: + /// - Returns: The DataSet Object with the given label. Sensitive or not. + @objc open func getDataSetByLabel(_ label: String, ignorecase: Bool) -> IChartDataSet? + { + let index = getDataSetIndexByLabel(label, ignorecase: ignorecase) + + if index < 0 || index >= _dataSets.count + { + return nil + } + else + { + return _dataSets[index] + } + } + + @objc open func getDataSetByIndex(_ index: Int) -> IChartDataSet! + { + if index < 0 || index >= _dataSets.count + { + return nil + } + + return _dataSets[index] + } + + @objc open func addDataSet(_ dataSet: IChartDataSet!) + { + calcMinMax(dataSet: dataSet) + + _dataSets.append(dataSet) + } + + /// Removes the given DataSet from this data object. + /// Also recalculates all minimum and maximum values. + /// + /// - Returns: `true` if a DataSet was removed, `false` ifno DataSet could be removed. + @objc @discardableResult open func removeDataSet(_ dataSet: IChartDataSet) -> Bool + { + guard let i = _dataSets.firstIndex(where: { $0 === dataSet }) else { return false } + return removeDataSetByIndex(i) + } + + /// Removes the DataSet at the given index in the DataSet array from the data object. + /// Also recalculates all minimum and maximum values. + /// + /// - Returns: `true` if a DataSet was removed, `false` ifno DataSet could be removed. + @objc @discardableResult open func removeDataSetByIndex(_ index: Int) -> Bool + { + if index >= _dataSets.count || index < 0 + { + return false + } + + _dataSets.remove(at: index) + + calcMinMax() + + return true + } + + /// Adds an Entry to the DataSet at the specified index. Entries are added to the end of the list. + @objc open func addEntry(_ e: ChartDataEntry, dataSetIndex: Int) + { + if _dataSets.count > dataSetIndex && dataSetIndex >= 0 + { + let set = _dataSets[dataSetIndex] + + if !set.addEntry(e) { return } + + calcMinMax(entry: e, axis: set.axisDependency) + } + else + { + print("ChartData.addEntry() - Cannot add Entry because dataSetIndex too high or too low.", terminator: "\n") + } + } + + /// Removes the given Entry object from the DataSet at the specified index. + @objc @discardableResult open func removeEntry(_ entry: ChartDataEntry, dataSetIndex: Int) -> Bool + { + // entry outofbounds + if dataSetIndex >= _dataSets.count + { + return false + } + + // remove the entry from the dataset + let removed = _dataSets[dataSetIndex].removeEntry(entry) + + if removed + { + calcMinMax() + } + + return removed + } + + /// Removes the Entry object closest to the given xIndex from the ChartDataSet at the + /// specified index. + /// + /// - Returns: `true` if an entry was removed, `false` ifno Entry was found that meets the specified requirements. + @objc @discardableResult open func removeEntry(xValue: Double, dataSetIndex: Int) -> Bool + { + if dataSetIndex >= _dataSets.count + { + return false + } + + if let entry = _dataSets[dataSetIndex].entryForXValue(xValue, closestToY: Double.nan) + { + return removeEntry(entry, dataSetIndex: dataSetIndex) + } + + return false + } + + /// - Returns: The DataSet that contains the provided Entry, or null, if no DataSet contains this entry. + @objc open func getDataSetForEntry(_ e: ChartDataEntry) -> IChartDataSet? + { + return _dataSets.first { $0.entryForXValue(e.x, closestToY: e.y) === e } + } + + /// - Returns: The index of the provided DataSet in the DataSet array of this data object, or -1 if it does not exist. + @objc open func indexOfDataSet(_ dataSet: IChartDataSet) -> Int + { + // TODO: Return nil instead of -1 + return _dataSets.firstIndex { $0 === dataSet } ?? -1 + } + + /// - Returns: The first DataSet from the datasets-array that has it's dependency on the left axis. Returns null if no DataSet with left dependency could be found. + @objc open func getFirstLeft(dataSets: [IChartDataSet]) -> IChartDataSet? + { + return dataSets.first { $0.axisDependency == .left } + } + + /// - Returns: The first DataSet from the datasets-array that has it's dependency on the right axis. Returns null if no DataSet with right dependency could be found. + @objc open func getFirstRight(dataSets: [IChartDataSet]) -> IChartDataSet? + { + return dataSets.first { $0.axisDependency == .right } + } + + /// - Returns: All colors used across all DataSet objects this object represents. + @objc open func getColors() -> [NSUIColor]? + { + // TODO: Don't return nil + return _dataSets.flatMap { $0.colors } + } + + /// Sets a custom IValueFormatter for all DataSets this data object contains. + @objc open func setValueFormatter(_ formatter: IValueFormatter) + { + dataSets.forEach { $0.valueFormatter = formatter } + } + + /// Sets the color of the value-text (color in which the value-labels are drawn) for all DataSets this data object contains. + @objc open func setValueTextColor(_ color: NSUIColor) + { + dataSets.forEach { $0.valueTextColor = color } + } + + /// Sets the font for all value-labels for all DataSets this data object contains. + @objc open func setValueFont(_ font: NSUIFont) + { + dataSets.forEach { $0.valueFont = font } + } + + /// Enables / disables drawing values (value-text) for all DataSets this data object contains. + @objc open func setDrawValues(_ enabled: Bool) + { + dataSets.forEach { $0.drawValuesEnabled = enabled } + } + + /// Enables / disables highlighting values for all DataSets this data object contains. + /// If set to true, this means that values can be highlighted programmatically or by touch gesture. + @objc open var highlightEnabled: Bool + { + get { return dataSets.allSatisfy { $0.highlightEnabled } } + set { dataSets.forEach { $0.highlightEnabled = newValue } } + } + + /// if true, value highlightning is enabled + @objc open var isHighlightEnabled: Bool { return highlightEnabled } + + /// Clears this data object from all DataSets and removes all Entries. + /// Don't forget to invalidate the chart after this. + @objc open func clearValues() + { + dataSets.removeAll(keepingCapacity: false) + notifyDataChanged() + } + + /// Checks if this data object contains the specified DataSet. + /// + /// - Returns: `true` if so, `false` ifnot. + @objc open func contains(dataSet: IChartDataSet) -> Bool + { + return dataSets.contains { $0 === dataSet } + } + + /// The total entry count across all DataSet objects this data object contains. + @objc open var entryCount: Int + { + return _dataSets.reduce(0) { $0 + $1.entryCount } + } + + /// The DataSet object with the maximum number of entries or null if there are no DataSets. + @objc open var maxEntryCountSet: IChartDataSet? + { + return dataSets.max { $0.entryCount < $1.entryCount } + } + + // MARK: - Accessibility + + /// When the data entry labels are generated identifiers, set this property to prepend a string before each identifier + /// + /// For example, if a label is "#3", settings this property to "Item" allows it to be spoken as "Item #3" + @objc open var accessibilityEntryLabelPrefix: String? + + /// When the data entry value requires a unit, use this property to append the string representation of the unit to the value + /// + /// For example, if a value is "44.1", setting this property to "m" allows it to be spoken as "44.1 m" + @objc open var accessibilityEntryLabelSuffix: String? + + /// If the data entry value is a count, set this to true to allow plurals and other grammatical changes + /// **default**: false + @objc open var accessibilityEntryLabelSuffixIsCount: Bool = false +} diff --git a/Pods/Charts/Source/Charts/Data/Implementations/Standard/ChartDataEntry.swift b/Pods/Charts/Source/Charts/Data/Implementations/Standard/ChartDataEntry.swift new file mode 100644 index 00000000..3f29f964 --- /dev/null +++ b/Pods/Charts/Source/Charts/Data/Implementations/Standard/ChartDataEntry.swift @@ -0,0 +1,110 @@ +// +// ChartDataEntry.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation + +open class ChartDataEntry: ChartDataEntryBase, NSCopying +{ + /// the x value + @objc open var x = 0.0 + + public required init() + { + super.init() + } + + /// An Entry represents one single entry in the chart. + /// + /// - Parameters: + /// - x: the x value + /// - y: the y value (the actual value of the entry) + @objc public init(x: Double, y: Double) + { + super.init(y: y) + self.x = x + } + + /// An Entry represents one single entry in the chart. + /// + /// - Parameters: + /// - x: the x value + /// - y: the y value (the actual value of the entry) + /// - data: Space for additional data this Entry represents. + + @objc public convenience init(x: Double, y: Double, data: Any?) + { + self.init(x: x, y: y) + self.data = data + } + + /// An Entry represents one single entry in the chart. + /// + /// - Parameters: + /// - x: the x value + /// - y: the y value (the actual value of the entry) + /// - icon: icon image + + @objc public convenience init(x: Double, y: Double, icon: NSUIImage?) + { + self.init(x: x, y: y) + self.icon = icon + } + + /// An Entry represents one single entry in the chart. + /// + /// - Parameters: + /// - x: the x value + /// - y: the y value (the actual value of the entry) + /// - icon: icon image + /// - data: Space for additional data this Entry represents. + + @objc public convenience init(x: Double, y: Double, icon: NSUIImage?, data: Any?) + { + self.init(x: x, y: y) + self.icon = icon + self.data = data + } + + // MARK: NSObject + + open override var description: String + { + return "ChartDataEntry, x: \(x), y \(y)" + } + + // MARK: NSCopying + + open func copy(with zone: NSZone? = nil) -> Any + { + let copy = type(of: self).init() + + copy.x = x + copy.y = y + copy.data = data + + return copy + } +} + +// MARK: Equatable +extension ChartDataEntry/*: Equatable*/ { + open override func isEqual(_ object: Any?) -> Bool { + guard let object = object as? ChartDataEntry else { return false } + + if self === object + { + return true + } + + return y == object.y + && x == object.x + } +} diff --git a/Pods/Charts/Source/Charts/Data/Implementations/Standard/ChartDataEntryBase.swift b/Pods/Charts/Source/Charts/Data/Implementations/Standard/ChartDataEntryBase.swift new file mode 100644 index 00000000..2c9d0d57 --- /dev/null +++ b/Pods/Charts/Source/Charts/Data/Implementations/Standard/ChartDataEntryBase.swift @@ -0,0 +1,96 @@ +// +// ChartDataEntryBase.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation + +open class ChartDataEntryBase: NSObject +{ + /// the y value + @objc open var y = 0.0 + + /// optional spot for additional data this Entry represents + @objc open var data: Any? + + /// optional icon image + @objc open var icon: NSUIImage? + + public override required init() + { + super.init() + } + + /// An Entry represents one single entry in the chart. + /// + /// - Parameters: + /// - y: the y value (the actual value of the entry) + @objc public init(y: Double) + { + super.init() + + self.y = y + } + + /// - Parameters: + /// - y: the y value (the actual value of the entry) + /// - data: Space for additional data this Entry represents. + + @objc public convenience init(y: Double, data: Any?) + { + self.init(y: y) + + self.data = data + } + + /// - Parameters: + /// - y: the y value (the actual value of the entry) + /// - icon: icon image + + @objc public convenience init(y: Double, icon: NSUIImage?) + { + self.init(y: y) + + self.icon = icon + } + + /// - Parameters: + /// - y: the y value (the actual value of the entry) + /// - icon: icon image + /// - data: Space for additional data this Entry represents. + + @objc public convenience init(y: Double, icon: NSUIImage?, data: Any?) + { + self.init(y: y) + + self.icon = icon + self.data = data + } + + // MARK: NSObject + + open override var description: String + { + return "ChartDataEntryBase, y \(y)" + } +} + +// MARK: Equatable +extension ChartDataEntryBase/*: Equatable*/ { + open override func isEqual(_ object: Any?) -> Bool { + guard let object = object as? ChartDataEntryBase else { return false } + + if self === object + { + return true + } + + return y == object.y + } +} diff --git a/Pods/Charts/Source/Charts/Data/Implementations/Standard/ChartDataSet.swift b/Pods/Charts/Source/Charts/Data/Implementations/Standard/ChartDataSet.swift new file mode 100644 index 00000000..1a9d2353 --- /dev/null +++ b/Pods/Charts/Source/Charts/Data/Implementations/Standard/ChartDataSet.swift @@ -0,0 +1,576 @@ +// +// ChartDataSet.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation + +/// Determines how to round DataSet index values for `ChartDataSet.entryIndex(x, rounding)` when an exact x-value is not found. +@objc +public enum ChartDataSetRounding: Int +{ + case up = 0 + case down = 1 + case closest = 2 +} + +/// The DataSet class represents one group or type of entries (Entry) in the Chart that belong together. +/// It is designed to logically separate different groups of values inside the Chart (e.g. the values for a specific line in the LineChart, or the values of a specific group of bars in the BarChart). +open class ChartDataSet: ChartBaseDataSet +{ + public required init() + { + entries = [] + + super.init() + } + + public override init(label: String?) + { + entries = [] + + super.init(label: label) + } + + @objc public init(entries: [ChartDataEntry]?, label: String?) + { + self.entries = entries ?? [] + + super.init(label: label) + + self.calcMinMax() + } + + @objc public convenience init(entries: [ChartDataEntry]?) + { + self.init(entries: entries, label: "DataSet") + } + + // MARK: - Data functions and accessors + + /// - Note: Calls `notifyDataSetChanged()` after setting a new value. + /// - Returns: The array of y-values that this DataSet represents. + /// the entries that this dataset represents / holds together + @available(*, unavailable, renamed: "entries") + @objc + open var values: [ChartDataEntry] { return entries } + + @objc + open private(set) var entries: [ChartDataEntry] + + /// Used to replace all entries of a data set while retaining styling properties. + /// This is a separate method from a setter on `entries` to encourage usage + /// of `Collection` conformances. + /// + /// - Parameter entries: new entries to replace existing entries in the dataset + @objc + public func replaceEntries(_ entries: [ChartDataEntry]) { + self.entries = entries + notifyDataSetChanged() + } + + /// maximum y-value in the value array + internal var _yMax: Double = -Double.greatestFiniteMagnitude + + /// minimum y-value in the value array + internal var _yMin: Double = Double.greatestFiniteMagnitude + + /// maximum x-value in the value array + internal var _xMax: Double = -Double.greatestFiniteMagnitude + + /// minimum x-value in the value array + internal var _xMin: Double = Double.greatestFiniteMagnitude + + open override func calcMinMax() + { + _yMax = -Double.greatestFiniteMagnitude + _yMin = Double.greatestFiniteMagnitude + _xMax = -Double.greatestFiniteMagnitude + _xMin = Double.greatestFiniteMagnitude + + guard !isEmpty else { return } + + forEach(calcMinMax) + } + + open override func calcMinMaxY(fromX: Double, toX: Double) + { + _yMax = -Double.greatestFiniteMagnitude + _yMin = Double.greatestFiniteMagnitude + + guard !isEmpty else { return } + + let indexFrom = entryIndex(x: fromX, closestToY: Double.nan, rounding: .down) + let indexTo = entryIndex(x: toX, closestToY: Double.nan, rounding: .up) + + guard !(indexTo < indexFrom) else { return } + // only recalculate y + self[indexFrom...indexTo].forEach(calcMinMaxY) + } + + @objc open func calcMinMaxX(entry e: ChartDataEntry) + { + if e.x < _xMin + { + _xMin = e.x + } + if e.x > _xMax + { + _xMax = e.x + } + } + + @objc open func calcMinMaxY(entry e: ChartDataEntry) + { + if e.y < _yMin + { + _yMin = e.y + } + if e.y > _yMax + { + _yMax = e.y + } + } + + /// Updates the min and max x and y value of this DataSet based on the given Entry. + /// + /// - Parameters: + /// - e: + internal func calcMinMax(entry e: ChartDataEntry) + { + calcMinMaxX(entry: e) + calcMinMaxY(entry: e) + } + + /// The minimum y-value this DataSet holds + open override var yMin: Double { return _yMin } + + /// The maximum y-value this DataSet holds + open override var yMax: Double { return _yMax } + + /// The minimum x-value this DataSet holds + open override var xMin: Double { return _xMin } + + /// The maximum x-value this DataSet holds + open override var xMax: Double { return _xMax } + + /// The number of y-values this DataSet represents + @available(*, deprecated, message: "Use `count` instead") + open override var entryCount: Int { return count } + + /// - Throws: out of bounds + /// if `i` is out of bounds, it may throw an out-of-bounds exception + /// - Returns: The entry object found at the given index (not x-value!) + @available(*, deprecated, message: "Use `subscript(index:)` instead.") + open override func entryForIndex(_ i: Int) -> ChartDataEntry? + { + guard i >= startIndex, i < endIndex else { + return nil + } + return self[i] + } + + /// - Parameters: + /// - xValue: the x-value + /// - closestToY: If there are multiple y-values for the specified x-value, + /// - rounding: determine whether to round up/down/closest if there is no Entry matching the provided x-value + /// - Returns: The first Entry object found at the given x-value with binary search. + /// If the no Entry at the specified x-value is found, this method returns the Entry at the closest x-value according to the rounding. + /// nil if no Entry object at that x-value. + open override func entryForXValue( + _ xValue: Double, + closestToY yValue: Double, + rounding: ChartDataSetRounding) -> ChartDataEntry? + { + let index = entryIndex(x: xValue, closestToY: yValue, rounding: rounding) + if index > -1 + { + return self[index] + } + return nil + } + + /// - Parameters: + /// - xValue: the x-value + /// - closestToY: If there are multiple y-values for the specified x-value, + /// - Returns: The first Entry object found at the given x-value with binary search. + /// If the no Entry at the specified x-value is found, this method returns the Entry at the closest x-value. + /// nil if no Entry object at that x-value. + open override func entryForXValue( + _ xValue: Double, + closestToY yValue: Double) -> ChartDataEntry? + { + return entryForXValue(xValue, closestToY: yValue, rounding: .closest) + } + + /// - Returns: All Entry objects found at the given xIndex with binary search. + /// An empty array if no Entry object at that index. + open override func entriesForXValue(_ xValue: Double) -> [ChartDataEntry] + { + var entries = [ChartDataEntry]() + + var low = startIndex + var high = endIndex - 1 + + while low <= high + { + var m = (high + low) / 2 + var entry = self[m] + + // if we have a match + if xValue == entry.x + { + while m > 0 && self[m - 1].x == xValue + { + m -= 1 + } + + high = endIndex + + // loop over all "equal" entries + while m < high + { + entry = self[m] + if entry.x == xValue + { + entries.append(entry) + } + else + { + break + } + + m += 1 + } + + break + } + else + { + if xValue > entry.x + { + low = m + 1 + } + else + { + high = m - 1 + } + } + } + + return entries + } + + /// - Parameters: + /// - xValue: x-value of the entry to search for + /// - closestToY: If there are multiple y-values for the specified x-value, + /// - rounding: Rounding method if exact value was not found + /// - Returns: The array-index of the specified entry. + /// If the no Entry at the specified x-value is found, this method returns the index of the Entry at the closest x-value according to the rounding. + open override func entryIndex( + x xValue: Double, + closestToY yValue: Double, + rounding: ChartDataSetRounding) -> Int + { + var low = startIndex + var high = endIndex - 1 + var closest = high + + while low < high + { + let m = (low + high) / 2 + + let d1 = self[m].x - xValue + let d2 = self[m + 1].x - xValue + let ad1 = abs(d1), ad2 = abs(d2) + + if ad2 < ad1 + { + // [m + 1] is closer to xValue + // Search in an higher place + low = m + 1 + } + else if ad1 < ad2 + { + // [m] is closer to xValue + // Search in a lower place + high = m + } + else + { + // We have multiple sequential x-value with same distance + + if d1 >= 0.0 + { + // Search in a lower place + high = m + } + else if d1 < 0.0 + { + // Search in an higher place + low = m + 1 + } + } + + closest = high + } + + if closest != -1 + { + let closestXValue = self[closest].x + + if rounding == .up + { + // If rounding up, and found x-value is lower than specified x, and we can go upper... + if closestXValue < xValue && closest < endIndex - 1 + { + closest += 1 + } + } + else if rounding == .down + { + // If rounding down, and found x-value is upper than specified x, and we can go lower... + if closestXValue > xValue && closest > 0 + { + closest -= 1 + } + } + + // Search by closest to y-value + if !yValue.isNaN + { + while closest > 0 && self[closest - 1].x == closestXValue + { + closest -= 1 + } + + var closestYValue = self[closest].y + var closestYIndex = closest + + while true + { + closest += 1 + if closest >= endIndex { break } + + let value = self[closest] + + if value.x != closestXValue { break } + if abs(value.y - yValue) <= abs(closestYValue - yValue) + { + closestYValue = yValue + closestYIndex = closest + } + } + + closest = closestYIndex + } + } + + return closest + } + + /// - Parameters: + /// - e: the entry to search for + /// - Returns: The array-index of the specified entry + @available(*, deprecated, message: "Use `firstIndex(of:)` or `lastIndex(of:)`") + open override func entryIndex(entry e: ChartDataEntry) -> Int + { + return firstIndex(of: e) ?? -1 + } + + /// Adds an Entry to the DataSet dynamically. + /// Entries are added to the end of the list. + /// This will also recalculate the current minimum and maximum values of the DataSet and the value-sum. + /// + /// - Parameters: + /// - e: the entry to add + /// - Returns: True + @available(*, deprecated, message: "Use `append(_:)` instead") + open override func addEntry(_ e: ChartDataEntry) -> Bool + { + append(e) + return true + } + + /// Adds an Entry to the DataSet dynamically. + /// Entries are added to their appropriate index respective to it's x-index. + /// This will also recalculate the current minimum and maximum values of the DataSet and the value-sum. + /// + /// - Parameters: + /// - e: the entry to add + /// - Returns: True + open override func addEntryOrdered(_ e: ChartDataEntry) -> Bool + { + calcMinMax(entry: e) + + if let last = last, last.x > e.x + { + var closestIndex = entryIndex(x: e.x, closestToY: e.y, rounding: .up) + while self[closestIndex].x < e.x + { + closestIndex += 1 + } + entries.insert(e, at: closestIndex) + } + else + { + append(e) + } + + return true + } + + @available(*, renamed: "remove(_:)") + open override func removeEntry(_ entry: ChartDataEntry) -> Bool + { + return remove(entry) + } + + /// Removes an Entry from the DataSet dynamically. + /// This will also recalculate the current minimum and maximum values of the DataSet and the value-sum. + /// + /// - Parameters: + /// - entry: the entry to remove + /// - Returns: `true` if the entry was removed successfully, else if the entry does not exist + open func remove(_ entry: ChartDataEntry) -> Bool + { + guard let index = firstIndex(of: entry) else { return false } + _ = remove(at: index) + return true + } + + /// Removes the first Entry (at index 0) of this DataSet from the entries array. + /// + /// - Returns: `true` if successful, `false` if not. + @available(*, deprecated, message: "Use `func removeFirst() -> ChartDataEntry` instead.") + open override func removeFirst() -> Bool + { + let entry: ChartDataEntry? = isEmpty ? nil : removeFirst() + return entry != nil + } + + /// Removes the last Entry (at index size-1) of this DataSet from the entries array. + /// + /// - Returns: `true` if successful, `false` if not. + @available(*, deprecated, message: "Use `func removeLast() -> ChartDataEntry` instead.") + open override func removeLast() -> Bool + { + let entry: ChartDataEntry? = isEmpty ? nil : removeLast() + return entry != nil + } + + /// Removes all values from this DataSet and recalculates min and max value. + @available(*, deprecated, message: "Use `removeAll(keepingCapacity:)` instead.") + open override func clear() + { + removeAll(keepingCapacity: true) + } + + // MARK: - Data functions and accessors + + // MARK: - NSCopying + + open override func copy(with zone: NSZone? = nil) -> Any + { + let copy = super.copy(with: zone) as! ChartDataSet + + copy.entries = entries + copy._yMax = _yMax + copy._yMin = _yMin + copy._xMax = _xMax + copy._xMin = _xMin + + return copy + } +} + +// MARK: MutableCollection +extension ChartDataSet: MutableCollection { + public typealias Index = Int + public typealias Element = ChartDataEntry + + public var startIndex: Index { + return entries.startIndex + } + + public var endIndex: Index { + return entries.endIndex + } + + public func index(after: Index) -> Index { + return entries.index(after: after) + } + + @objc + public subscript(position: Index) -> Element { + get { + // This is intentionally not a safe subscript to mirror + // the behaviour of the built in Swift Collection Types + return entries[position] + } + set { + calcMinMax(entry: newValue) + entries[position] = newValue + } + } +} + +// MARK: RandomAccessCollection +extension ChartDataSet: RandomAccessCollection { + public func index(before: Index) -> Index { + return entries.index(before: before) + } +} + +// MARK: RangeReplaceableCollection +extension ChartDataSet: RangeReplaceableCollection { + public func append(_ newElement: Element) { + calcMinMax(entry: newElement) + entries.append(newElement) + } + + public func remove(at position: Index) -> Element { + let element = entries.remove(at: position) + notifyDataSetChanged() + return element + } + + public func removeFirst() -> Element { + let element = entries.removeFirst() + notifyDataSetChanged() + return element + } + + public func removeFirst(_ n: Int) { + entries.removeFirst(n) + notifyDataSetChanged() + } + + public func removeLast() -> Element { + let element = entries.removeLast() + notifyDataSetChanged() + return element + } + + public func removeLast(_ n: Int) { + entries.removeLast(n) + notifyDataSetChanged() + } + + public func removeSubrange(_ bounds: R) where R : RangeExpression, Index == R.Bound { + entries.removeSubrange(bounds) + notifyDataSetChanged() + } + + @objc + public func removeAll(keepingCapacity keepCapacity: Bool) { + entries.removeAll(keepingCapacity: keepCapacity) + notifyDataSetChanged() + } +} diff --git a/Pods/Charts/Source/Charts/Data/Implementations/Standard/CombinedChartData.swift b/Pods/Charts/Source/Charts/Data/Implementations/Standard/CombinedChartData.swift new file mode 100644 index 00000000..e883c8b7 --- /dev/null +++ b/Pods/Charts/Source/Charts/Data/Implementations/Standard/CombinedChartData.swift @@ -0,0 +1,301 @@ +// +// CombinedChartData.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation + +open class CombinedChartData: BarLineScatterCandleBubbleChartData +{ + private var _lineData: LineChartData! + private var _barData: BarChartData! + private var _scatterData: ScatterChartData! + private var _candleData: CandleChartData! + private var _bubbleData: BubbleChartData! + + public override init() + { + super.init() + } + + public override init(dataSets: [IChartDataSet]?) + { + super.init(dataSets: dataSets) + } + + @objc open var lineData: LineChartData! + { + get + { + return _lineData + } + set + { + _lineData = newValue + notifyDataChanged() + } + } + + @objc open var barData: BarChartData! + { + get + { + return _barData + } + set + { + _barData = newValue + notifyDataChanged() + } + } + + @objc open var scatterData: ScatterChartData! + { + get + { + return _scatterData + } + set + { + _scatterData = newValue + notifyDataChanged() + } + } + + @objc open var candleData: CandleChartData! + { + get + { + return _candleData + } + set + { + _candleData = newValue + notifyDataChanged() + } + } + + @objc open var bubbleData: BubbleChartData! + { + get + { + return _bubbleData + } + set + { + _bubbleData = newValue + notifyDataChanged() + } + } + + open override func calcMinMax() + { + _dataSets.removeAll() + + _yMax = -Double.greatestFiniteMagnitude + _yMin = Double.greatestFiniteMagnitude + _xMax = -Double.greatestFiniteMagnitude + _xMin = Double.greatestFiniteMagnitude + + _leftAxisMax = -Double.greatestFiniteMagnitude + _leftAxisMin = Double.greatestFiniteMagnitude + _rightAxisMax = -Double.greatestFiniteMagnitude + _rightAxisMin = Double.greatestFiniteMagnitude + + let allData = self.allData + + for data in allData + { + data.calcMinMax() + + let sets = data.dataSets + _dataSets.append(contentsOf: sets) + + if data.yMax > _yMax + { + _yMax = data.yMax + } + + if data.yMin < _yMin + { + _yMin = data.yMin + } + + if data.xMax > _xMax + { + _xMax = data.xMax + } + + if data.xMin < _xMin + { + _xMin = data.xMin + } + + for dataset in sets + { + if dataset.axisDependency == .left + { + if dataset.yMax > _leftAxisMax + { + _leftAxisMax = dataset.yMax + } + if dataset.yMin < _leftAxisMin + { + _leftAxisMin = dataset.yMin + } + } + else + { + if dataset.yMax > _rightAxisMax + { + _rightAxisMax = dataset.yMax + } + if dataset.yMin < _rightAxisMin + { + _rightAxisMin = dataset.yMin + } + } + } + } + } + + /// All data objects in row: line-bar-scatter-candle-bubble if not null. + @objc open var allData: [ChartData] + { + var data = [ChartData]() + + if lineData !== nil + { + data.append(lineData) + } + if barData !== nil + { + data.append(barData) + } + if scatterData !== nil + { + data.append(scatterData) + } + if candleData !== nil + { + data.append(candleData) + } + if bubbleData !== nil + { + data.append(bubbleData) + } + + return data + } + + @objc open func dataByIndex(_ index: Int) -> ChartData + { + return allData[index] + } + + open func dataIndex(_ data: ChartData) -> Int? + { + return allData.firstIndex(of: data) + } + + open override func removeDataSet(_ dataSet: IChartDataSet) -> Bool + { + return allData.contains { $0.removeDataSet(dataSet) } + } + + open override func removeDataSetByIndex(_ index: Int) -> Bool + { + print("removeDataSet(index) not supported for CombinedData", terminator: "\n") + return false + } + + open override func removeEntry(_ entry: ChartDataEntry, dataSetIndex: Int) -> Bool + { + print("removeEntry(entry, dataSetIndex) not supported for CombinedData", terminator: "\n") + return false + } + + open override func removeEntry(xValue: Double, dataSetIndex: Int) -> Bool + { + print("removeEntry(xValue, dataSetIndex) not supported for CombinedData", terminator: "\n") + return false + } + + open override func notifyDataChanged() + { + if _lineData !== nil + { + _lineData.notifyDataChanged() + } + if _barData !== nil + { + _barData.notifyDataChanged() + } + if _scatterData !== nil + { + _scatterData.notifyDataChanged() + } + if _candleData !== nil + { + _candleData.notifyDataChanged() + } + if _bubbleData !== nil + { + _bubbleData.notifyDataChanged() + } + + super.notifyDataChanged() // recalculate everything + } + + /// Get the Entry for a corresponding highlight object + /// + /// - Parameters: + /// - highlight: + /// - Returns: The entry that is highlighted + open override func entryForHighlight(_ highlight: Highlight) -> ChartDataEntry? + { + if highlight.dataIndex >= allData.count + { + return nil + } + + let data = dataByIndex(highlight.dataIndex) + + if highlight.dataSetIndex >= data.dataSetCount + { + return nil + } + + // The value of the highlighted entry could be NaN - if we are not interested in highlighting a specific value. + let entries = data.getDataSetByIndex(highlight.dataSetIndex).entriesForXValue(highlight.x) + return entries.first { $0.y == highlight.y || highlight.y.isNaN } + } + + /// Get dataset for highlight + /// + /// - Parameters: + /// - highlight: current highlight + /// - Returns: dataset related to highlight + @objc open func getDataSetByHighlight(_ highlight: Highlight) -> IChartDataSet! + { + if highlight.dataIndex >= allData.count + { + return nil + } + + let data = dataByIndex(highlight.dataIndex) + + if highlight.dataSetIndex >= data.dataSetCount + { + return nil + } + + return data.dataSets[highlight.dataSetIndex] + } +} diff --git a/Pods/Charts/Source/Charts/Data/Implementations/Standard/LineChartData.swift b/Pods/Charts/Source/Charts/Data/Implementations/Standard/LineChartData.swift new file mode 100644 index 00000000..2ebd6b42 --- /dev/null +++ b/Pods/Charts/Source/Charts/Data/Implementations/Standard/LineChartData.swift @@ -0,0 +1,26 @@ +// +// LineChartData.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation + +/// Data object that encapsulates all data associated with a LineChart. +open class LineChartData: ChartData +{ + public override init() + { + super.init() + } + + public override init(dataSets: [IChartDataSet]?) + { + super.init(dataSets: dataSets) + } +} diff --git a/Pods/Charts/Source/Charts/Data/Implementations/Standard/LineChartDataSet.swift b/Pods/Charts/Source/Charts/Data/Implementations/Standard/LineChartDataSet.swift new file mode 100644 index 00000000..b53ddd4d --- /dev/null +++ b/Pods/Charts/Source/Charts/Data/Implementations/Standard/LineChartDataSet.swift @@ -0,0 +1,173 @@ +// +// LineChartDataSet.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + + +open class LineChartDataSet: LineRadarChartDataSet, ILineChartDataSet +{ + @objc(LineChartMode) + public enum Mode: Int + { + case linear + case stepped + case cubicBezier + case horizontalBezier + } + + private func initialize() + { + // default color + circleColors.append(NSUIColor(red: 140.0/255.0, green: 234.0/255.0, blue: 255.0/255.0, alpha: 1.0)) + } + + public required init() + { + super.init() + initialize() + } + + public override init(entries: [ChartDataEntry]?, label: String?) + { + super.init(entries: entries, label: label) + initialize() + } + + // MARK: - Data functions and accessors + + // MARK: - Styling functions and accessors + + /// The drawing mode for this line dataset + /// + /// **default**: Linear + open var mode: Mode = Mode.linear + + private var _cubicIntensity = CGFloat(0.2) + + /// Intensity for cubic lines (min = 0.05, max = 1) + /// + /// **default**: 0.2 + open var cubicIntensity: CGFloat + { + get + { + return _cubicIntensity + } + set + { + _cubicIntensity = newValue.clamped(to: 0.05...1) + } + } + + /// The radius of the drawn circles. + open var circleRadius = CGFloat(8.0) + + /// The hole radius of the drawn circles + open var circleHoleRadius = CGFloat(4.0) + + open var circleColors = [NSUIColor]() + + /// - Returns: The color at the given index of the DataSet's circle-color array. + /// Performs a IndexOutOfBounds check by modulus. + open func getCircleColor(atIndex index: Int) -> NSUIColor? + { + let size = circleColors.count + let index = index % size + if index >= size + { + return nil + } + return circleColors[index] + } + + /// Sets the one and ONLY color that should be used for this DataSet. + /// Internally, this recreates the colors array and adds the specified color. + open func setCircleColor(_ color: NSUIColor) + { + circleColors.removeAll(keepingCapacity: false) + circleColors.append(color) + } + + open func setCircleColors(_ colors: NSUIColor...) + { + circleColors.removeAll(keepingCapacity: false) + circleColors.append(contentsOf: colors) + } + + /// Resets the circle-colors array and creates a new one + open func resetCircleColors(_ index: Int) + { + circleColors.removeAll(keepingCapacity: false) + } + + /// If true, drawing circles is enabled + open var drawCirclesEnabled = true + + /// `true` if drawing circles for this DataSet is enabled, `false` ifnot + open var isDrawCirclesEnabled: Bool { return drawCirclesEnabled } + + /// The color of the inner circle (the circle-hole). + open var circleHoleColor: NSUIColor? = NSUIColor.white + + /// `true` if drawing circles for this DataSet is enabled, `false` ifnot + open var drawCircleHoleEnabled = true + + /// `true` if drawing the circle-holes is enabled, `false` ifnot. + open var isDrawCircleHoleEnabled: Bool { return drawCircleHoleEnabled } + + /// This is how much (in pixels) into the dash pattern are we starting from. + open var lineDashPhase = CGFloat(0.0) + + /// This is the actual dash pattern. + /// I.e. [2, 3] will paint [-- -- ] + /// [1, 3, 4, 2] will paint [- ---- - ---- ] + open var lineDashLengths: [CGFloat]? + + /// Line cap type, default is CGLineCap.Butt + open var lineCapType = CGLineCap.butt + + /// formatter for customizing the position of the fill-line + private var _fillFormatter: IFillFormatter = DefaultFillFormatter() + + /// Sets a custom IFillFormatter to the chart that handles the position of the filled-line for each DataSet. Set this to null to use the default logic. + open var fillFormatter: IFillFormatter? + { + get + { + return _fillFormatter + } + set + { + _fillFormatter = newValue ?? DefaultFillFormatter() + } + } + + // MARK: NSCopying + + open override func copy(with zone: NSZone? = nil) -> Any + { + let copy = super.copy(with: zone) as! LineChartDataSet + copy.circleColors = circleColors + copy.circleHoleColor = circleHoleColor + copy.circleRadius = circleRadius + copy.circleHoleRadius = circleHoleRadius + copy.cubicIntensity = cubicIntensity + copy.lineDashPhase = lineDashPhase + copy.lineDashLengths = lineDashLengths + copy.lineCapType = lineCapType + copy.drawCirclesEnabled = drawCirclesEnabled + copy.drawCircleHoleEnabled = drawCircleHoleEnabled + copy.mode = mode + copy._fillFormatter = _fillFormatter + return copy + } +} diff --git a/Pods/Charts/Source/Charts/Data/Implementations/Standard/LineRadarChartDataSet.swift b/Pods/Charts/Source/Charts/Data/Implementations/Standard/LineRadarChartDataSet.swift new file mode 100644 index 00000000..54a3af69 --- /dev/null +++ b/Pods/Charts/Source/Charts/Data/Implementations/Standard/LineRadarChartDataSet.swift @@ -0,0 +1,85 @@ +// +// LineRadarChartDataSet.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + + +open class LineRadarChartDataSet: LineScatterCandleRadarChartDataSet, ILineRadarChartDataSet +{ + // MARK: - Data functions and accessors + + // MARK: - Styling functions and accessors + + /// The color that is used for filling the line surface area. + private var _fillColor = NSUIColor(red: 140.0/255.0, green: 234.0/255.0, blue: 255.0/255.0, alpha: 1.0) + + /// The color that is used for filling the line surface area. + open var fillColor: NSUIColor + { + get { return _fillColor } + set + { + _fillColor = newValue + fill = nil + } + } + + /// The object that is used for filling the area below the line. + /// **default**: nil + open var fill: Fill? + + /// The alpha value that is used for filling the line surface, + /// **default**: 0.33 + open var fillAlpha = CGFloat(0.33) + + private var _lineWidth = CGFloat(1.0) + + /// line width of the chart (min = 0.0, max = 10) + /// + /// **default**: 1 + open var lineWidth: CGFloat + { + get + { + return _lineWidth + } + set + { + _lineWidth = newValue.clamped(to: 0...10) + } + } + + /// Set to `true` if the DataSet should be drawn filled (surface), and not just as a line. + /// Disabling this will give great performance boost. + /// Please note that this method uses the path clipping for drawing the filled area (with images, gradients and layers). + open var drawFilledEnabled = false + + /// `true` if filled drawing is enabled, `false` ifnot + open var isDrawFilledEnabled: Bool + { + return drawFilledEnabled + } + + // MARK: NSCopying + + open override func copy(with zone: NSZone? = nil) -> Any + { + let copy = super.copy(with: zone) as! LineRadarChartDataSet + copy.fill = fill + copy.fillAlpha = fillAlpha + copy._fillColor = _fillColor + copy._lineWidth = _lineWidth + copy.drawFilledEnabled = drawFilledEnabled + return copy + } + +} diff --git a/Pods/Charts/Source/Charts/Data/Implementations/Standard/LineScatterCandleRadarChartDataSet.swift b/Pods/Charts/Source/Charts/Data/Implementations/Standard/LineScatterCandleRadarChartDataSet.swift new file mode 100644 index 00000000..1c68983b --- /dev/null +++ b/Pods/Charts/Source/Charts/Data/Implementations/Standard/LineScatterCandleRadarChartDataSet.swift @@ -0,0 +1,51 @@ +// +// LineScatterCandleRadarChartDataSet.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation + + +open class LineScatterCandleRadarChartDataSet: BarLineScatterCandleBubbleChartDataSet, ILineScatterCandleRadarChartDataSet +{ + // MARK: - Data functions and accessors + + // MARK: - Styling functions and accessors + + /// Enables / disables the horizontal highlight-indicator. If disabled, the indicator is not drawn. + open var drawHorizontalHighlightIndicatorEnabled = true + + /// Enables / disables the vertical highlight-indicator. If disabled, the indicator is not drawn. + open var drawVerticalHighlightIndicatorEnabled = true + + /// `true` if horizontal highlight indicator lines are enabled (drawn) + open var isHorizontalHighlightIndicatorEnabled: Bool { return drawHorizontalHighlightIndicatorEnabled } + + /// `true` if vertical highlight indicator lines are enabled (drawn) + open var isVerticalHighlightIndicatorEnabled: Bool { return drawVerticalHighlightIndicatorEnabled } + + /// Enables / disables both vertical and horizontal highlight-indicators. + /// :param: enabled + open func setDrawHighlightIndicators(_ enabled: Bool) + { + drawHorizontalHighlightIndicatorEnabled = enabled + drawVerticalHighlightIndicatorEnabled = enabled + } + + // MARK: NSCopying + + open override func copy(with zone: NSZone? = nil) -> Any + { + let copy = super.copy(with: zone) as! LineScatterCandleRadarChartDataSet + copy.drawHorizontalHighlightIndicatorEnabled = drawHorizontalHighlightIndicatorEnabled + copy.drawVerticalHighlightIndicatorEnabled = drawVerticalHighlightIndicatorEnabled + return copy + } + +} diff --git a/Pods/Charts/Source/Charts/Data/Implementations/Standard/PieChartData.swift b/Pods/Charts/Source/Charts/Data/Implementations/Standard/PieChartData.swift new file mode 100644 index 00000000..7f343835 --- /dev/null +++ b/Pods/Charts/Source/Charts/Data/Implementations/Standard/PieChartData.swift @@ -0,0 +1,124 @@ +// +// PieData.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation + +open class PieChartData: ChartData +{ + public override init() + { + super.init() + } + + public override init(dataSets: [IChartDataSet]?) + { + super.init(dataSets: dataSets) + } + + /// All DataSet objects this ChartData object holds. + @objc open override var dataSets: [IChartDataSet] + { + get + { + assert(super.dataSets.count <= 1, "Found multiple data sets while pie chart only allows one") + return super.dataSets + } + set + { + super.dataSets = newValue + } + } + + @objc var dataSet: IPieChartDataSet? + { + get + { + return dataSets.count > 0 ? dataSets[0] as? IPieChartDataSet : nil + } + set + { + if let newValue = newValue + { + dataSets = [newValue] + } + else + { + dataSets = [] + } + } + } + + open override func getDataSetByIndex(_ index: Int) -> IChartDataSet? + { + if index != 0 + { + return nil + } + return super.getDataSetByIndex(index) + } + + open override func getDataSetByLabel(_ label: String, ignorecase: Bool) -> IChartDataSet? + { + if dataSets.count == 0 || dataSets[0].label == nil + { + return nil + } + + if ignorecase + { + if let label = dataSets[0].label, label.caseInsensitiveCompare(label) == .orderedSame + { + return dataSets[0] + } + } + else + { + if label == dataSets[0].label + { + return dataSets[0] + } + } + return nil + } + + open override func entryForHighlight(_ highlight: Highlight) -> ChartDataEntry? + { + return dataSet?.entryForIndex(Int(highlight.x)) + } + + open override func addDataSet(_ d: IChartDataSet!) + { + super.addDataSet(d) + } + + /// Removes the DataSet at the given index in the DataSet array from the data object. + /// Also recalculates all minimum and maximum values. + /// + /// - Returns: `true` if a DataSet was removed, `false` ifno DataSet could be removed. + open override func removeDataSetByIndex(_ index: Int) -> Bool + { + if index >= _dataSets.count || index < 0 + { + return false + } + + return false + } + + /// The total y-value sum across all DataSet objects the this object represents. + @objc open var yValueSum: Double + { + guard let dataSet = dataSet else { return 0.0 } + return (0.. Any + { + let copy = super.copy(with: zone) as! PieChartDataEntry + copy.label = label + return copy + } +} diff --git a/Pods/Charts/Source/Charts/Data/Implementations/Standard/PieChartDataSet.swift b/Pods/Charts/Source/Charts/Data/Implementations/Standard/PieChartDataSet.swift new file mode 100644 index 00000000..ac0e6348 --- /dev/null +++ b/Pods/Charts/Source/Charts/Data/Implementations/Standard/PieChartDataSet.swift @@ -0,0 +1,135 @@ +// +// PieChartDataSet.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + +open class PieChartDataSet: ChartDataSet, IPieChartDataSet +{ + @objc(PieChartValuePosition) + public enum ValuePosition: Int + { + case insideSlice + case outsideSlice + } + + private func initialize() + { + self.valueTextColor = NSUIColor.white + self.valueFont = NSUIFont.systemFont(ofSize: 13.0) + } + + public required init() + { + super.init() + initialize() + } + + public override init(entries: [ChartDataEntry]?, label: String?) + { + super.init(entries: entries, label: label) + initialize() + } + + internal override func calcMinMax(entry e: ChartDataEntry) + { + calcMinMaxY(entry: e) + } + + // MARK: - Styling functions and accessors + + private var _sliceSpace = CGFloat(0.0) + + /// the space in pixels between the pie-slices + /// **default**: 0 + /// **maximum**: 20 + open var sliceSpace: CGFloat + { + get + { + return _sliceSpace + } + set + { + var space = newValue + if space > 20.0 + { + space = 20.0 + } + if space < 0.0 + { + space = 0.0 + } + _sliceSpace = space + } + } + + /// When enabled, slice spacing will be 0.0 when the smallest value is going to be smaller than the slice spacing itself. + open var automaticallyDisableSliceSpacing: Bool = false + + /// indicates the selection distance of a pie slice + open var selectionShift = CGFloat(18.0) + + open var xValuePosition: ValuePosition = .insideSlice + open var yValuePosition: ValuePosition = .insideSlice + + /// When valuePosition is OutsideSlice, indicates line color + open var valueLineColor: NSUIColor? = NSUIColor.black + + /// When valuePosition is OutsideSlice and enabled, line will have the same color as the slice + open var useValueColorForLine: Bool = false + + /// When valuePosition is OutsideSlice, indicates line width + open var valueLineWidth: CGFloat = 1.0 + + /// When valuePosition is OutsideSlice, indicates offset as percentage out of the slice size + open var valueLinePart1OffsetPercentage: CGFloat = 0.75 + + /// When valuePosition is OutsideSlice, indicates length of first half of the line + open var valueLinePart1Length: CGFloat = 0.3 + + /// When valuePosition is OutsideSlice, indicates length of second half of the line + open var valueLinePart2Length: CGFloat = 0.4 + + /// When valuePosition is OutsideSlice, this allows variable line length + open var valueLineVariableLength: Bool = true + + /// the font for the slice-text labels + open var entryLabelFont: NSUIFont? = nil + + /// the color for the slice-text labels + open var entryLabelColor: NSUIColor? = nil + + /// the color for the highlighted sector + open var highlightColor: NSUIColor? = nil + + // MARK: - NSCopying + + open override func copy(with zone: NSZone? = nil) -> Any + { + let copy = super.copy(with: zone) as! PieChartDataSet + copy._sliceSpace = _sliceSpace + copy.automaticallyDisableSliceSpacing = automaticallyDisableSliceSpacing + copy.selectionShift = selectionShift + copy.xValuePosition = xValuePosition + copy.yValuePosition = yValuePosition + copy.valueLineColor = valueLineColor + copy.valueLineWidth = valueLineWidth + copy.valueLinePart1OffsetPercentage = valueLinePart1OffsetPercentage + copy.valueLinePart1Length = valueLinePart1Length + copy.valueLinePart2Length = valueLinePart2Length + copy.valueLineVariableLength = valueLineVariableLength + copy.entryLabelFont = entryLabelFont + copy.entryLabelColor = entryLabelColor + copy.highlightColor = highlightColor + return copy + } +} diff --git a/Pods/Charts/Source/Charts/Data/Implementations/Standard/RadarChartData.swift b/Pods/Charts/Source/Charts/Data/Implementations/Standard/RadarChartData.swift new file mode 100644 index 00000000..31fd7d2b --- /dev/null +++ b/Pods/Charts/Source/Charts/Data/Implementations/Standard/RadarChartData.swift @@ -0,0 +1,46 @@ +// +// RadarChartData.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + + +open class RadarChartData: ChartData +{ + @objc open var highlightColor = NSUIColor(red: 255.0/255.0, green: 187.0/255.0, blue: 115.0/255.0, alpha: 1.0) + @objc open var highlightLineWidth = CGFloat(1.0) + @objc open var highlightLineDashPhase = CGFloat(0.0) + @objc open var highlightLineDashLengths: [CGFloat]? + + /// Sets labels that should be drawn around the RadarChart at the end of each web line. + @objc open var labels = [String]() + + /// Sets the labels that should be drawn around the RadarChart at the end of each web line. + open func setLabels(_ labels: String...) + { + self.labels = labels + } + + public override init() + { + super.init() + } + + public override init(dataSets: [IChartDataSet]?) + { + super.init(dataSets: dataSets) + } + + open override func entryForHighlight(_ highlight: Highlight) -> ChartDataEntry? + { + return getDataSetByIndex(highlight.dataSetIndex)?.entryForIndex(Int(highlight.x)) + } +} diff --git a/Pods/Charts/Source/Charts/Data/Implementations/Standard/RadarChartDataEntry.swift b/Pods/Charts/Source/Charts/Data/Implementations/Standard/RadarChartDataEntry.swift new file mode 100644 index 00000000..e557ba92 --- /dev/null +++ b/Pods/Charts/Source/Charts/Data/Implementations/Standard/RadarChartDataEntry.swift @@ -0,0 +1,54 @@ +// +// RadarChartDataEntry.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + +open class RadarChartDataEntry: ChartDataEntry +{ + public required init() + { + super.init() + } + + /// - Parameters: + /// - value: The value on the y-axis. + @objc public init(value: Double) + { + super.init(x: .nan, y: value) + } + + /// - Parameters: + /// - value: The value on the y-axis. + /// - data: Spot for additional data this Entry represents. + @objc public convenience init(value: Double, data: Any?) + { + self.init(value: value) + self.data = data + } + + // MARK: Data property accessors + + @objc open var value: Double + { + get { return y } + set { y = value } + } + + // MARK: NSCopying + + open override func copy(with zone: NSZone? = nil) -> Any + { + let copy = super.copy(with: zone) as! RadarChartDataEntry + + return copy + } +} diff --git a/Pods/Charts/Source/Charts/Data/Implementations/Standard/RadarChartDataSet.swift b/Pods/Charts/Source/Charts/Data/Implementations/Standard/RadarChartDataSet.swift new file mode 100644 index 00000000..030269d6 --- /dev/null +++ b/Pods/Charts/Source/Charts/Data/Implementations/Standard/RadarChartDataSet.swift @@ -0,0 +1,59 @@ +// +// RadarChartDataSet.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + + +open class RadarChartDataSet: LineRadarChartDataSet, IRadarChartDataSet +{ + private func initialize() + { + self.valueFont = NSUIFont.systemFont(ofSize: 13.0) + } + + public required init() + { + super.init() + initialize() + } + + public required override init(entries: [ChartDataEntry]?, label: String?) + { + super.init(entries: entries, label: label) + initialize() + } + + // MARK: - Data functions and accessors + + // MARK: - Styling functions and accessors + + /// flag indicating whether highlight circle should be drawn or not + /// **default**: false + open var drawHighlightCircleEnabled: Bool = false + + /// `true` if highlight circle should be drawn, `false` ifnot + open var isDrawHighlightCircleEnabled: Bool { return drawHighlightCircleEnabled } + + open var highlightCircleFillColor: NSUIColor? = NSUIColor.white + + /// The stroke color for highlight circle. + /// If `nil`, the color of the dataset is taken. + open var highlightCircleStrokeColor: NSUIColor? + + open var highlightCircleStrokeAlpha: CGFloat = 0.3 + + open var highlightCircleInnerRadius: CGFloat = 3.0 + + open var highlightCircleOuterRadius: CGFloat = 4.0 + + open var highlightCircleStrokeWidth: CGFloat = 2.0 +} diff --git a/Pods/Charts/Source/Charts/Data/Implementations/Standard/ScatterChartData.swift b/Pods/Charts/Source/Charts/Data/Implementations/Standard/ScatterChartData.swift new file mode 100644 index 00000000..e06a6032 --- /dev/null +++ b/Pods/Charts/Source/Charts/Data/Implementations/Standard/ScatterChartData.swift @@ -0,0 +1,34 @@ +// +// ScatterChartData.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + +open class ScatterChartData: BarLineScatterCandleBubbleChartData +{ + public override init() + { + super.init() + } + + public override init(dataSets: [IChartDataSet]?) + { + super.init(dataSets: dataSets) + } + + /// - Returns: The maximum shape-size across all DataSets. + @objc open func getGreatestShapeSize() -> CGFloat + { + return (_dataSets as? [IScatterChartDataSet])? + .max { $0.scatterShapeSize < $1.scatterShapeSize }? + .scatterShapeSize ?? 0 + } +} diff --git a/Pods/Charts/Source/Charts/Data/Implementations/Standard/ScatterChartDataSet.swift b/Pods/Charts/Source/Charts/Data/Implementations/Standard/ScatterChartDataSet.swift new file mode 100644 index 00000000..bc9767a0 --- /dev/null +++ b/Pods/Charts/Source/Charts/Data/Implementations/Standard/ScatterChartDataSet.swift @@ -0,0 +1,78 @@ +// +// ScatterChartDataSet.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + +open class ScatterChartDataSet: LineScatterCandleRadarChartDataSet, IScatterChartDataSet +{ + + @objc(ScatterShape) + public enum Shape: Int + { + case square + case circle + case triangle + case cross + case x + case chevronUp + case chevronDown + } + + /// The size the scatter shape will have + open var scatterShapeSize = CGFloat(10.0) + + /// The radius of the hole in the shape (applies to Square, Circle and Triangle) + /// **default**: 0.0 + open var scatterShapeHoleRadius: CGFloat = 0.0 + + /// Color for the hole in the shape. Setting to `nil` will behave as transparent. + /// **default**: nil + open var scatterShapeHoleColor: NSUIColor? = nil + + /// Sets the ScatterShape this DataSet should be drawn with. + /// This will search for an available IShapeRenderer and set this renderer for the DataSet + @objc open func setScatterShape(_ shape: Shape) + { + self.shapeRenderer = ScatterChartDataSet.renderer(forShape: shape) + } + + /// The IShapeRenderer responsible for rendering this DataSet. + /// This can also be used to set a custom IShapeRenderer aside from the default ones. + /// **default**: `SquareShapeRenderer` + open var shapeRenderer: IShapeRenderer? = SquareShapeRenderer() + + @objc open class func renderer(forShape shape: Shape) -> IShapeRenderer + { + switch shape + { + case .square: return SquareShapeRenderer() + case .circle: return CircleShapeRenderer() + case .triangle: return TriangleShapeRenderer() + case .cross: return CrossShapeRenderer() + case .x: return XShapeRenderer() + case .chevronUp: return ChevronUpShapeRenderer() + case .chevronDown: return ChevronDownShapeRenderer() + } + } + + // MARK: NSCopying + + open override func copy(with zone: NSZone? = nil) -> Any + { + let copy = super.copy(with: zone) as! ScatterChartDataSet + copy.scatterShapeSize = scatterShapeSize + copy.scatterShapeHoleRadius = scatterShapeHoleRadius + copy.scatterShapeHoleColor = scatterShapeHoleColor + copy.shapeRenderer = shapeRenderer + return copy + } +} diff --git a/Pods/Charts/Source/Charts/Data/Interfaces/IBarChartDataSet.swift b/Pods/Charts/Source/Charts/Data/Interfaces/IBarChartDataSet.swift new file mode 100644 index 00000000..b90b4dc0 --- /dev/null +++ b/Pods/Charts/Source/Charts/Data/Interfaces/IBarChartDataSet.swift @@ -0,0 +1,42 @@ +// +// IBarChartDataSet.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + +@objc +public protocol IBarChartDataSet: IBarLineScatterCandleBubbleChartDataSet +{ + // MARK: - Data functions and accessors + + // MARK: - Styling functions and accessors + + /// `true` if this DataSet is stacked (stacksize > 1) or not. + var isStacked: Bool { get } + + /// The maximum number of bars that can be stacked upon another in this DataSet. + var stackSize: Int { get } + + /// the color used for drawing the bar-shadows. The bar shadows is a surface behind the bar that indicates the maximum value + var barShadowColor: NSUIColor { get set } + + /// the width used for drawing borders around the bars. If borderWidth == 0, no border will be drawn. + var barBorderWidth : CGFloat { get set } + + /// the color drawing borders around the bars. + var barBorderColor: NSUIColor { get set } + + /// the alpha value (transparency) that is used for drawing the highlight indicator bar. min = 0.0 (fully transparent), max = 1.0 (fully opaque) + var highlightAlpha: CGFloat { get set } + + /// array of labels used to describe the different values of the stacked bars + var stackLabels: [String] { get set } +} diff --git a/Pods/Charts/Source/Charts/Data/Interfaces/IBarLineScatterCandleBubbleChartDataSet.swift b/Pods/Charts/Source/Charts/Data/Interfaces/IBarLineScatterCandleBubbleChartDataSet.swift new file mode 100644 index 00000000..8af47ff4 --- /dev/null +++ b/Pods/Charts/Source/Charts/Data/Interfaces/IBarLineScatterCandleBubbleChartDataSet.swift @@ -0,0 +1,26 @@ +// +// IBarLineScatterCandleBubbleChartDataSet.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + +@objc +public protocol IBarLineScatterCandleBubbleChartDataSet: IChartDataSet +{ + // MARK: - Data functions and accessors + + // MARK: - Styling functions and accessors + + var highlightColor: NSUIColor { get set } + var highlightLineWidth: CGFloat { get set } + var highlightLineDashPhase: CGFloat { get set } + var highlightLineDashLengths: [CGFloat]? { get set } +} diff --git a/Pods/Charts/Source/Charts/Data/Interfaces/IBubbleChartDataSet.swift b/Pods/Charts/Source/Charts/Data/Interfaces/IBubbleChartDataSet.swift new file mode 100644 index 00000000..10c5d9ee --- /dev/null +++ b/Pods/Charts/Source/Charts/Data/Interfaces/IBubbleChartDataSet.swift @@ -0,0 +1,27 @@ +// +// IBubbleChartDataSet.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + +@objc +public protocol IBubbleChartDataSet: IBarLineScatterCandleBubbleChartDataSet +{ + // MARK: - Data functions and accessors + + var maxSize: CGFloat { get } + var isNormalizeSizeEnabled: Bool { get } + + // MARK: - Styling functions and accessors + + /// Sets/gets the width of the circle that surrounds the bubble when highlighted + var highlightCircleWidth: CGFloat { get set } +} diff --git a/Pods/Charts/Source/Charts/Data/Interfaces/ICandleChartDataSet.swift b/Pods/Charts/Source/Charts/Data/Interfaces/ICandleChartDataSet.swift new file mode 100644 index 00000000..fac88d3b --- /dev/null +++ b/Pods/Charts/Source/Charts/Data/Interfaces/ICandleChartDataSet.swift @@ -0,0 +1,66 @@ +// +// ICandleChartDataSet.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + +@objc +public protocol ICandleChartDataSet: ILineScatterCandleRadarChartDataSet +{ + // MARK: - Data functions and accessors + + // MARK: - Styling functions and accessors + + /// the space that is left out on the left and right side of each candle, + /// **default**: 0.1 (10%), max 0.45, min 0.0 + var barSpace: CGFloat { get set } + + /// should the candle bars show? + /// when false, only "ticks" will show + /// + /// **default**: true + var showCandleBar: Bool { get set } + + /// the width of the candle-shadow-line in pixels. + /// + /// **default**: 3.0 + var shadowWidth: CGFloat { get set } + + /// the color of the shadow line + var shadowColor: NSUIColor? { get set } + + /// use candle color for the shadow + var shadowColorSameAsCandle: Bool { get set } + + /// Is the shadow color same as the candle color? + var isShadowColorSameAsCandle: Bool { get } + + /// color for open == close + var neutralColor: NSUIColor? { get set } + + /// color for open > close + var increasingColor: NSUIColor? { get set } + + /// color for open < close + var decreasingColor: NSUIColor? { get set } + + /// Are increasing values drawn as filled? + var increasingFilled: Bool { get set } + + /// Are increasing values drawn as filled? + var isIncreasingFilled: Bool { get } + + /// Are decreasing values drawn as filled? + var decreasingFilled: Bool { get set } + + /// Are decreasing values drawn as filled? + var isDecreasingFilled: Bool { get } +} diff --git a/Pods/Charts/Source/Charts/Data/Interfaces/IChartDataSet.swift b/Pods/Charts/Source/Charts/Data/Interfaces/IChartDataSet.swift new file mode 100644 index 00000000..849da103 --- /dev/null +++ b/Pods/Charts/Source/Charts/Data/Interfaces/IChartDataSet.swift @@ -0,0 +1,270 @@ +// +// IChartDataSet.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + +@objc +public protocol IChartDataSet +{ + // MARK: - Data functions and accessors + + /// Use this method to tell the data set that the underlying data has changed + func notifyDataSetChanged() + + /// Calculates the minimum and maximum x and y values (_xMin, _xMax, _yMin, _yMax). + func calcMinMax() + + /// Calculates the min and max y-values from the Entry closest to the given fromX to the Entry closest to the given toX value. + /// This is only needed for the autoScaleMinMax feature. + func calcMinMaxY(fromX: Double, toX: Double) + + /// The minimum y-value this DataSet holds + var yMin: Double { get } + + /// The maximum y-value this DataSet holds + var yMax: Double { get } + + /// The minimum x-value this DataSet holds + var xMin: Double { get } + + /// The maximum x-value this DataSet holds + var xMax: Double { get } + + /// The number of y-values this DataSet represents + var entryCount: Int { get } + + /// - Throws: out of bounds + /// if `i` is out of bounds, it may throw an out-of-bounds exception + /// - Returns: The entry object found at the given index (not x-value!) + func entryForIndex(_ i: Int) -> ChartDataEntry? + + /// - Parameters: + /// - xValue: the x-value + /// - closestToY: If there are multiple y-values for the specified x-value, + /// - rounding: determine whether to round up/down/closest if there is no Entry matching the provided x-value + /// - Returns: The first Entry object found at the given x-value with binary search. + /// If the no Entry at the specified x-value is found, this method returns the Entry at the closest x-value according to the rounding. + /// nil if no Entry object at that x-value. + func entryForXValue( + _ xValue: Double, + closestToY yValue: Double, + rounding: ChartDataSetRounding) -> ChartDataEntry? + + /// - Parameters: + /// - xValue: the x-value + /// - closestToY: If there are multiple y-values for the specified x-value, + /// - Returns: The first Entry object found at the given x-value with binary search. + /// If the no Entry at the specified x-value is found, this method returns the Entry at the closest x-value. + /// nil if no Entry object at that x-value. + func entryForXValue( + _ xValue: Double, + closestToY yValue: Double) -> ChartDataEntry? + + /// - Returns: All Entry objects found at the given x-value with binary search. + /// An empty array if no Entry object at that x-value. + func entriesForXValue(_ xValue: Double) -> [ChartDataEntry] + + /// - Parameters: + /// - xValue: x-value of the entry to search for + /// - closestToY: If there are multiple y-values for the specified x-value, + /// - rounding: Rounding method if exact value was not found + /// - Returns: The array-index of the specified entry. + /// If the no Entry at the specified x-value is found, this method returns the index of the Entry at the closest x-value according to the rounding. + func entryIndex( + x xValue: Double, + closestToY yValue: Double, + rounding: ChartDataSetRounding) -> Int + + /// - Parameters: + /// - e: the entry to search for + /// - Returns: The array-index of the specified entry + func entryIndex(entry e: ChartDataEntry) -> Int + + /// Adds an Entry to the DataSet dynamically. + /// + /// *optional feature, can return `false` ifnot implemented* + /// + /// Entries are added to the end of the list. + /// + /// - Parameters: + /// - e: the entry to add + /// - Returns: `true` if the entry was added successfully, `false` ifthis feature is not supported + func addEntry(_ e: ChartDataEntry) -> Bool + + /// Adds an Entry to the DataSet dynamically. + /// Entries are added to their appropriate index in the values array respective to their x-position. + /// This will also recalculate the current minimum and maximum values of the DataSet and the value-sum. + /// + /// *optional feature, can return `false` ifnot implemented* + /// + /// Entries are added to the end of the list. + /// + /// - Parameters: + /// - e: the entry to add + /// - Returns: `true` if the entry was added successfully, `false` ifthis feature is not supported + func addEntryOrdered(_ e: ChartDataEntry) -> Bool + + /// Removes an Entry from the DataSet dynamically. + /// + /// *optional feature, can return `false` ifnot implemented* + /// + /// - Parameters: + /// - entry: the entry to remove + /// - Returns: `true` if the entry was removed successfully, `false` ifthe entry does not exist or if this feature is not supported + func removeEntry(_ entry: ChartDataEntry) -> Bool + + /// Removes the Entry object at the given index in the values array from the DataSet. + /// + /// *optional feature, can return `false` ifnot implemented* + /// + /// - Parameters: + /// - index: the index of the entry to remove + /// - Returns: `true` if the entry was removed successfully, `false` ifthe entry does not exist or if this feature is not supported + func removeEntry(index: Int) -> Bool + + /// Removes the Entry object closest to the given x-value from the DataSet. + /// + /// *optional feature, can return `false` ifnot implemented* + /// + /// - Parameters: + /// - x: the x-value to remove + /// - Returns: `true` if the entry was removed successfully, `false` ifthe entry does not exist or if this feature is not supported + func removeEntry(x: Double) -> Bool + + /// Removes the first Entry (at index 0) of this DataSet from the entries array. + /// + /// *optional feature, can return `false` ifnot implemented* + /// + /// - Returns: `true` if the entry was removed successfully, `false` ifthe entry does not exist or if this feature is not supported + func removeFirst() -> Bool + + /// Removes the last Entry (at index 0) of this DataSet from the entries array. + /// + /// *optional feature, can return `false` ifnot implemented* + /// + /// - Returns: `true` if the entry was removed successfully, `false` ifthe entry does not exist or if this feature is not supported + func removeLast() -> Bool + + /// Checks if this DataSet contains the specified Entry. + /// + /// - Returns: `true` if contains the entry, `false` ifnot. + func contains(_ e: ChartDataEntry) -> Bool + + /// Removes all values from this DataSet and does all necessary recalculations. + /// + /// *optional feature, could throw if not implemented* + func clear() + + // MARK: - Styling functions and accessors + + /// The label string that describes the DataSet. + var label: String? { get } + + /// The axis this DataSet should be plotted against. + var axisDependency: YAxis.AxisDependency { get } + + /// List representing all colors that are used for drawing the actual values for this DataSet + var valueColors: [NSUIColor] { get } + + /// All the colors that are used for this DataSet. + /// Colors are reused as soon as the number of Entries the DataSet represents is higher than the size of the colors array. + var colors: [NSUIColor] { get } + + /// - Returns: The color at the given index of the DataSet's color array. + /// This prevents out-of-bounds by performing a modulus on the color index, so colours will repeat themselves. + func color(atIndex: Int) -> NSUIColor + + func resetColors() + + func addColor(_ color: NSUIColor) + + func setColor(_ color: NSUIColor) + + /// if true, value highlighting is enabled + var highlightEnabled: Bool { get set } + + /// `true` if value highlighting is enabled for this dataset + var isHighlightEnabled: Bool { get } + + /// Custom formatter that is used instead of the auto-formatter if set + var valueFormatter: IValueFormatter? { get set } + + /// `true` if the valueFormatter object of this DataSet is null. + var needsFormatter: Bool { get } + + /// Sets/get a single color for value text. + /// Setting the color clears the colors array and adds a single color. + /// Getting will return the first color in the array. + var valueTextColor: NSUIColor { get set } + + /// - Returns: The color at the specified index that is used for drawing the values inside the chart. Uses modulus internally. + func valueTextColorAt(_ index: Int) -> NSUIColor + + /// the font for the value-text labels + var valueFont: NSUIFont { get set } + + /// The form to draw for this dataset in the legend. + /// + /// Return `.Default` to use the default legend form. + var form: Legend.Form { get } + + /// The form size to draw for this dataset in the legend. + /// + /// Return `NaN` to use the default legend form size. + var formSize: CGFloat { get } + + /// The line width for drawing the form of this dataset in the legend + /// + /// Return `NaN` to use the default legend form line width. + var formLineWidth: CGFloat { get } + + /// Line dash configuration for legend shapes that consist of lines. + /// + /// This is how much (in pixels) into the dash pattern are we starting from. + var formLineDashPhase: CGFloat { get } + + /// Line dash configuration for legend shapes that consist of lines. + /// + /// This is the actual dash pattern. + /// I.e. [2, 3] will paint [-- -- ] + /// [1, 3, 4, 2] will paint [- ---- - ---- ] + var formLineDashLengths: [CGFloat]? { get } + + /// Set this to true to draw y-values on the chart. + /// + /// - Note: For bar and line charts: if `maxVisibleCount` is reached, no values will be drawn even if this is enabled. + var drawValuesEnabled: Bool { get set } + + /// `true` if y-value drawing is enabled, `false` ifnot + var isDrawValuesEnabled: Bool { get } + + /// Set this to true to draw y-icons on the chart + /// + /// - Note: For bar and line charts: if `maxVisibleCount` is reached, no icons will be drawn even if this is enabled. + var drawIconsEnabled: Bool { get set } + + /// Returns true if y-icon drawing is enabled, false if not + var isDrawIconsEnabled: Bool { get } + + /// Offset of icons drawn on the chart. + /// + /// For all charts except Pie and Radar it will be ordinary (x offset, y offset). + /// + /// For Pie and Radar chart it will be (y offset, distance from center offset); so if you want icon to be rendered under value, you should increase X component of CGPoint, and if you want icon to be rendered closet to center, you should decrease height component of CGPoint. + var iconsOffset: CGPoint { get set } + + /// Set the visibility of this DataSet. If not visible, the DataSet will not be drawn to the chart upon refreshing it. + var visible: Bool { get set } + + /// `true` if this DataSet is visible inside the chart, or `false` ifit is currently hidden. + var isVisible: Bool { get } +} diff --git a/Pods/Charts/Source/Charts/Data/Interfaces/ILineChartDataSet.swift b/Pods/Charts/Source/Charts/Data/Interfaces/ILineChartDataSet.swift new file mode 100644 index 00000000..071f2695 --- /dev/null +++ b/Pods/Charts/Source/Charts/Data/Interfaces/ILineChartDataSet.swift @@ -0,0 +1,80 @@ +// +// ILineChartDataSet.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + + +@objc +public protocol ILineChartDataSet: ILineRadarChartDataSet +{ + // MARK: - Data functions and accessors + + // MARK: - Styling functions and accessors + + /// The drawing mode for this line dataset + /// + /// **default**: Linear + var mode: LineChartDataSet.Mode { get set } + + /// Intensity for cubic lines (min = 0.05, max = 1) + /// + /// **default**: 0.2 + var cubicIntensity: CGFloat { get set } + + /// The radius of the drawn circles. + var circleRadius: CGFloat { get set } + + /// The hole radius of the drawn circles. + var circleHoleRadius: CGFloat { get set } + + var circleColors: [NSUIColor] { get set } + + /// - Returns: The color at the given index of the DataSet's circle-color array. + /// Performs a IndexOutOfBounds check by modulus. + func getCircleColor(atIndex: Int) -> NSUIColor? + + /// Sets the one and ONLY color that should be used for this DataSet. + /// Internally, this recreates the colors array and adds the specified color. + func setCircleColor(_ color: NSUIColor) + + /// Resets the circle-colors array and creates a new one + func resetCircleColors(_ index: Int) + + /// If true, drawing circles is enabled + var drawCirclesEnabled: Bool { get set } + + /// `true` if drawing circles for this DataSet is enabled, `false` ifnot + var isDrawCirclesEnabled: Bool { get } + + /// The color of the inner circle (the circle-hole). + var circleHoleColor: NSUIColor? { get set } + + /// `true` if drawing circles for this DataSet is enabled, `false` ifnot + var drawCircleHoleEnabled: Bool { get set } + + /// `true` if drawing the circle-holes is enabled, `false` ifnot. + var isDrawCircleHoleEnabled: Bool { get } + + /// This is how much (in pixels) into the dash pattern are we starting from. + var lineDashPhase: CGFloat { get } + + /// This is the actual dash pattern. + /// I.e. [2, 3] will paint [-- -- ] + /// [1, 3, 4, 2] will paint [- ---- - ---- ] + var lineDashLengths: [CGFloat]? { get set } + + /// Line cap type, default is CGLineCap.Butt + var lineCapType: CGLineCap { get set } + + /// Sets a custom IFillFormatter to the chart that handles the position of the filled-line for each DataSet. Set this to null to use the default logic. + var fillFormatter: IFillFormatter? { get set } +} diff --git a/Pods/Charts/Source/Charts/Data/Interfaces/ILineRadarChartDataSet.swift b/Pods/Charts/Source/Charts/Data/Interfaces/ILineRadarChartDataSet.swift new file mode 100644 index 00000000..d9f8980b --- /dev/null +++ b/Pods/Charts/Source/Charts/Data/Interfaces/ILineRadarChartDataSet.swift @@ -0,0 +1,45 @@ +// +// ILineRadarChartDataSet.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + +@objc +public protocol ILineRadarChartDataSet: ILineScatterCandleRadarChartDataSet +{ + // MARK: - Data functions and accessors + + // MARK: - Styling functions and accessors + + /// The color that is used for filling the line surface area. + var fillColor: NSUIColor { get set } + + /// - Returns: The object that is used for filling the area below the line. + /// **default**: nil + var fill: Fill? { get set } + + /// The alpha value that is used for filling the line surface. + /// **default**: 0.33 + var fillAlpha: CGFloat { get set } + + /// line width of the chart (min = 0.0, max = 10) + /// + /// **default**: 1 + var lineWidth: CGFloat { get set } + + /// Set to `true` if the DataSet should be drawn filled (surface), and not just as a line. + /// Disabling this will give great performance boost. + /// Please note that this method uses the path clipping for drawing the filled area (with images, gradients and layers). + var drawFilledEnabled: Bool { get set } + + /// `true` if filled drawing is enabled, `false` if not + var isDrawFilledEnabled: Bool { get } +} diff --git a/Pods/Charts/Source/Charts/Data/Interfaces/ILineScatterCandleRadarChartDataSet.swift b/Pods/Charts/Source/Charts/Data/Interfaces/ILineScatterCandleRadarChartDataSet.swift new file mode 100644 index 00000000..27c2bca9 --- /dev/null +++ b/Pods/Charts/Source/Charts/Data/Interfaces/ILineScatterCandleRadarChartDataSet.swift @@ -0,0 +1,36 @@ +// +// ILineScatterCandleRadarChartDataSet.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation + +@objc +public protocol ILineScatterCandleRadarChartDataSet: IBarLineScatterCandleBubbleChartDataSet +{ + // MARK: - Data functions and accessors + + // MARK: - Styling functions and accessors + + /// Enables / disables the horizontal highlight-indicator. If disabled, the indicator is not drawn. + var drawHorizontalHighlightIndicatorEnabled: Bool { get set } + + /// Enables / disables the vertical highlight-indicator. If disabled, the indicator is not drawn. + var drawVerticalHighlightIndicatorEnabled: Bool { get set } + + /// `true` if horizontal highlight indicator lines are enabled (drawn) + var isHorizontalHighlightIndicatorEnabled: Bool { get } + + /// `true` if vertical highlight indicator lines are enabled (drawn) + var isVerticalHighlightIndicatorEnabled: Bool { get } + + /// Enables / disables both vertical and horizontal highlight-indicators. + /// :param: enabled + func setDrawHighlightIndicators(_ enabled: Bool) +} diff --git a/Pods/Charts/Source/Charts/Data/Interfaces/IPieChartDataSet.swift b/Pods/Charts/Source/Charts/Data/Interfaces/IPieChartDataSet.swift new file mode 100644 index 00000000..433c08f2 --- /dev/null +++ b/Pods/Charts/Source/Charts/Data/Interfaces/IPieChartDataSet.swift @@ -0,0 +1,64 @@ +// +// IPieChartDataSet.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + +@objc +public protocol IPieChartDataSet: IChartDataSet +{ + // MARK: - Styling functions and accessors + + /// the space in pixels between the pie-slices + /// **default**: 0 + /// **maximum**: 20 + var sliceSpace: CGFloat { get set } + + /// When enabled, slice spacing will be 0.0 when the smallest value is going to be smaller than the slice spacing itself. + var automaticallyDisableSliceSpacing: Bool { get set } + + /// indicates the selection distance of a pie slice + var selectionShift: CGFloat { get set } + + var xValuePosition: PieChartDataSet.ValuePosition { get set } + var yValuePosition: PieChartDataSet.ValuePosition { get set } + + /// When valuePosition is OutsideSlice, indicates line color + var valueLineColor: NSUIColor? { get set } + + /// When valuePosition is OutsideSlice and enabled, line will have the same color as the slice + var useValueColorForLine: Bool { get set } + + /// When valuePosition is OutsideSlice, indicates line width + var valueLineWidth: CGFloat { get set } + + /// When valuePosition is OutsideSlice, indicates offset as percentage out of the slice size + var valueLinePart1OffsetPercentage: CGFloat { get set } + + /// When valuePosition is OutsideSlice, indicates length of first half of the line + var valueLinePart1Length: CGFloat { get set } + + /// When valuePosition is OutsideSlice, indicates length of second half of the line + var valueLinePart2Length: CGFloat { get set } + + /// When valuePosition is OutsideSlice, this allows variable line length + var valueLineVariableLength: Bool { get set } + + /// the font for the slice-text labels + var entryLabelFont: NSUIFont? { get set } + + /// the color for the slice-text labels + var entryLabelColor: NSUIColor? { get set } + + /// get/sets the color for the highlighted sector + var highlightColor: NSUIColor? { get set } + +} diff --git a/Pods/Charts/Source/Charts/Data/Interfaces/IRadarChartDataSet.swift b/Pods/Charts/Source/Charts/Data/Interfaces/IRadarChartDataSet.swift new file mode 100644 index 00000000..2e37b4ff --- /dev/null +++ b/Pods/Charts/Source/Charts/Data/Interfaces/IRadarChartDataSet.swift @@ -0,0 +1,40 @@ +// +// IRadarChartDataSet.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + +@objc +public protocol IRadarChartDataSet: ILineRadarChartDataSet +{ + // MARK: - Data functions and accessors + + // MARK: - Styling functions and accessors + + /// flag indicating whether highlight circle should be drawn or not + var drawHighlightCircleEnabled: Bool { get set } + + var isDrawHighlightCircleEnabled: Bool { get } + + var highlightCircleFillColor: NSUIColor? { get set } + + /// The stroke color for highlight circle. + /// If `nil`, the color of the dataset is taken. + var highlightCircleStrokeColor: NSUIColor? { get set } + + var highlightCircleStrokeAlpha: CGFloat { get set } + + var highlightCircleInnerRadius: CGFloat { get set } + + var highlightCircleOuterRadius: CGFloat { get set } + + var highlightCircleStrokeWidth: CGFloat { get set } +} diff --git a/Pods/Charts/Source/Charts/Data/Interfaces/IScatterChartDataSet.swift b/Pods/Charts/Source/Charts/Data/Interfaces/IScatterChartDataSet.swift new file mode 100644 index 00000000..05651467 --- /dev/null +++ b/Pods/Charts/Source/Charts/Data/Interfaces/IScatterChartDataSet.swift @@ -0,0 +1,36 @@ +// +// IScatterChartDataSet.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + +@objc +public protocol IScatterChartDataSet: ILineScatterCandleRadarChartDataSet +{ + // MARK: - Data functions and accessors + + // MARK: - Styling functions and accessors + + /// The size the scatter shape will have + var scatterShapeSize: CGFloat { get } + + /// - Returns: The radius of the hole in the shape (applies to Square, Circle and Triangle) + /// Set this to <= 0 to remove holes. + /// **default**: 0.0 + var scatterShapeHoleRadius: CGFloat { get } + + /// - Returns: Color for the hole in the shape. Setting to `nil` will behave as transparent. + /// **default**: nil + var scatterShapeHoleColor: NSUIColor? { get } + + /// The IShapeRenderer responsible for rendering this DataSet. + var shapeRenderer: IShapeRenderer? { get } +} diff --git a/Pods/Charts/Source/Charts/Filters/DataApproximator+N.swift b/Pods/Charts/Source/Charts/Filters/DataApproximator+N.swift new file mode 100644 index 00000000..36bbeec4 --- /dev/null +++ b/Pods/Charts/Source/Charts/Filters/DataApproximator+N.swift @@ -0,0 +1,152 @@ +// +// DataApproximator+N.swift +// Charts +// +// Created by M Ivaniushchenko on 9/6/17. +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation + +extension CGPoint { + fileprivate func distanceToLine(from linePoint1: CGPoint, to linePoint2: CGPoint) -> CGFloat { + let dx = linePoint2.x - linePoint1.x + let dy = linePoint2.y - linePoint1.y + + let dividend = abs(dy * self.x - dx * self.y - linePoint1.x * linePoint2.y + linePoint2.x * linePoint1.y) + let divisor = sqrt(dx * dx + dy * dy) + + return dividend / divisor + } +} + +private struct LineAlt { + let start: Int + let end: Int + + var distance: CGFloat = 0 + var index: Int = 0 + + init(start: Int, end: Int, points: [CGPoint]) { + self.start = start + self.end = end + + let startPoint = points[start] + let endPoint = points[end] + + guard (end > start + 1) else { + return + } + + for i in start + 1 ..< end { + let currentPoint = points[i] + + let distance = currentPoint.distanceToLine(from: startPoint, to: endPoint) + + if distance > self.distance { + self.index = i + self.distance = distance + } + } + } +} + +extension LineAlt: Comparable { + static func ==(lhs: LineAlt, rhs: LineAlt) -> Bool { + return (lhs.start == rhs.start) && (lhs.end == rhs.end) && (lhs.index == rhs.index) + } + + static func <(lhs: LineAlt, rhs: LineAlt) -> Bool { + return lhs.distance < rhs.distance + } +} + + +extension DataApproximator { + /// uses the douglas peuker algorithm to reduce the given arraylist of entries to given number of points + /// More algorithm details here - http://psimpl.sourceforge.net/douglas-peucker.html + @objc open class func reduceWithDouglasPeukerN(_ points: [CGPoint], resultCount: Int) -> [CGPoint] + { + // if a shape has 2 or less points it cannot be reduced + if resultCount <= 2 || resultCount >= points.count + { + return points + } + var keep = [Bool](repeating: false, count: points.count) + + // first and last always stay + keep[0] = true + keep[points.count - 1] = true + var currentStoredPoints = 2 + + var queue = [LineAlt]() + let line = LineAlt(start: 0, end: points.count - 1, points: points) + queue.append(line) + + repeat { + let line = queue.popLast()! + + // store the key + keep[line.index] = true + + // check point count tolerance + currentStoredPoints += 1 + + if (currentStoredPoints == resultCount) { + break; + } + + // split the polyline at the key and recurse + let left = LineAlt(start: line.start, end: line.index, points: points) + if (left.index > 0) { + self.insertLine(left, into: &queue) + } + + let right = LineAlt(start: line.index, end: line.end, points: points) + if (right.index > 0) { + self.insertLine(right, into: &queue) + } + + } while !queue.isEmpty + + // create a new array with series, only take the kept ones + let reducedEntries = points.enumerated().compactMap { (index: Int, point: CGPoint) -> CGPoint? in + return keep[index] ? point : nil + } + + return reducedEntries + } + + // Keeps array sorted + private static func insertLine(_ line: LineAlt, into array: inout [LineAlt]) { + let insertionIndex = self.insertionIndex(for: line, into: &array) + array.insert(line, at: insertionIndex) + } + + private static func insertionIndex(for line: LineAlt, into array: inout [LineAlt]) -> Int { + var indices = array.indices + + while !indices.isEmpty { + let midIndex = indices.lowerBound.advanced(by: indices.count / 2) + let midLine = array[midIndex] + + if midLine == line { + return midIndex + } + else if (line < midLine) { + // perform search in left half + indices = indices.lowerBound.. [CGPoint] + { + // if a shape has 2 or less points it cannot be reduced + if tolerance <= 0 || points.count < 3 + { + return points + } + + var keep = [Bool](repeating: false, count: points.count) + + // first and last always stay + keep[0] = true + keep[points.count - 1] = true + + // first and last entry are entry point to recursion + reduceWithDouglasPeuker(points: points, + tolerance: tolerance, + start: 0, + end: points.count - 1, + keep: &keep) + + // create a new array with series, only take the kept ones + return zip(keep, points).compactMap { $0 ? nil : $1 } + } + + /// apply the Douglas-Peucker-Reduction to an array of `CGPoint`s with a given tolerance + /// + /// - Parameters: + /// - points: + /// - tolerance: + /// - start: + /// - end: + open class func reduceWithDouglasPeuker( + points: [CGPoint], + tolerance: CGFloat, + start: Int, + end: Int, + keep: inout [Bool]) + { + if end <= start + 1 + { + // recursion finished + return + } + + var greatestIndex = Int(0) + var greatestDistance = CGFloat(0.0) + + let line = Line(pt1: points[start], pt2: points[end]) + + for i in start + 1 ..< end + { + let distance = line.distance(toPoint: points[i]) + + if distance > greatestDistance + { + greatestDistance = distance + greatestIndex = i + } + } + + if greatestDistance > tolerance + { + // keep max dist point + keep[greatestIndex] = true + + // recursive call + reduceWithDouglasPeuker(points: points, tolerance: tolerance, start: start, end: greatestIndex, keep: &keep) + reduceWithDouglasPeuker(points: points, tolerance: tolerance, start: greatestIndex, end: end, keep: &keep) + } // else don't keep the point... + } + + private class Line + { + var sxey: CGFloat + var exsy: CGFloat + + var dx: CGFloat + var dy: CGFloat + + var length: CGFloat + + init(pt1: CGPoint, pt2: CGPoint) + { + dx = pt1.x - pt2.x + dy = pt1.y - pt2.y + sxey = pt1.x * pt2.y + exsy = pt2.x * pt1.y + length = sqrt(dx * dx + dy * dy) + } + + func distance(toPoint pt: CGPoint) -> CGFloat + { + return abs(dy * pt.x - dx * pt.y + sxey - exsy) / length + } + } +} diff --git a/Pods/Charts/Source/Charts/Formatters/DefaultAxisValueFormatter.swift b/Pods/Charts/Source/Charts/Formatters/DefaultAxisValueFormatter.swift new file mode 100644 index 00000000..85193d0c --- /dev/null +++ b/Pods/Charts/Source/Charts/Formatters/DefaultAxisValueFormatter.swift @@ -0,0 +1,100 @@ +// +// DefaultAxisValueFormatter.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation + +@objc(ChartDefaultAxisValueFormatter) +open class DefaultAxisValueFormatter: NSObject, IAxisValueFormatter +{ + public typealias Block = ( + _ value: Double, + _ axis: AxisBase?) -> String + + @objc open var block: Block? + + @objc open var hasAutoDecimals: Bool = false + + private var _formatter: NumberFormatter? + @objc open var formatter: NumberFormatter? + { + get { return _formatter } + set + { + hasAutoDecimals = false + _formatter = newValue + } + } + + // TODO: Documentation. Especially the nil case + private var _decimals: Int? + open var decimals: Int? + { + get { return _decimals } + set + { + _decimals = newValue + + if let digits = newValue + { + self.formatter?.minimumFractionDigits = digits + self.formatter?.maximumFractionDigits = digits + self.formatter?.usesGroupingSeparator = true + } + } + } + + public override init() + { + super.init() + + self.formatter = NumberFormatter() + hasAutoDecimals = true + } + + @objc public init(formatter: NumberFormatter) + { + super.init() + + self.formatter = formatter + } + + @objc public init(decimals: Int) + { + super.init() + + self.formatter = NumberFormatter() + self.formatter?.usesGroupingSeparator = true + self.decimals = decimals + hasAutoDecimals = true + } + + @objc public init(block: @escaping Block) + { + super.init() + + self.block = block + } + + @objc public static func with(block: @escaping Block) -> DefaultAxisValueFormatter? + { + return DefaultAxisValueFormatter(block: block) + } + + open func stringForValue(_ value: Double, + axis: AxisBase?) -> String + { + if let block = block { + return block(value, axis) + } else { + return formatter?.string(from: NSNumber(floatLiteral: value)) ?? "" + } + } +} diff --git a/Pods/Charts/Source/Charts/Formatters/DefaultFillFormatter.swift b/Pods/Charts/Source/Charts/Formatters/DefaultFillFormatter.swift new file mode 100644 index 00000000..3afadf35 --- /dev/null +++ b/Pods/Charts/Source/Charts/Formatters/DefaultFillFormatter.swift @@ -0,0 +1,58 @@ +// +// DefaultFillFormatter.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + +/// Default formatter that calculates the position of the filled line. +@objc(ChartDefaultFillFormatter) +open class DefaultFillFormatter: NSObject, IFillFormatter +{ + public typealias Block = ( + _ dataSet: ILineChartDataSet, + _ dataProvider: LineChartDataProvider) -> CGFloat + + @objc open var block: Block? + + public override init() { } + + @objc public init(block: @escaping Block) + { + self.block = block + } + + @objc public static func with(block: @escaping Block) -> DefaultFillFormatter? + { + return DefaultFillFormatter(block: block) + } + + open func getFillLinePosition( + dataSet: ILineChartDataSet, + dataProvider: LineChartDataProvider) -> CGFloat + { + guard block == nil else { return block!(dataSet, dataProvider) } + var fillMin: CGFloat = 0.0 + + if dataSet.yMax > 0.0 && dataSet.yMin < 0.0 + { + fillMin = 0.0 + } + else if let data = dataProvider.data + { + let max = data.yMax > 0.0 ? 0.0 : dataProvider.chartYMax + let min = data.yMin < 0.0 ? 0.0 : dataProvider.chartYMin + + fillMin = CGFloat(dataSet.yMin >= 0.0 ? min : max) + } + + return fillMin + } +} diff --git a/Pods/Charts/Source/Charts/Formatters/DefaultValueFormatter.swift b/Pods/Charts/Source/Charts/Formatters/DefaultValueFormatter.swift new file mode 100644 index 00000000..b3fff70a --- /dev/null +++ b/Pods/Charts/Source/Charts/Formatters/DefaultValueFormatter.swift @@ -0,0 +1,103 @@ +// +// DefaultValueFormatter.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation + +@objc(ChartDefaultValueFormatter) +open class DefaultValueFormatter: NSObject, IValueFormatter +{ + public typealias Block = ( + _ value: Double, + _ entry: ChartDataEntry, + _ dataSetIndex: Int, + _ viewPortHandler: ViewPortHandler?) -> String + + @objc open var block: Block? + + @objc open var hasAutoDecimals: Bool = false + + private var _formatter: NumberFormatter? + @objc open var formatter: NumberFormatter? + { + get { return _formatter } + set + { + hasAutoDecimals = false + _formatter = newValue + } + } + + private var _decimals: Int? + open var decimals: Int? + { + get { return _decimals } + set + { + _decimals = newValue + + if let digits = newValue + { + self.formatter?.minimumFractionDigits = digits + self.formatter?.maximumFractionDigits = digits + self.formatter?.usesGroupingSeparator = true + } + } + } + + public override init() + { + super.init() + + self.formatter = NumberFormatter() + hasAutoDecimals = true + } + + @objc public init(formatter: NumberFormatter) + { + super.init() + + self.formatter = formatter + } + + @objc public init(decimals: Int) + { + super.init() + + self.formatter = NumberFormatter() + self.formatter?.usesGroupingSeparator = true + self.decimals = decimals + hasAutoDecimals = true + } + + @objc public init(block: @escaping Block) + { + super.init() + + self.block = block + } + + @objc public static func with(block: @escaping Block) -> DefaultValueFormatter? + { + return DefaultValueFormatter(block: block) + } + + open func stringForValue(_ value: Double, + entry: ChartDataEntry, + dataSetIndex: Int, + viewPortHandler: ViewPortHandler?) -> String + { + if let block = block { + return block(value, entry, dataSetIndex, viewPortHandler) + } else { + return formatter?.string(from: NSNumber(floatLiteral: value)) ?? "" + } + } +} diff --git a/Pods/Charts/Source/Charts/Formatters/IAxisValueFormatter.swift b/Pods/Charts/Source/Charts/Formatters/IAxisValueFormatter.swift new file mode 100644 index 00000000..302eee18 --- /dev/null +++ b/Pods/Charts/Source/Charts/Formatters/IAxisValueFormatter.swift @@ -0,0 +1,30 @@ +// +// IAxisValueFormatter.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation + +/// An interface for providing custom axis Strings. +@objc(IChartAxisValueFormatter) +public protocol IAxisValueFormatter: class +{ + + /// Called when a value from an axis is formatted before being drawn. + /// + /// For performance reasons, avoid excessive calculations and memory allocations inside this method. + /// + /// - Parameters: + /// - value: the value that is currently being drawn + /// - axis: the axis that the value belongs to + /// - Returns: The customized label that is drawn on the x-axis. + func stringForValue(_ value: Double, + axis: AxisBase?) -> String + +} diff --git a/Pods/Charts/Source/Charts/Formatters/IFillFormatter.swift b/Pods/Charts/Source/Charts/Formatters/IFillFormatter.swift new file mode 100644 index 00000000..7b684fd8 --- /dev/null +++ b/Pods/Charts/Source/Charts/Formatters/IFillFormatter.swift @@ -0,0 +1,21 @@ +// +// IFillFormatter.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + +/// Protocol for providing a custom logic to where the filling line of a LineDataSet should end. This of course only works if setFillEnabled(...) is set to true. +@objc(IChartFillFormatter) +public protocol IFillFormatter +{ + /// - Returns: The vertical (y-axis) position where the filled-line of the LineDataSet should end. + func getFillLinePosition(dataSet: ILineChartDataSet, dataProvider: LineChartDataProvider) -> CGFloat +} diff --git a/Pods/Charts/Source/Charts/Formatters/IValueFormatter.swift b/Pods/Charts/Source/Charts/Formatters/IValueFormatter.swift new file mode 100644 index 00000000..53ca7a40 --- /dev/null +++ b/Pods/Charts/Source/Charts/Formatters/IValueFormatter.swift @@ -0,0 +1,36 @@ +// +// IValueFormatter.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation + +/// Interface that allows custom formatting of all values inside the chart before they are drawn to the screen. +/// +/// Simply create your own formatting class and let it implement ValueFormatter. Then override the stringForValue() +/// method and return whatever you want. + +@objc(IChartValueFormatter) +public protocol IValueFormatter: class +{ + + /// Called when a value (from labels inside the chart) is formatted before being drawn. + /// + /// For performance reasons, avoid excessive calculations and memory allocations inside this method. + /// + /// - Parameters: + /// - value: The value to be formatted + /// - dataSetIndex: The index of the DataSet the entry in focus belongs to + /// - viewPortHandler: provides information about the current chart state (scale, translation, ...) + /// - Returns: The formatted label ready to be drawn + func stringForValue(_ value: Double, + entry: ChartDataEntry, + dataSetIndex: Int, + viewPortHandler: ViewPortHandler?) -> String +} diff --git a/Pods/Charts/Source/Charts/Formatters/IndexAxisValueFormatter.swift b/Pods/Charts/Source/Charts/Formatters/IndexAxisValueFormatter.swift new file mode 100644 index 00000000..ae86509d --- /dev/null +++ b/Pods/Charts/Source/Charts/Formatters/IndexAxisValueFormatter.swift @@ -0,0 +1,59 @@ +// +// IndexAxisValueFormatter.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation + +/// This formatter is used for passing an array of x-axis labels, on whole x steps. +@objc(ChartIndexAxisValueFormatter) +open class IndexAxisValueFormatter: NSObject, IAxisValueFormatter +{ + private var _values: [String] = [String]() + private var _valueCount: Int = 0 + + @objc public var values: [String] + { + get + { + return _values + } + set + { + _values = newValue + _valueCount = _values.count + } + } + + public override init() + { + super.init() + + } + + @objc public init(values: [String]) + { + super.init() + + self.values = values + } + + @objc public static func with(values: [String]) -> IndexAxisValueFormatter? + { + return IndexAxisValueFormatter(values: values) + } + + open func stringForValue(_ value: Double, + axis: AxisBase?) -> String + { + let index = Int(value.rounded()) + guard values.indices.contains(index), index == Int(value) else { return "" } + return _values[index] + } +} diff --git a/Pods/Charts/Source/Charts/Highlight/BarHighlighter.swift b/Pods/Charts/Source/Charts/Highlight/BarHighlighter.swift new file mode 100644 index 00000000..da9e6da7 --- /dev/null +++ b/Pods/Charts/Source/Charts/Highlight/BarHighlighter.swift @@ -0,0 +1,108 @@ +// +// BarHighlighter.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + +@objc(BarChartHighlighter) +open class BarHighlighter: ChartHighlighter +{ + open override func getHighlight(x: CGFloat, y: CGFloat) -> Highlight? + { + guard + let barData = (self.chart as? BarChartDataProvider)?.barData, + let high = super.getHighlight(x: x, y: y) + else { return nil } + + let pos = getValsForTouch(x: x, y: y) + + if let set = barData.getDataSetByIndex(high.dataSetIndex) as? IBarChartDataSet, + set.isStacked + { + return getStackedHighlight(high: high, + set: set, + xValue: Double(pos.x), + yValue: Double(pos.y)) + } + else + { + return high + } + } + + internal override func getDistance(x1: CGFloat, y1: CGFloat, x2: CGFloat, y2: CGFloat) -> CGFloat + { + return abs(x1 - x2) + } + + internal override var data: ChartData? + { + return (chart as? BarChartDataProvider)?.barData + } + + /// This method creates the Highlight object that also indicates which value of a stacked BarEntry has been selected. + /// + /// - Parameters: + /// - high: the Highlight to work with looking for stacked values + /// - set: + /// - xIndex: + /// - yValue: + /// - Returns: + @objc open func getStackedHighlight(high: Highlight, + set: IBarChartDataSet, + xValue: Double, + yValue: Double) -> Highlight? + { + guard + let chart = self.chart as? BarLineScatterCandleBubbleChartDataProvider, + let entry = set.entryForXValue(xValue, closestToY: yValue) as? BarChartDataEntry + else { return nil } + + // Not stacked + if entry.yValues == nil + { + return high + } + + guard + let ranges = entry.ranges, + ranges.count > 0 + else { return nil } + + let stackIndex = getClosestStackIndex(ranges: ranges, value: yValue) + let pixel = chart + .getTransformer(forAxis: set.axisDependency) + .pixelForValues(x: high.x, y: ranges[stackIndex].to) + + return Highlight(x: entry.x, + y: entry.y, + xPx: pixel.x, + yPx: pixel.y, + dataSetIndex: high.dataSetIndex, + stackIndex: stackIndex, + axis: high.axis) + } + + /// - Parameters: + /// - entry: + /// - value: + /// - Returns: The index of the closest value inside the values array / ranges (stacked barchart) to the value given as a parameter. + @objc open func getClosestStackIndex(ranges: [Range]?, value: Double) -> Int + { + guard let ranges = ranges else { return 0 } + if let stackIndex = ranges.firstIndex(where: { $0.contains(value) }) { + return stackIndex + } else { + let length = max(ranges.count - 1, 0) + return (value > ranges[length].to) ? length : 0 + } + } +} diff --git a/Pods/Charts/Source/Charts/Highlight/ChartHighlighter.swift b/Pods/Charts/Source/Charts/Highlight/ChartHighlighter.swift new file mode 100644 index 00000000..417ba0d0 --- /dev/null +++ b/Pods/Charts/Source/Charts/Highlight/ChartHighlighter.swift @@ -0,0 +1,180 @@ +// +// ChartHighlighter.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + +open class ChartHighlighter : NSObject, IHighlighter +{ + /// instance of the data-provider + @objc open weak var chart: ChartDataProvider? + + @objc public init(chart: ChartDataProvider) + { + self.chart = chart + } + + open func getHighlight(x: CGFloat, y: CGFloat) -> Highlight? + { + let xVal = Double(getValsForTouch(x: x, y: y).x) + return getHighlight(xValue: xVal, x: x, y: y) + } + + /// - Parameters: + /// - x: + /// - Returns: The corresponding x-pos for a given touch-position in pixels. + @objc open func getValsForTouch(x: CGFloat, y: CGFloat) -> CGPoint + { + guard let chart = self.chart as? BarLineScatterCandleBubbleChartDataProvider else { return .zero } + + // take any transformer to determine the values + return chart.getTransformer(forAxis: .left).valueForTouchPoint(x: x, y: y) + } + + /// - Parameters: + /// - xValue: + /// - x: + /// - y: + /// - Returns: The corresponding ChartHighlight for a given x-value and xy-touch position in pixels. + @objc open func getHighlight(xValue xVal: Double, x: CGFloat, y: CGFloat) -> Highlight? + { + guard let chart = chart else { return nil } + + let closestValues = getHighlights(xValue: xVal, x: x, y: y) + guard !closestValues.isEmpty else { return nil } + + let leftAxisMinDist = getMinimumDistance(closestValues: closestValues, y: y, axis: .left) + let rightAxisMinDist = getMinimumDistance(closestValues: closestValues, y: y, axis: .right) + + let axis: YAxis.AxisDependency = leftAxisMinDist < rightAxisMinDist ? .left : .right + + let detail = closestSelectionDetailByPixel(closestValues: closestValues, x: x, y: y, axis: axis, minSelectionDistance: chart.maxHighlightDistance) + + return detail + } + + /// - Parameters: + /// - xValue: the transformed x-value of the x-touch position + /// - x: touch position + /// - y: touch position + /// - Returns: A list of Highlight objects representing the entries closest to the given xVal. + /// The returned list contains two objects per DataSet (closest rounding up, closest rounding down). + @objc open func getHighlights(xValue: Double, x: CGFloat, y: CGFloat) -> [Highlight] + { + var vals = [Highlight]() + + guard let data = self.data else { return vals } + + for i in 0 ..< data.dataSetCount + { + guard + let dataSet = data.getDataSetByIndex(i), + dataSet.isHighlightEnabled // don't include datasets that cannot be highlighted + else { continue } + + + // extract all y-values from all DataSets at the given x-value. + // some datasets (i.e bubble charts) make sense to have multiple values for an x-value. We'll have to find a way to handle that later on. It's more complicated now when x-indices are floating point. + vals.append(contentsOf: buildHighlights(dataSet: dataSet, dataSetIndex: i, xValue: xValue, rounding: .closest)) + } + + return vals + } + + /// - Returns: An array of `Highlight` objects corresponding to the selected xValue and dataSetIndex. + internal func buildHighlights( + dataSet set: IChartDataSet, + dataSetIndex: Int, + xValue: Double, + rounding: ChartDataSetRounding) -> [Highlight] + { + guard let chart = self.chart as? BarLineScatterCandleBubbleChartDataProvider else { return [] } + + var entries = set.entriesForXValue(xValue) + if entries.count == 0, let closest = set.entryForXValue(xValue, closestToY: .nan, rounding: rounding) + { + // Try to find closest x-value and take all entries for that x-value + entries = set.entriesForXValue(closest.x) + } + + return entries.map { e in + let px = chart.getTransformer(forAxis: set.axisDependency) + .pixelForValues(x: e.x, y: e.y) + + return Highlight(x: e.x, y: e.y, xPx: px.x, yPx: px.y, dataSetIndex: dataSetIndex, axis: set.axisDependency) + } + } + + // - MARK: - Utilities + + /// - Returns: The `ChartHighlight` of the closest value on the x-y cartesian axes + internal func closestSelectionDetailByPixel( + closestValues: [Highlight], + x: CGFloat, + y: CGFloat, + axis: YAxis.AxisDependency?, + minSelectionDistance: CGFloat) -> Highlight? + { + var distance = minSelectionDistance + var closest: Highlight? + + for high in closestValues + { + if axis == nil || high.axis == axis + { + let cDistance = getDistance(x1: x, y1: y, x2: high.xPx, y2: high.yPx) + + if cDistance < distance + { + closest = high + distance = cDistance + } + } + } + + return closest + } + + /// - Returns: The minimum distance from a touch-y-value (in pixels) to the closest y-value (in pixels) that is displayed in the chart. + internal func getMinimumDistance( + closestValues: [Highlight], + y: CGFloat, + axis: YAxis.AxisDependency + ) -> CGFloat { + var distance = CGFloat.greatestFiniteMagnitude + + for high in closestValues where high.axis == axis + { + let tempDistance = abs(getHighlightPos(high: high) - y) + if tempDistance < distance + { + distance = tempDistance + } + } + + return distance + } + + internal func getHighlightPos(high: Highlight) -> CGFloat + { + return high.yPx + } + + internal func getDistance(x1: CGFloat, y1: CGFloat, x2: CGFloat, y2: CGFloat) -> CGFloat + { + return hypot(x1 - x2, y1 - y2) + } + + internal var data: ChartData? + { + return chart?.data + } +} diff --git a/Pods/Charts/Source/Charts/Highlight/CombinedHighlighter.swift b/Pods/Charts/Source/Charts/Highlight/CombinedHighlighter.swift new file mode 100644 index 00000000..7053df09 --- /dev/null +++ b/Pods/Charts/Source/Charts/Highlight/CombinedHighlighter.swift @@ -0,0 +1,70 @@ +// +// CombinedHighlighter.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + +@objc(CombinedChartHighlighter) +open class CombinedHighlighter: ChartHighlighter +{ + /// bar highlighter for supporting stacked highlighting + private var barHighlighter: BarHighlighter? + + @objc public init(chart: CombinedChartDataProvider, barDataProvider: BarChartDataProvider) + { + super.init(chart: chart) + + // if there is BarData, create a BarHighlighter + self.barHighlighter = barDataProvider.barData == nil ? nil : BarHighlighter(chart: barDataProvider) + } + + open override func getHighlights(xValue: Double, x: CGFloat, y: CGFloat) -> [Highlight] + { + var vals = [Highlight]() + + guard + let chart = self.chart as? CombinedChartDataProvider, + let dataObjects = chart.combinedData?.allData + else { return vals } + + for i in 0..= 0 } + + /// Sets the x- and y-position (pixels) where this highlight was last drawn. + @objc open func setDraw(x: CGFloat, y: CGFloat) + { + self.drawX = x + self.drawY = y + } + + /// Sets the x- and y-position (pixels) where this highlight was last drawn. + @objc open func setDraw(pt: CGPoint) + { + self.drawX = pt.x + self.drawY = pt.y + } + + // MARK: NSObject + + open override var description: String + { + return "Highlight, x: \(_x), y: \(_y), dataIndex (combined charts): \(dataIndex), dataSetIndex: \(_dataSetIndex), stackIndex (only stacked barentry): \(_stackIndex)" + } +} + + +// MARK: Equatable +extension Highlight /*: Equatable*/ { + open override func isEqual(_ object: Any?) -> Bool { + guard let object = object as? Highlight else { return false } + + if self === object + { + return true + } + + return _x == object._x + && _y == object._y + && dataIndex == object.dataIndex + && _dataSetIndex == object._dataSetIndex + && _stackIndex == object._stackIndex + } +} diff --git a/Pods/Charts/Source/Charts/Highlight/HorizontalBarHighlighter.swift b/Pods/Charts/Source/Charts/Highlight/HorizontalBarHighlighter.swift new file mode 100644 index 00000000..103d53f9 --- /dev/null +++ b/Pods/Charts/Source/Charts/Highlight/HorizontalBarHighlighter.swift @@ -0,0 +1,63 @@ +// +// HorizontalBarHighlighter.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + +@objc(HorizontalBarChartHighlighter) +open class HorizontalBarHighlighter: BarHighlighter +{ + open override func getHighlight(x: CGFloat, y: CGFloat) -> Highlight? + { + guard let barData = self.chart?.data as? BarChartData else { return nil } + + let pos = getValsForTouch(x: y, y: x) + guard let high = getHighlight(xValue: Double(pos.y), x: y, y: x) else { return nil } + + if let set = barData.getDataSetByIndex(high.dataSetIndex) as? IBarChartDataSet, + set.isStacked + { + return getStackedHighlight(high: high, + set: set, + xValue: Double(pos.y), + yValue: Double(pos.x)) + } + + return high + } + + internal override func buildHighlights( + dataSet set: IChartDataSet, + dataSetIndex: Int, + xValue: Double, + rounding: ChartDataSetRounding) -> [Highlight] + { + guard let chart = self.chart as? BarLineScatterCandleBubbleChartDataProvider else { return [] } + + var entries = set.entriesForXValue(xValue) + if entries.count == 0, let closest = set.entryForXValue(xValue, closestToY: .nan, rounding: rounding) + { + // Try to find closest x-value and take all entries for that x-value + entries = set.entriesForXValue(closest.x) + } + + return entries.map { e in + let px = chart.getTransformer(forAxis: set.axisDependency) + .pixelForValues(x: e.y, y: e.x) + return Highlight(x: e.x, y: e.y, xPx: px.x, yPx: px.y, dataSetIndex: dataSetIndex, axis: set.axisDependency) + } + } + + internal override func getDistance(x1: CGFloat, y1: CGFloat, x2: CGFloat, y2: CGFloat) -> CGFloat + { + return abs(y1 - y2) + } +} diff --git a/Pods/Charts/Source/Charts/Highlight/IHighlighter.swift b/Pods/Charts/Source/Charts/Highlight/IHighlighter.swift new file mode 100644 index 00000000..21ae298c --- /dev/null +++ b/Pods/Charts/Source/Charts/Highlight/IHighlighter.swift @@ -0,0 +1,23 @@ +// +// IHighlighter.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + +@objc(IChartHighlighter) +public protocol IHighlighter: class +{ + /// - Parameters: + /// - x: + /// - y: + /// - Returns: A Highlight object corresponding to the given x- and y- touch positions in pixels. + func getHighlight(x: CGFloat, y: CGFloat) -> Highlight? +} diff --git a/Pods/Charts/Source/Charts/Highlight/PieHighlighter.swift b/Pods/Charts/Source/Charts/Highlight/PieHighlighter.swift new file mode 100644 index 00000000..54bb3d7b --- /dev/null +++ b/Pods/Charts/Source/Charts/Highlight/PieHighlighter.swift @@ -0,0 +1,27 @@ +// +// PieHighlighter.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + +@objc(PieChartHighlighter) +open class PieHighlighter: PieRadarHighlighter +{ + open override func closestHighlight(index: Int, x: CGFloat, y: CGFloat) -> Highlight? + { + guard + let set = chart?.data?.dataSets[0], + let entry = set.entryForIndex(index) + else { return nil } + + return Highlight(x: Double(index), y: entry.y, xPx: x, yPx: y, dataSetIndex: 0, axis: set.axisDependency) + } +} diff --git a/Pods/Charts/Source/Charts/Highlight/PieRadarHighlighter.swift b/Pods/Charts/Source/Charts/Highlight/PieRadarHighlighter.swift new file mode 100644 index 00000000..c55988ab --- /dev/null +++ b/Pods/Charts/Source/Charts/Highlight/PieRadarHighlighter.swift @@ -0,0 +1,61 @@ +// +// PieRadarHighlighter.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + +@objc(PieRadarChartHighlighter) +open class PieRadarHighlighter: ChartHighlighter +{ + open override func getHighlight(x: CGFloat, y: CGFloat) -> Highlight? + { + guard let chart = self.chart as? PieRadarChartViewBase else { return nil } + + let touchDistanceToCenter = chart.distanceToCenter(x: x, y: y) + + // check if a slice was touched + guard touchDistanceToCenter <= chart.radius else + { + // if no slice was touched, highlight nothing + return nil + } + + var angle = chart.angleForPoint(x: x ,y: y) + + if chart is PieChartView + { + angle /= CGFloat(chart.chartAnimator.phaseY) + } + + let index = chart.indexForAngle(angle) + + // check if the index could be found + if index < 0 || index >= chart.data?.maxEntryCountSet?.entryCount ?? 0 + { + return nil + } + else + { + return closestHighlight(index: index, x: x, y: y) + } + + } + + /// - Parameters: + /// - index: + /// - x: + /// - y: + /// - Returns: The closest Highlight object of the given objects based on the touch position inside the chart. + @objc open func closestHighlight(index: Int, x: CGFloat, y: CGFloat) -> Highlight? + { + fatalError("closestHighlight(index, x, y) cannot be called on PieRadarChartHighlighter") + } +} diff --git a/Pods/Charts/Source/Charts/Highlight/RadarHighlighter.swift b/Pods/Charts/Source/Charts/Highlight/RadarHighlighter.swift new file mode 100644 index 00000000..cfaf57ae --- /dev/null +++ b/Pods/Charts/Source/Charts/Highlight/RadarHighlighter.swift @@ -0,0 +1,78 @@ +// +// RadarHighlighter.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + +@objc(RadarChartHighlighter) +open class RadarHighlighter: PieRadarHighlighter +{ + open override func closestHighlight(index: Int, x: CGFloat, y: CGFloat) -> Highlight? + { + guard let chart = self.chart as? RadarChartView else { return nil } + + let highlights = getHighlights(forIndex: index) + + let distanceToCenter = Double(chart.distanceToCenter(x: x, y: y) / chart.factor) + + var closest: Highlight? + var distance = Double.greatestFiniteMagnitude + + for high in highlights + { + let cdistance = abs(high.y - distanceToCenter) + if cdistance < distance + { + closest = high + distance = cdistance + } + } + + return closest + } + + /// - Parameters: + /// - index: + /// - Returns: An array of Highlight objects for the given index. + /// The Highlight objects give information about the value at the selected index and DataSet it belongs to. + internal func getHighlights(forIndex index: Int) -> [Highlight] + { + var vals = [Highlight]() + + guard + let chart = self.chart as? RadarChartView, + let chartData = chart.data + else { return vals } + + let phaseX = chart.chartAnimator.phaseX + let phaseY = chart.chartAnimator.phaseY + let sliceangle = chart.sliceAngle + let factor = chart.factor + + for i in chartData.dataSets.indices + { + guard + let dataSet = chartData.getDataSetByIndex(i), + let entry = dataSet.entryForIndex(index) + else { continue } + + let y = (entry.y - chart.chartYMin) + + let p = chart.centerOffsets.moving(distance: CGFloat(y) * factor * CGFloat(phaseY), + atAngle: sliceangle * CGFloat(index) * CGFloat(phaseX) + chart.rotationAngle) + + let highlight = Highlight(x: Double(index), y: entry.y, xPx: p.x, yPx: p.y, dataSetIndex: i, axis: dataSet.axisDependency) + vals.append(highlight) + } + + return vals + } +} diff --git a/Pods/Charts/Source/Charts/Highlight/Range.swift b/Pods/Charts/Source/Charts/Highlight/Range.swift new file mode 100644 index 00000000..4b7ead10 --- /dev/null +++ b/Pods/Charts/Source/Charts/Highlight/Range.swift @@ -0,0 +1,52 @@ +// +// Range.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation + +@objc(ChartRange) +open class Range: NSObject +{ + @objc open var from: Double + @objc open var to: Double + + @objc public init(from: Double, to: Double) + { + self.from = from + self.to = to + + super.init() + } + + /// - Parameters: + /// - value: + /// - Returns: `true` if this range contains (if the value is in between) the given value, `false` ifnot. + @objc open func contains(_ value: Double) -> Bool + { + if value > from && value <= to + { + return true + } + else + { + return false + } + } + + @objc open func isLarger(_ value: Double) -> Bool + { + return value > to + } + + @objc open func isSmaller(_ value: Double) -> Bool + { + return value < from + } +} diff --git a/Pods/Charts/Source/Charts/Interfaces/BarChartDataProvider.swift b/Pods/Charts/Source/Charts/Interfaces/BarChartDataProvider.swift new file mode 100644 index 00000000..e1d0a8d0 --- /dev/null +++ b/Pods/Charts/Source/Charts/Interfaces/BarChartDataProvider.swift @@ -0,0 +1,23 @@ +// +// BarChartDataProvider.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + +@objc +public protocol BarChartDataProvider: BarLineScatterCandleBubbleChartDataProvider +{ + var barData: BarChartData? { get } + + var isDrawBarShadowEnabled: Bool { get } + var isDrawValueAboveBarEnabled: Bool { get } + var isHighlightFullBarEnabled: Bool { get } +} \ No newline at end of file diff --git a/Pods/Charts/Source/Charts/Interfaces/BarLineScatterCandleBubbleChartDataProvider.swift b/Pods/Charts/Source/Charts/Interfaces/BarLineScatterCandleBubbleChartDataProvider.swift new file mode 100644 index 00000000..fd5c0652 --- /dev/null +++ b/Pods/Charts/Source/Charts/Interfaces/BarLineScatterCandleBubbleChartDataProvider.swift @@ -0,0 +1,23 @@ +// +// BarLineScatterCandleBubbleChartDataProvider.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + +@objc +public protocol BarLineScatterCandleBubbleChartDataProvider: ChartDataProvider +{ + func getTransformer(forAxis: YAxis.AxisDependency) -> Transformer + func isInverted(axis: YAxis.AxisDependency) -> Bool + + var lowestVisibleX: Double { get } + var highestVisibleX: Double { get } +} diff --git a/Pods/Charts/Source/Charts/Interfaces/BubbleChartDataProvider.swift b/Pods/Charts/Source/Charts/Interfaces/BubbleChartDataProvider.swift new file mode 100644 index 00000000..d9fc9e81 --- /dev/null +++ b/Pods/Charts/Source/Charts/Interfaces/BubbleChartDataProvider.swift @@ -0,0 +1,19 @@ +// +// BubbleChartDataProvider.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + +@objc +public protocol BubbleChartDataProvider: BarLineScatterCandleBubbleChartDataProvider +{ + var bubbleData: BubbleChartData? { get } +} \ No newline at end of file diff --git a/Pods/Charts/Source/Charts/Interfaces/CandleChartDataProvider.swift b/Pods/Charts/Source/Charts/Interfaces/CandleChartDataProvider.swift new file mode 100644 index 00000000..6e729ff1 --- /dev/null +++ b/Pods/Charts/Source/Charts/Interfaces/CandleChartDataProvider.swift @@ -0,0 +1,19 @@ +// +// CandleChartDataProvider.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + +@objc +public protocol CandleChartDataProvider: BarLineScatterCandleBubbleChartDataProvider +{ + var candleData: CandleChartData? { get } +} \ No newline at end of file diff --git a/Pods/Charts/Source/Charts/Interfaces/ChartDataProvider.swift b/Pods/Charts/Source/Charts/Interfaces/ChartDataProvider.swift new file mode 100644 index 00000000..531f04b7 --- /dev/null +++ b/Pods/Charts/Source/Charts/Interfaces/ChartDataProvider.swift @@ -0,0 +1,39 @@ +// +// ChartDataProvider.swift +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + +@objc +public protocol ChartDataProvider +{ + /// The minimum x-value of the chart, regardless of zoom or translation. + var chartXMin: Double { get } + + /// The maximum x-value of the chart, regardless of zoom or translation. + var chartXMax: Double { get } + + /// The minimum y-value of the chart, regardless of zoom or translation. + var chartYMin: Double { get } + + /// The maximum y-value of the chart, regardless of zoom or translation. + var chartYMax: Double { get } + + var maxHighlightDistance: CGFloat { get } + + var xRange: Double { get } + + var centerOffsets: CGPoint { get } + + var data: ChartData? { get } + + var maxVisibleCount: Int { get } +} diff --git a/Pods/Charts/Source/Charts/Interfaces/CombinedChartDataProvider.swift b/Pods/Charts/Source/Charts/Interfaces/CombinedChartDataProvider.swift new file mode 100644 index 00000000..e360eedd --- /dev/null +++ b/Pods/Charts/Source/Charts/Interfaces/CombinedChartDataProvider.swift @@ -0,0 +1,19 @@ +// +// CombinedChartDataProvider.swoft +// Charts +// +// Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda +// A port of MPAndroidChart for iOS +// Licensed under Apache License 2.0 +// +// https://github.com/danielgindi/Charts +// + +import Foundation +import CoreGraphics + +@objc +public protocol CombinedChartDataProvider: LineChartDataProvider, BarChartDataProvider, BubbleChartDataProvider, CandleChartDataProvider, ScatterChartDataProvider +{ + var combinedData: CombinedChartData? { get } +} \ No newline at end of file diff --git a/Pods/Charts/Source/Charts/Interfaces/LineChartDataProvider.swift b/Pods/Charts/Source/Charts/Interfaces/LineChartDataProvider.swift new file mode 100644 index 00000000..e6354821 --- /dev/null +++ b/Pods/Charts/Source/Charts/Interfaces/LineChartDataProvider.swift @@ -0,0 +1,21 @@ +// +// LineChartDataProvider.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 LineChartDataProvider: BarLineScatterCandleBubbleChartDataProvider +{ + var lineData: LineChartData? { get } + + func getAxis(_ axis: YAxis.AxisDependency) -> YAxis +} diff --git a/Pods/Charts/Source/Charts/Interfaces/ScatterChartDataProvider.swift b/Pods/Charts/Source/Charts/Interfaces/ScatterChartDataProvider.swift new file mode 100644 index 00000000..050bde74 --- /dev/null +++ b/Pods/Charts/Source/Charts/Interfaces/ScatterChartDataProvider.swift @@ -0,0 +1,19 @@ +// +// ScatterChartDataProvider.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 ScatterChartDataProvider: BarLineScatterCandleBubbleChartDataProvider +{ + var scatterData: ScatterChartData? { get } +} \ No newline at end of file diff --git a/Pods/Charts/Source/Charts/Jobs/AnimatedMoveViewJob.swift b/Pods/Charts/Source/Charts/Jobs/AnimatedMoveViewJob.swift new file mode 100644 index 00000000..7a758221 --- /dev/null +++ b/Pods/Charts/Source/Charts/Jobs/AnimatedMoveViewJob.swift @@ -0,0 +1,33 @@ +// +// AnimatedMoveViewJob.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 AnimatedMoveViewJob: AnimatedViewPortJob +{ + internal override func animationUpdate() + { + guard + let viewPortHandler = viewPortHandler, + let transformer = transformer, + let view = view + else { return } + + var pt = CGPoint( + x: xOrigin + (CGFloat(xValue) - xOrigin) * phase, + y: yOrigin + (CGFloat(yValue) - yOrigin) * phase + ) + + transformer.pointValueToPixel(&pt) + viewPortHandler.centerViewPort(pt: pt, chart: view) + } +} diff --git a/Pods/Charts/Source/Charts/Jobs/AnimatedViewPortJob.swift b/Pods/Charts/Source/Charts/Jobs/AnimatedViewPortJob.swift new file mode 100644 index 00000000..73754566 --- /dev/null +++ b/Pods/Charts/Source/Charts/Jobs/AnimatedViewPortJob.swift @@ -0,0 +1,126 @@ +// +// AnimatedViewPortJob.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 AnimatedViewPortJob: ViewPortJob +{ + internal var phase: CGFloat = 1.0 + internal var xOrigin: CGFloat = 0.0 + internal var yOrigin: CGFloat = 0.0 + + private var _startTime: TimeInterval = 0.0 + private var _displayLink: NSUIDisplayLink! + private var _duration: TimeInterval = 0.0 + private var _endTime: TimeInterval = 0.0 + + private var _easing: ChartEasingFunctionBlock? + + @objc public init( + viewPortHandler: ViewPortHandler, + xValue: Double, + yValue: Double, + transformer: Transformer, + view: ChartViewBase, + xOrigin: CGFloat, + yOrigin: CGFloat, + duration: TimeInterval, + easing: ChartEasingFunctionBlock?) + { + super.init(viewPortHandler: viewPortHandler, + xValue: xValue, + yValue: yValue, + transformer: transformer, + view: view) + + self.xOrigin = xOrigin + self.yOrigin = yOrigin + self._duration = duration + self._easing = easing + } + + deinit + { + stop(finish: false) + } + + open override func doJob() + { + start() + } + + @objc open func start() + { + _startTime = CACurrentMediaTime() + _endTime = _startTime + _duration + _endTime = _endTime > _endTime ? _endTime : _endTime + + updateAnimationPhase(_startTime) + + _displayLink = NSUIDisplayLink(target: self, selector: #selector(animationLoop)) + _displayLink.add(to: .main, forMode: RunLoop.Mode.common) + } + + @objc open func stop(finish: Bool) + { + guard _displayLink != nil else { return } + + _displayLink.remove(from: .main, forMode: RunLoop.Mode.common) + _displayLink = nil + + if finish + { + if phase != 1.0 + { + phase = 1.0 + animationUpdate() + } + + animationEnd() + } + } + + private func updateAnimationPhase(_ currentTime: TimeInterval) + { + let elapsedTime = currentTime - _startTime + let duration = _duration + var elapsed = elapsedTime + + elapsed = min(elapsed, duration) + + phase = CGFloat(_easing?(elapsed, duration) ?? elapsed / duration) + } + + @objc private func animationLoop() + { + let currentTime: TimeInterval = CACurrentMediaTime() + + updateAnimationPhase(currentTime) + + animationUpdate() + + if currentTime >= _endTime + { + stop(finish: true) + } + } + + internal func animationUpdate() + { + // Override this + } + + internal func animationEnd() + { + // Override this + } +} diff --git a/Pods/Charts/Source/Charts/Jobs/AnimatedZoomViewJob.swift b/Pods/Charts/Source/Charts/Jobs/AnimatedZoomViewJob.swift new file mode 100644 index 00000000..4e9d5fd9 --- /dev/null +++ b/Pods/Charts/Source/Charts/Jobs/AnimatedZoomViewJob.swift @@ -0,0 +1,96 @@ +// +// AnimatedZoomViewJob.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 AnimatedZoomViewJob: AnimatedViewPortJob +{ + internal var yAxis: YAxis? + internal var xAxisRange: Double = 0.0 + internal var scaleX: CGFloat = 0.0 + internal var scaleY: CGFloat = 0.0 + internal var zoomOriginX: CGFloat = 0.0 + internal var zoomOriginY: CGFloat = 0.0 + internal var zoomCenterX: CGFloat = 0.0 + internal var zoomCenterY: CGFloat = 0.0 + + @objc public init( + viewPortHandler: ViewPortHandler, + transformer: Transformer, + view: ChartViewBase, + yAxis: YAxis, + xAxisRange: Double, + scaleX: CGFloat, + scaleY: CGFloat, + xOrigin: CGFloat, + yOrigin: CGFloat, + zoomCenterX: CGFloat, + zoomCenterY: CGFloat, + zoomOriginX: CGFloat, + zoomOriginY: CGFloat, + duration: TimeInterval, + easing: ChartEasingFunctionBlock?) + { + super.init(viewPortHandler: viewPortHandler, + xValue: 0.0, + yValue: 0.0, + transformer: transformer, + view: view, + xOrigin: xOrigin, + yOrigin: yOrigin, + duration: duration, + easing: easing) + + self.yAxis = yAxis + self.xAxisRange = xAxisRange + self.scaleX = scaleX + self.scaleY = scaleY + self.zoomCenterX = zoomCenterX + self.zoomCenterY = zoomCenterY + self.zoomOriginX = zoomOriginX + self.zoomOriginY = zoomOriginY + } + + internal override func animationUpdate() + { + guard + let viewPortHandler = viewPortHandler, + let transformer = transformer, + let view = view + else { return } + + let scaleX = xOrigin + (self.scaleX - xOrigin) * phase + let scaleY = yOrigin + (self.scaleY - yOrigin) * phase + + var matrix = viewPortHandler.setZoom(scaleX: scaleX, scaleY: scaleY) + viewPortHandler.refresh(newMatrix: matrix, chart: view, invalidate: false) + + let valsInView = CGFloat(yAxis?.axisRange ?? 0.0) / viewPortHandler.scaleY + let xsInView = CGFloat(xAxisRange) / viewPortHandler.scaleX + + var pt = CGPoint( + x: zoomOriginX + ((zoomCenterX - xsInView / 2.0) - zoomOriginX) * phase, + y: zoomOriginY + ((zoomCenterY + valsInView / 2.0) - zoomOriginY) * phase + ) + + transformer.pointValueToPixel(&pt) + + matrix = viewPortHandler.translate(pt: pt) + viewPortHandler.refresh(newMatrix: matrix, chart: view, invalidate: true) + } + + internal override func animationEnd() + { + (view as? BarLineChartViewBase)?.calculateOffsets() + view?.setNeedsDisplay() + } +} diff --git a/Pods/Charts/Source/Charts/Jobs/MoveViewJob.swift b/Pods/Charts/Source/Charts/Jobs/MoveViewJob.swift new file mode 100644 index 00000000..0b6ca320 --- /dev/null +++ b/Pods/Charts/Source/Charts/Jobs/MoveViewJob.swift @@ -0,0 +1,34 @@ +// +// MoveViewJob.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(MoveChartViewJob) +open class MoveViewJob: ViewPortJob +{ + open override func doJob() + { + guard + let viewPortHandler = viewPortHandler, + let transformer = transformer, + let view = view + else { return } + + var pt = CGPoint( + x: xValue, + y: yValue + ) + + transformer.pointValueToPixel(&pt) + viewPortHandler.centerViewPort(pt: pt, chart: view) + } +} diff --git a/Pods/Charts/Source/Charts/Jobs/ViewPortJob.swift b/Pods/Charts/Source/Charts/Jobs/ViewPortJob.swift new file mode 100644 index 00000000..c52562ed --- /dev/null +++ b/Pods/Charts/Source/Charts/Jobs/ViewPortJob.swift @@ -0,0 +1,46 @@ +// +// ViewPortJob.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 defines a viewport modification job, used for delaying or animating viewport changes +@objc(ChartViewPortJob) +open class ViewPortJob: NSObject +{ + internal var point: CGPoint = CGPoint() + internal weak var viewPortHandler: ViewPortHandler? + internal var xValue: Double = 0.0 + internal var yValue: Double = 0.0 + internal weak var transformer: Transformer? + internal weak var view: ChartViewBase? + + @objc public init( + viewPortHandler: ViewPortHandler, + xValue: Double, + yValue: Double, + transformer: Transformer, + view: ChartViewBase) + { + super.init() + + self.viewPortHandler = viewPortHandler + self.xValue = xValue + self.yValue = yValue + self.transformer = transformer + self.view = view + } + + @objc open func doJob() + { + fatalError("`doJob()` must be overridden by subclasses") + } +} diff --git a/Pods/Charts/Source/Charts/Jobs/ZoomViewJob.swift b/Pods/Charts/Source/Charts/Jobs/ZoomViewJob.swift new file mode 100644 index 00000000..a6a79394 --- /dev/null +++ b/Pods/Charts/Source/Charts/Jobs/ZoomViewJob.swift @@ -0,0 +1,71 @@ +// +// ZoomViewJob.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(ZoomChartViewJob) +open class ZoomViewJob: ViewPortJob +{ + internal var scaleX: CGFloat = 0.0 + internal var scaleY: CGFloat = 0.0 + internal var axisDependency: YAxis.AxisDependency = .left + + @objc public init( + viewPortHandler: ViewPortHandler, + scaleX: CGFloat, + scaleY: CGFloat, + xValue: Double, + yValue: Double, + transformer: Transformer, + axis: YAxis.AxisDependency, + view: ChartViewBase) + { + super.init( + viewPortHandler: viewPortHandler, + xValue: xValue, + yValue: yValue, + transformer: transformer, + view: view) + + self.scaleX = scaleX + self.scaleY = scaleY + self.axisDependency = axis + } + + open override func doJob() + { + guard + let viewPortHandler = viewPortHandler, + let transformer = transformer, + let view = view + else { return } + + var matrix = viewPortHandler.setZoom(scaleX: scaleX, scaleY: scaleY) + viewPortHandler.refresh(newMatrix: matrix, chart: view, invalidate: false) + + let yValsInView = (view as! BarLineChartViewBase).getAxis(axisDependency).axisRange / Double(viewPortHandler.scaleY) + let xValsInView = (view as! BarLineChartViewBase).xAxis.axisRange / Double(viewPortHandler.scaleX) + + var pt = CGPoint( + x: CGFloat(xValue - xValsInView / 2.0), + y: CGFloat(yValue + yValsInView / 2.0) + ) + + transformer.pointValueToPixel(&pt) + + matrix = viewPortHandler.translate(pt: pt) + viewPortHandler.refresh(newMatrix: matrix, chart: view, invalidate: false) + + (view as! BarLineChartViewBase).calculateOffsets() + view.setNeedsDisplay() + } +} diff --git a/Pods/Charts/Source/Charts/Renderers/AxisRendererBase.swift b/Pods/Charts/Source/Charts/Renderers/AxisRendererBase.swift new file mode 100644 index 00000000..302bdf53 --- /dev/null +++ b/Pods/Charts/Source/Charts/Renderers/AxisRendererBase.swift @@ -0,0 +1,218 @@ +// +// AxisRendererBase.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(ChartAxisRendererBase) +open class AxisRendererBase: Renderer +{ + /// base axis this axis renderer works with + @objc open var axis: AxisBase? + + /// transformer to transform values to screen pixels and return + @objc open var transformer: Transformer? + + @objc public init(viewPortHandler: ViewPortHandler, transformer: Transformer?, axis: AxisBase?) + { + super.init(viewPortHandler: viewPortHandler) + + self.transformer = transformer + self.axis = axis + } + + /// Draws the axis labels on the specified context + @objc open func renderAxisLabels(context: CGContext) + { + fatalError("renderAxisLabels() cannot be called on AxisRendererBase") + } + + /// Draws the grid lines belonging to the axis. + @objc open func renderGridLines(context: CGContext) + { + fatalError("renderGridLines() cannot be called on AxisRendererBase") + } + + /// Draws the line that goes alongside the axis. + @objc open func renderAxisLine(context: CGContext) + { + fatalError("renderAxisLine() cannot be called on AxisRendererBase") + } + + /// Draws the LimitLines associated with this axis to the screen. + @objc open func renderLimitLines(context: CGContext) + { + fatalError("renderLimitLines() cannot be called on AxisRendererBase") + } + + /// Computes the axis values. + /// + /// - Parameters: + /// - min: the minimum value in the data object for this axis + /// - max: the maximum value in the data object for this axis + @objc open func computeAxis(min: Double, max: Double, inverted: Bool) + { + var min = min, max = max + + if let transformer = self.transformer + { + // calculate the starting and entry point of the y-labels (depending on zoom / contentrect bounds) + if viewPortHandler.contentWidth > 10.0 && !viewPortHandler.isFullyZoomedOutY + { + let p1 = transformer.valueForTouchPoint(CGPoint(x: viewPortHandler.contentLeft, y: viewPortHandler.contentTop)) + let p2 = transformer.valueForTouchPoint(CGPoint(x: viewPortHandler.contentLeft, y: viewPortHandler.contentBottom)) + + if !inverted + { + min = Double(p2.y) + max = Double(p1.y) + } + else + { + min = Double(p1.y) + max = Double(p2.y) + } + } + } + + computeAxisValues(min: min, max: max) + } + + /// Sets up the axis values. Computes the desired number of labels between the two given extremes. + @objc open func computeAxisValues(min: Double, max: Double) + { + guard let axis = self.axis else { return } + + let yMin = min + let yMax = max + + let labelCount = axis.labelCount + let range = abs(yMax - yMin) + + if labelCount == 0 || range <= 0 || range.isInfinite + { + axis.entries = [Double]() + axis.centeredEntries = [Double]() + return + } + + // Find out how much spacing (in y value space) between axis values + let rawInterval = range / Double(labelCount) + var interval = rawInterval.roundedToNextSignficant() + + // If granularity is enabled, then do not allow the interval to go below specified granularity. + // This is used to avoid repeated values when rounding values for display. + if axis.granularityEnabled + { + interval = interval < axis.granularity ? axis.granularity : interval + } + + // Normalize interval + let intervalMagnitude = pow(10.0, Double(Int(log10(interval)))).roundedToNextSignficant() + let intervalSigDigit = Int(interval / intervalMagnitude) + if intervalSigDigit > 5 + { + // Use one order of magnitude higher, to avoid intervals like 0.9 or 90 + // if it's 0.0 after floor(), we use the old value + interval = floor(10.0 * intervalMagnitude) == 0.0 ? interval : floor(10.0 * intervalMagnitude) + } + + var n = axis.centerAxisLabelsEnabled ? 1 : 0 + + // force label count + if axis.isForceLabelsEnabled + { + interval = Double(range) / Double(labelCount - 1) + + // Ensure stops contains at least n elements. + axis.entries.removeAll(keepingCapacity: true) + axis.entries.reserveCapacity(labelCount) + + var v = yMin + + for _ in 0 ..< labelCount + { + axis.entries.append(v) + v += interval + } + + n = labelCount + } + else + { + // no forced count + + var first = interval == 0.0 ? 0.0 : ceil(yMin / interval) * interval + + if axis.centerAxisLabelsEnabled + { + first -= interval + } + + let last = interval == 0.0 ? 0.0 : (floor(yMax / interval) * interval).nextUp + + if interval != 0.0 && last != first + { + for _ in stride(from: first, through: last, by: interval) + { + n += 1 + } + } + else if last == first && n == 0 + { + n = 1 + } + + // Ensure stops contains at least n elements. + axis.entries.removeAll(keepingCapacity: true) + axis.entries.reserveCapacity(labelCount) + + var f = first + var i = 0 + while i < n + { + if f == 0.0 + { + // Fix for IEEE negative zero case (Where value == -0.0, and 0.0 == -0.0) + f = 0.0 + } + + axis.entries.append(Double(f)) + + f += interval + i += 1 + } + } + + // set decimals + if interval < 1 + { + axis.decimals = Int(ceil(-log10(interval))) + } + else + { + axis.decimals = 0 + } + + if axis.centerAxisLabelsEnabled + { + axis.centeredEntries.reserveCapacity(n) + axis.centeredEntries.removeAll() + + let offset: Double = interval / 2.0 + + for i in 0 ..< n + { + axis.centeredEntries.append(axis.entries[i] + offset) + } + } + } +} diff --git a/Pods/Charts/Source/Charts/Renderers/BarChartRenderer.swift b/Pods/Charts/Source/Charts/Renderers/BarChartRenderer.swift new file mode 100644 index 00000000..6b192051 --- /dev/null +++ b/Pods/Charts/Source/Charts/Renderers/BarChartRenderer.swift @@ -0,0 +1,893 @@ +// +// BarChartRenderer.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 BarChartRenderer: BarLineScatterCandleBubbleRenderer +{ + /// A nested array of elements ordered logically (i.e not in visual/drawing order) for use with VoiceOver + /// + /// Its use is apparent when there are multiple data sets, since we want to read bars in left to right order, + /// irrespective of dataset. However, drawing is done per dataset, so using this array and then flattening it prevents us from needing to + /// re-render for the sake of accessibility. + /// + /// In practise, its structure is: + /// + /// ```` + /// [ + /// [dataset1 element1, dataset2 element1], + /// [dataset1 element2, dataset2 element2], + /// [dataset1 element3, dataset2 element3] + /// ... + /// ] + /// ```` + /// This is done to provide numerical inference across datasets to a screenreader user, in the same way that a sighted individual + /// uses a multi-dataset bar chart. + /// + /// The ````internal```` specifier is to allow subclasses (HorizontalBar) to populate the same array + internal lazy var accessibilityOrderedElements: [[NSUIAccessibilityElement]] = accessibilityCreateEmptyOrderedElements() + + private class Buffer + { + var rects = [CGRect]() + } + + @objc open weak var dataProvider: BarChartDataProvider? + + @objc public init(dataProvider: BarChartDataProvider, animator: Animator, viewPortHandler: ViewPortHandler) + { + super.init(animator: animator, viewPortHandler: viewPortHandler) + + self.dataProvider = dataProvider + } + + // [CGRect] per dataset + private var _buffers = [Buffer]() + + open override func initBuffers() + { + if let barData = dataProvider?.barData + { + // Matche buffers count to dataset count + if _buffers.count != barData.dataSetCount + { + while _buffers.count < barData.dataSetCount + { + _buffers.append(Buffer()) + } + while _buffers.count > barData.dataSetCount + { + _buffers.removeLast() + } + } + + for i in stride(from: 0, to: barData.dataSetCount, by: 1) + { + let set = barData.dataSets[i] as! IBarChartDataSet + let size = set.entryCount * (set.isStacked ? set.stackSize : 1) + if _buffers[i].rects.count != size + { + _buffers[i].rects = [CGRect](repeating: CGRect(), count: size) + } + } + } + else + { + _buffers.removeAll() + } + } + + private func prepareBuffer(dataSet: IBarChartDataSet, index: Int) + { + guard + let dataProvider = dataProvider, + let barData = dataProvider.barData + else { return } + + let barWidthHalf = barData.barWidth / 2.0 + + let buffer = _buffers[index] + var bufferIndex = 0 + let containsStacks = dataSet.isStacked + + let isInverted = dataProvider.isInverted(axis: dataSet.axisDependency) + let phaseY = animator.phaseY + var barRect = CGRect() + var x: Double + var y: Double + + + for i in stride(from: 0, to: min(Int(ceil(Double(dataSet.entryCount) * animator.phaseX)), dataSet.entryCount), by: 1) + { + guard let e = dataSet.entryForIndex(i) as? BarChartDataEntry else { continue } + + let vals = e.yValues + + x = e.x + y = e.y + + if !containsStacks || vals == nil + { + let left = CGFloat(x - barWidthHalf) + let right = CGFloat(x + barWidthHalf) + var top = isInverted + ? (y <= 0.0 ? CGFloat(y) : 0) + : (y >= 0.0 ? CGFloat(y) : 0) + var bottom = isInverted + ? (y >= 0.0 ? CGFloat(y) : 0) + : (y <= 0.0 ? CGFloat(y) : 0) + + /* When drawing each bar, the renderer actually draws each bar from 0 to the required value. + * This drawn bar is then clipped to the visible chart rect in BarLineChartViewBase's draw(rect:) using clipDataToContent. + * While this works fine when calculating the bar rects for drawing, it causes the accessibilityFrames to be oversized in some cases. + * This offset attempts to undo that unnecessary drawing when calculating barRects + * + * +---------------------------------------------------------------+---------------------------------------------------------------+ + * | Situation 1: (!inverted && y >= 0) | Situation 3: (inverted && y >= 0) | + * | | | + * | y -> +--+ <- top | 0 -> ---+--+---+--+------ <- top | + * | |//| } topOffset = y - max | | | |//| } topOffset = min | + * | max -> +---------+--+----+ <- top - topOffset | min -> +--+--+---+--+----+ <- top + topOffset | + * | | +--+ |//| | | | | | |//| | | + * | | | | |//| | | | +--+ |//| | | + * | | | | |//| | | | |//| | | + * | min -> +--+--+---+--+----+ <- bottom + bottomOffset | max -> +---------+--+----+ <- bottom - bottomOffset | + * | | | |//| } bottomOffset = min | |//| } bottomOffset = y - max | + * | 0 -> ---+--+---+--+----- <- bottom | y -> +--+ <- bottom | + * | | | + * +---------------------------------------------------------------+---------------------------------------------------------------+ + * | Situation 2: (!inverted && y < 0) | Situation 4: (inverted && y < 0) | + * | | | + * | 0 -> ---+--+---+--+----- <- top | y -> +--+ <- top | + * | | | |//| } topOffset = -max | |//| } topOffset = min - y | + * | max -> +--+--+---+--+----+ <- top - topOffset | min -> +---------+--+----+ <- top + topOffset | + * | | | | |//| | | | +--+ |//| | | + * | | +--+ |//| | | | | | |//| | | + * | | |//| | | | | | |//| | | + * | min -> +---------+--+----+ <- bottom + bottomOffset | max -> +--+--+---+--+----+ <- bottom - bottomOffset | + * | |//| } bottomOffset = min - y | | | |//| } bottomOffset = -max | + * | y -> +--+ <- bottom | 0 -> ---+--+---+--+------- <- bottom | + * | | | + * +---------------------------------------------------------------+---------------------------------------------------------------+ + */ + var topOffset: CGFloat = 0.0 + var bottomOffset: CGFloat = 0.0 + if let offsetView = dataProvider as? BarChartView + { + let offsetAxis = offsetView.getAxis(dataSet.axisDependency) + if y >= 0 + { + // situation 1 + if offsetAxis.axisMaximum < y + { + topOffset = CGFloat(y - offsetAxis.axisMaximum) + } + if offsetAxis.axisMinimum > 0 + { + bottomOffset = CGFloat(offsetAxis.axisMinimum) + } + } + else // y < 0 + { + //situation 2 + if offsetAxis.axisMaximum < 0 + { + topOffset = CGFloat(offsetAxis.axisMaximum * -1) + } + if offsetAxis.axisMinimum > y + { + bottomOffset = CGFloat(offsetAxis.axisMinimum - y) + } + } + if isInverted + { + // situation 3 and 4 + // exchange topOffset/bottomOffset based on 1 and 2 + // see diagram above + (topOffset, bottomOffset) = (bottomOffset, topOffset) + } + } + //apply offset + top = isInverted ? top + topOffset : top - topOffset + bottom = isInverted ? bottom - bottomOffset : bottom + bottomOffset + + // multiply the height of the rect with the phase + // explicitly add 0 + topOffset to indicate this is changed after adding accessibility support (#3650, #3520) + if top > 0 + topOffset + { + top *= CGFloat(phaseY) + } + else + { + bottom *= CGFloat(phaseY) + } + + barRect.origin.x = left + barRect.origin.y = top + barRect.size.width = right - left + barRect.size.height = bottom - top + buffer.rects[bufferIndex] = barRect + bufferIndex += 1 + } + else + { + var posY = 0.0 + var negY = -e.negativeSum + var yStart = 0.0 + + // fill the stack + for k in 0 ..< vals!.count + { + let value = vals![k] + + if value == 0.0 && (posY == 0.0 || negY == 0.0) + { + // Take care of the situation of a 0.0 value, which overlaps a non-zero bar + y = value + yStart = y + } + else if value >= 0.0 + { + y = posY + yStart = posY + value + posY = yStart + } + else + { + y = negY + yStart = negY + abs(value) + negY += abs(value) + } + + let left = CGFloat(x - barWidthHalf) + let right = CGFloat(x + barWidthHalf) + var top = isInverted + ? (y <= yStart ? CGFloat(y) : CGFloat(yStart)) + : (y >= yStart ? CGFloat(y) : CGFloat(yStart)) + var bottom = isInverted + ? (y >= yStart ? CGFloat(y) : CGFloat(yStart)) + : (y <= yStart ? CGFloat(y) : CGFloat(yStart)) + + // multiply the height of the rect with the phase + top *= CGFloat(phaseY) + bottom *= CGFloat(phaseY) + + barRect.origin.x = left + barRect.size.width = right - left + barRect.origin.y = top + barRect.size.height = bottom - top + + buffer.rects[bufferIndex] = barRect + bufferIndex += 1 + } + } + } + } + + open override func drawData(context: CGContext) + { + guard + let dataProvider = dataProvider, + let barData = dataProvider.barData + else { return } + + // If we redraw the data, remove and repopulate accessible elements to update label values and frames + accessibleChartElements.removeAll() + accessibilityOrderedElements = accessibilityCreateEmptyOrderedElements() + + // Make the chart header the first element in the accessible elements array + if let chart = dataProvider as? BarChartView { + let element = createAccessibleHeader(usingChart: chart, + andData: barData, + withDefaultDescription: "Bar Chart") + accessibleChartElements.append(element) + } + + // Populate logically ordered nested elements into accessibilityOrderedElements in drawDataSet() + for i in 0 ..< barData.dataSetCount + { + guard let set = barData.getDataSetByIndex(i) else { continue } + + if set.isVisible + { + if !(set is IBarChartDataSet) + { + fatalError("Datasets for BarChartRenderer must conform to IBarChartDataset") + } + + drawDataSet(context: context, dataSet: set as! IBarChartDataSet, index: i) + } + } + + // Merge nested ordered arrays into the single accessibleChartElements. + accessibleChartElements.append(contentsOf: accessibilityOrderedElements.flatMap { $0 } ) + accessibilityPostLayoutChangedNotification() + } + + private var _barShadowRectBuffer: CGRect = CGRect() + + @objc open func drawDataSet(context: CGContext, dataSet: IBarChartDataSet, index: Int) + { + guard let dataProvider = dataProvider else { return } + + let trans = dataProvider.getTransformer(forAxis: dataSet.axisDependency) + + prepareBuffer(dataSet: dataSet, index: index) + trans.rectValuesToPixel(&_buffers[index].rects) + + let borderWidth = dataSet.barBorderWidth + let borderColor = dataSet.barBorderColor + let drawBorder = borderWidth > 0.0 + + context.saveGState() + + // draw the bar shadow before the values + if dataProvider.isDrawBarShadowEnabled + { + guard let barData = dataProvider.barData else { return } + + let barWidth = barData.barWidth + let barWidthHalf = barWidth / 2.0 + var x: Double = 0.0 + + for i in stride(from: 0, to: min(Int(ceil(Double(dataSet.entryCount) * animator.phaseX)), dataSet.entryCount), by: 1) + { + guard let e = dataSet.entryForIndex(i) as? BarChartDataEntry else { continue } + + x = e.x + + _barShadowRectBuffer.origin.x = CGFloat(x - barWidthHalf) + _barShadowRectBuffer.size.width = CGFloat(barWidth) + + trans.rectValueToPixel(&_barShadowRectBuffer) + + if !viewPortHandler.isInBoundsLeft(_barShadowRectBuffer.origin.x + _barShadowRectBuffer.size.width) + { + continue + } + + if !viewPortHandler.isInBoundsRight(_barShadowRectBuffer.origin.x) + { + break + } + + _barShadowRectBuffer.origin.y = viewPortHandler.contentTop + _barShadowRectBuffer.size.height = viewPortHandler.contentHeight + + context.setFillColor(dataSet.barShadowColor.cgColor) + context.fill(_barShadowRectBuffer) + } + } + + let buffer = _buffers[index] + + // draw the bar shadow before the values + if dataProvider.isDrawBarShadowEnabled + { + for j in stride(from: 0, to: buffer.rects.count, by: 1) + { + let barRect = buffer.rects[j] + + if (!viewPortHandler.isInBoundsLeft(barRect.origin.x + barRect.size.width)) + { + continue + } + + if (!viewPortHandler.isInBoundsRight(barRect.origin.x)) + { + break + } + + context.setFillColor(dataSet.barShadowColor.cgColor) + context.fill(barRect) + } + } + + let isSingleColor = dataSet.colors.count == 1 + + if isSingleColor + { + context.setFillColor(dataSet.color(atIndex: 0).cgColor) + } + + // In case the chart is stacked, we need to accomodate individual bars within accessibilityOrdereredElements + let isStacked = dataSet.isStacked + let stackSize = isStacked ? dataSet.stackSize : 1 + + for j in stride(from: 0, to: buffer.rects.count, by: 1) + { + let barRect = buffer.rects[j] + + if (!viewPortHandler.isInBoundsLeft(barRect.origin.x + barRect.size.width)) + { + continue + } + + if (!viewPortHandler.isInBoundsRight(barRect.origin.x)) + { + break + } + + if !isSingleColor + { + // Set the color for the currently drawn value. If the index is out of bounds, reuse colors. + context.setFillColor(dataSet.color(atIndex: j).cgColor) + } + + context.fill(barRect) + + if drawBorder + { + context.setStrokeColor(borderColor.cgColor) + context.setLineWidth(borderWidth) + context.stroke(barRect) + } + + // Create and append the corresponding accessibility element to accessibilityOrderedElements + if let chart = dataProvider as? BarChartView + { + let element = createAccessibleElement(withIndex: j, + container: chart, + dataSet: dataSet, + dataSetIndex: index, + stackSize: stackSize) + { (element) in + element.accessibilityFrame = barRect + } + + accessibilityOrderedElements[j/stackSize].append(element) + } + } + + context.restoreGState() + } + + open func prepareBarHighlight( + x: Double, + y1: Double, + y2: Double, + barWidthHalf: Double, + trans: Transformer, + rect: inout CGRect) + { + let left = x - barWidthHalf + let right = x + barWidthHalf + let top = y1 + let bottom = y2 + + rect.origin.x = CGFloat(left) + rect.origin.y = CGFloat(top) + rect.size.width = CGFloat(right - left) + rect.size.height = CGFloat(bottom - top) + + trans.rectValueToPixel(&rect, phaseY: animator.phaseY ) + } + + open override func drawValues(context: CGContext) + { + // if values are drawn + if isDrawingValuesAllowed(dataProvider: dataProvider) + { + guard + let dataProvider = dataProvider, + let barData = dataProvider.barData + else { return } + + var dataSets = barData.dataSets + + let valueOffsetPlus: CGFloat = 4.5 + var posOffset: CGFloat + var negOffset: CGFloat + let drawValueAboveBar = dataProvider.isDrawValueAboveBarEnabled + + for dataSetIndex in 0 ..< barData.dataSetCount + { + guard let + dataSet = dataSets[dataSetIndex] as? IBarChartDataSet, + shouldDrawValues(forDataSet: dataSet) + else { continue } + + let isInverted = dataProvider.isInverted(axis: dataSet.axisDependency) + + // calculate the correct offset depending on the draw position of the value + let valueFont = dataSet.valueFont + let valueTextHeight = valueFont.lineHeight + posOffset = (drawValueAboveBar ? -(valueTextHeight + valueOffsetPlus) : valueOffsetPlus) + negOffset = (drawValueAboveBar ? valueOffsetPlus : -(valueTextHeight + valueOffsetPlus)) + + if isInverted + { + posOffset = -posOffset - valueTextHeight + negOffset = -negOffset - valueTextHeight + } + + let buffer = _buffers[dataSetIndex] + + guard let formatter = dataSet.valueFormatter else { continue } + + let trans = dataProvider.getTransformer(forAxis: dataSet.axisDependency) + + let phaseY = animator.phaseY + + let iconsOffset = dataSet.iconsOffset + + // if only single values are drawn (sum) + if !dataSet.isStacked + { + for j in 0 ..< Int(ceil(Double(dataSet.entryCount) * animator.phaseX)) + { + guard let e = dataSet.entryForIndex(j) as? BarChartDataEntry else { continue } + + let rect = buffer.rects[j] + + let x = rect.origin.x + rect.size.width / 2.0 + + if !viewPortHandler.isInBoundsRight(x) + { + break + } + + if !viewPortHandler.isInBoundsY(rect.origin.y) + || !viewPortHandler.isInBoundsLeft(x) + { + continue + } + + let val = e.y + + if dataSet.isDrawValuesEnabled + { + drawValue( + context: context, + value: formatter.stringForValue( + val, + entry: e, + dataSetIndex: dataSetIndex, + viewPortHandler: viewPortHandler), + xPos: x, + yPos: val >= 0.0 + ? (rect.origin.y + posOffset) + : (rect.origin.y + rect.size.height + negOffset), + font: valueFont, + align: .center, + color: dataSet.valueTextColorAt(j)) + } + + if let icon = e.icon, dataSet.isDrawIconsEnabled + { + var px = x + var py = val >= 0.0 + ? (rect.origin.y + posOffset) + : (rect.origin.y + rect.size.height + negOffset) + + px += iconsOffset.x + py += iconsOffset.y + + ChartUtils.drawImage( + context: context, + image: icon, + x: px, + y: py, + size: icon.size) + } + } + } + else + { + // if we have stacks + + var bufferIndex = 0 + + for index in 0 ..< Int(ceil(Double(dataSet.entryCount) * animator.phaseX)) + { + guard let e = dataSet.entryForIndex(index) as? BarChartDataEntry else { continue } + + let vals = e.yValues + + let rect = buffer.rects[bufferIndex] + + let x = rect.origin.x + rect.size.width / 2.0 + + // we still draw stacked bars, but there is one non-stacked in between + if vals == nil + { + if !viewPortHandler.isInBoundsRight(x) + { + break + } + + if !viewPortHandler.isInBoundsY(rect.origin.y) + || !viewPortHandler.isInBoundsLeft(x) + { + continue + } + + if dataSet.isDrawValuesEnabled + { + drawValue( + context: context, + value: formatter.stringForValue( + e.y, + entry: e, + dataSetIndex: dataSetIndex, + viewPortHandler: viewPortHandler), + xPos: x, + yPos: rect.origin.y + + (e.y >= 0 ? posOffset : negOffset), + font: valueFont, + align: .center, + color: dataSet.valueTextColorAt(index)) + } + + if let icon = e.icon, dataSet.isDrawIconsEnabled + { + var px = x + var py = rect.origin.y + + (e.y >= 0 ? posOffset : negOffset) + + px += iconsOffset.x + py += iconsOffset.y + + ChartUtils.drawImage( + context: context, + image: icon, + x: px, + y: py, + size: icon.size) + } + } + else + { + // draw stack values + + let vals = vals! + var transformed = [CGPoint]() + + var posY = 0.0 + var negY = -e.negativeSum + + for k in 0 ..< vals.count + { + let value = vals[k] + var y: Double + + if value == 0.0 && (posY == 0.0 || negY == 0.0) + { + // Take care of the situation of a 0.0 value, which overlaps a non-zero bar + y = value + } + else if value >= 0.0 + { + posY += value + y = posY + } + else + { + y = negY + negY -= value + } + + transformed.append(CGPoint(x: 0.0, y: CGFloat(y * phaseY))) + } + + trans.pointValuesToPixel(&transformed) + + for k in 0 ..< transformed.count + { + let val = vals[k] + let drawBelow = (val == 0.0 && negY == 0.0 && posY > 0.0) || val < 0.0 + let y = transformed[k].y + (drawBelow ? negOffset : posOffset) + + if !viewPortHandler.isInBoundsRight(x) + { + break + } + + if !viewPortHandler.isInBoundsY(y) || !viewPortHandler.isInBoundsLeft(x) + { + continue + } + + if dataSet.isDrawValuesEnabled + { + drawValue( + context: context, + value: formatter.stringForValue( + vals[k], + entry: e, + dataSetIndex: dataSetIndex, + viewPortHandler: viewPortHandler), + xPos: x, + yPos: y, + font: valueFont, + align: .center, + color: dataSet.valueTextColorAt(index)) + } + + if let icon = e.icon, dataSet.isDrawIconsEnabled + { + ChartUtils.drawImage( + context: context, + image: icon, + x: x + iconsOffset.x, + y: y + iconsOffset.y, + size: icon.size) + } + } + } + + bufferIndex = vals == nil ? (bufferIndex + 1) : (bufferIndex + vals!.count) + } + } + } + } + } + + /// Draws a value at the specified x and y position. + @objc open func drawValue(context: CGContext, value: String, xPos: CGFloat, yPos: CGFloat, font: NSUIFont, align: NSTextAlignment, color: NSUIColor) + { + ChartUtils.drawText(context: context, text: value, point: CGPoint(x: xPos, y: yPos), align: align, attributes: [NSAttributedString.Key.font: font, NSAttributedString.Key.foregroundColor: color]) + } + + open override func drawExtras(context: CGContext) + { + + } + + open override func drawHighlighted(context: CGContext, indices: [Highlight]) + { + guard + let dataProvider = dataProvider, + let barData = dataProvider.barData + else { return } + + context.saveGState() + + var barRect = CGRect() + + for high in indices + { + guard + let set = barData.getDataSetByIndex(high.dataSetIndex) as? IBarChartDataSet, + set.isHighlightEnabled + else { continue } + + if let e = set.entryForXValue(high.x, closestToY: high.y) as? BarChartDataEntry + { + if !isInBoundsX(entry: e, dataSet: set) + { + continue + } + + let trans = dataProvider.getTransformer(forAxis: set.axisDependency) + + context.setFillColor(set.highlightColor.cgColor) + context.setAlpha(set.highlightAlpha) + + let isStack = high.stackIndex >= 0 && e.isStacked + + let y1: Double + let y2: Double + + if isStack + { + if dataProvider.isHighlightFullBarEnabled + { + y1 = e.positiveSum + y2 = -e.negativeSum + } + else + { + let range = e.ranges?[high.stackIndex] + + y1 = range?.from ?? 0.0 + y2 = range?.to ?? 0.0 + } + } + else + { + y1 = e.y + y2 = 0.0 + } + + prepareBarHighlight(x: e.x, y1: y1, y2: y2, barWidthHalf: barData.barWidth / 2.0, trans: trans, rect: &barRect) + + setHighlightDrawPos(highlight: high, barRect: barRect) + + context.fill(barRect) + } + } + + context.restoreGState() + } + + /// Sets the drawing position of the highlight object based on the given bar-rect. + internal func setHighlightDrawPos(highlight high: Highlight, barRect: CGRect) + { + high.setDraw(x: barRect.midX, y: barRect.origin.y) + } + + /// Creates a nested array of empty subarrays each of which will be populated with NSUIAccessibilityElements. + /// This is marked internal to support HorizontalBarChartRenderer as well. + internal func accessibilityCreateEmptyOrderedElements() -> [[NSUIAccessibilityElement]] + { + guard let chart = dataProvider as? BarChartView else { return [] } + + // Unlike Bubble & Line charts, here we use the maximum entry count to account for stacked bars + let maxEntryCount = chart.data?.maxEntryCountSet?.entryCount ?? 0 + + return Array(repeating: [NSUIAccessibilityElement](), + count: maxEntryCount) + } + + /// Creates an NSUIAccessibleElement representing the smallest meaningful bar of the chart + /// i.e. in case of a stacked chart, this returns each stack, not the combined bar. + /// Note that it is marked internal to support subclass modification in the HorizontalBarChart. + internal func createAccessibleElement(withIndex idx: Int, + container: BarChartView, + dataSet: IBarChartDataSet, + dataSetIndex: Int, + stackSize: Int, + modifier: (NSUIAccessibilityElement) -> ()) -> NSUIAccessibilityElement + { + let element = NSUIAccessibilityElement(accessibilityContainer: container) + let xAxis = container.xAxis + + guard let e = dataSet.entryForIndex(idx/stackSize) as? BarChartDataEntry else { return element } + guard let dataProvider = dataProvider else { return element } + + // NOTE: The formatter can cause issues when the x-axis labels are consecutive ints. + // i.e. due to the Double conversion, if there are more than one data set that are grouped, + // there is the possibility of some labels being rounded up. A floor() might fix this, but seems to be a brute force solution. + let label = xAxis.valueFormatter?.stringForValue(e.x, axis: xAxis) ?? "\(e.x)" + + var elementValueText = dataSet.valueFormatter?.stringForValue( + e.y, + entry: e, + dataSetIndex: dataSetIndex, + viewPortHandler: viewPortHandler) ?? "\(e.y)" + + if dataSet.isStacked, let vals = e.yValues + { + let labelCount = min(dataSet.colors.count, stackSize) + + let stackLabel: String? + if (dataSet.stackLabels.count > 0 && labelCount > 0) { + let labelIndex = idx % labelCount + stackLabel = dataSet.stackLabels.indices.contains(labelIndex) ? dataSet.stackLabels[labelIndex] : nil + } else { + stackLabel = nil + } + + elementValueText = dataSet.valueFormatter?.stringForValue( + vals[idx % stackSize], + entry: e, + dataSetIndex: dataSetIndex, + viewPortHandler: viewPortHandler) ?? "\(e.y)" + + if let stackLabel = stackLabel { + elementValueText = stackLabel + " \(elementValueText)" + } else { + elementValueText = "\(elementValueText)" + } + } + + let dataSetCount = dataProvider.barData?.dataSetCount ?? -1 + let doesContainMultipleDataSets = dataSetCount > 1 + + element.accessibilityLabel = "\(doesContainMultipleDataSets ? (dataSet.label ?? "") + ", " : "") \(label): \(elementValueText)" + + modifier(element) + + return element + } +} diff --git a/Pods/Charts/Source/Charts/Renderers/BarLineScatterCandleBubbleRenderer.swift b/Pods/Charts/Source/Charts/Renderers/BarLineScatterCandleBubbleRenderer.swift new file mode 100644 index 00000000..7c258b1f --- /dev/null +++ b/Pods/Charts/Source/Charts/Renderers/BarLineScatterCandleBubbleRenderer.swift @@ -0,0 +1,119 @@ +// +// BarLineScatterCandleBubbleRenderer.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(BarLineScatterCandleBubbleChartRenderer) +open class BarLineScatterCandleBubbleRenderer: DataRenderer +{ + internal var _xBounds = XBounds() // Reusable XBounds object + + public override init(animator: Animator, viewPortHandler: ViewPortHandler) + { + super.init(animator: animator, viewPortHandler: viewPortHandler) + } + + /// Checks if the provided entry object is in bounds for drawing considering the current animation phase. + internal func isInBoundsX(entry e: ChartDataEntry, dataSet: IBarLineScatterCandleBubbleChartDataSet) -> Bool + { + let entryIndex = dataSet.entryIndex(entry: e) + return Double(entryIndex) < Double(dataSet.entryCount) * animator.phaseX + } + + /// Calculates and returns the x-bounds for the given DataSet in terms of index in their values array. + /// This includes minimum and maximum visible x, as well as range. + internal func xBounds(chart: BarLineScatterCandleBubbleChartDataProvider, + dataSet: IBarLineScatterCandleBubbleChartDataSet, + animator: Animator?) -> XBounds + { + return XBounds(chart: chart, dataSet: dataSet, animator: animator) + } + + /// - Returns: `true` if the DataSet values should be drawn, `false` if not. + internal func shouldDrawValues(forDataSet set: IChartDataSet) -> Bool + { + return set.isVisible && (set.isDrawValuesEnabled || set.isDrawIconsEnabled) + } + + /// Class representing the bounds of the current viewport in terms of indices in the values array of a DataSet. + open class XBounds + { + /// minimum visible entry index + open var min: Int = 0 + + /// maximum visible entry index + open var max: Int = 0 + + /// range of visible entry indices + open var range: Int = 0 + + public init() + { + + } + + public init(chart: BarLineScatterCandleBubbleChartDataProvider, + dataSet: IBarLineScatterCandleBubbleChartDataSet, + animator: Animator?) + { + self.set(chart: chart, dataSet: dataSet, animator: animator) + } + + /// Calculates the minimum and maximum x values as well as the range between them. + open func set(chart: BarLineScatterCandleBubbleChartDataProvider, + dataSet: IBarLineScatterCandleBubbleChartDataSet, + animator: Animator?) + { + let phaseX = Swift.max(0.0, Swift.min(1.0, animator?.phaseX ?? 1.0)) + + let low = chart.lowestVisibleX + let high = chart.highestVisibleX + + let entryFrom = dataSet.entryForXValue(low, closestToY: .nan, rounding: .down) + let entryTo = dataSet.entryForXValue(high, closestToY: .nan, rounding: .up) + + self.min = entryFrom == nil ? 0 : dataSet.entryIndex(entry: entryFrom!) + self.max = entryTo == nil ? 0 : dataSet.entryIndex(entry: entryTo!) + range = Int(Double(self.max - self.min) * phaseX) + } + } +} + +extension BarLineScatterCandleBubbleRenderer.XBounds: RangeExpression { + public func relative(to collection: C) -> Swift.Range + where C : Collection, Bound == C.Index + { + return Swift.Range(min...min + range) + } + + public func contains(_ element: Int) -> Bool { + return (min...min + range).contains(element) + } +} + +extension BarLineScatterCandleBubbleRenderer.XBounds: Sequence { + public struct Iterator: IteratorProtocol { + private var iterator: IndexingIterator> + + fileprivate init(min: Int, max: Int) { + self.iterator = (min...max).makeIterator() + } + + public mutating func next() -> Int? { + return self.iterator.next() + } + } + + public func makeIterator() -> Iterator { + return Iterator(min: self.min, max: self.max) + } +} diff --git a/Pods/Charts/Source/Charts/Renderers/BubbleChartRenderer.swift b/Pods/Charts/Source/Charts/Renderers/BubbleChartRenderer.swift new file mode 100644 index 00000000..1a089e9f --- /dev/null +++ b/Pods/Charts/Source/Charts/Renderers/BubbleChartRenderer.swift @@ -0,0 +1,359 @@ +// +// BubbleChartRenderer.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 BubbleChartRenderer: BarLineScatterCandleBubbleRenderer +{ + /// A nested array of elements ordered logically (i.e not in visual/drawing order) for use with VoiceOver. + private lazy var accessibilityOrderedElements: [[NSUIAccessibilityElement]] = accessibilityCreateEmptyOrderedElements() + + @objc open weak var dataProvider: BubbleChartDataProvider? + + @objc public init(dataProvider: BubbleChartDataProvider, animator: Animator, viewPortHandler: ViewPortHandler) + { + super.init(animator: animator, viewPortHandler: viewPortHandler) + + self.dataProvider = dataProvider + } + + open override func drawData(context: CGContext) + { + guard + let dataProvider = dataProvider, + let bubbleData = dataProvider.bubbleData + else { return } + + // If we redraw the data, remove and repopulate accessible elements to update label values and frames + accessibleChartElements.removeAll() + accessibilityOrderedElements = accessibilityCreateEmptyOrderedElements() + + // Make the chart header the first element in the accessible elements array + if let chart = dataProvider as? BubbleChartView { + let element = createAccessibleHeader(usingChart: chart, + andData: bubbleData, + withDefaultDescription: "Bubble Chart") + accessibleChartElements.append(element) + } + + for (i, set) in (bubbleData.dataSets as! [IBubbleChartDataSet]).enumerated() where set.isVisible + { + drawDataSet(context: context, dataSet: set, dataSetIndex: i) + } + + // Merge nested ordered arrays into the single accessibleChartElements. + accessibleChartElements.append(contentsOf: accessibilityOrderedElements.flatMap { $0 } ) + accessibilityPostLayoutChangedNotification() + } + + private func getShapeSize( + entrySize: CGFloat, + maxSize: CGFloat, + reference: CGFloat, + normalizeSize: Bool) -> CGFloat + { + let factor: CGFloat = normalizeSize + ? ((maxSize == 0.0) ? 1.0 : sqrt(entrySize / maxSize)) + : entrySize + let shapeSize: CGFloat = reference * factor + return shapeSize + } + + private var _pointBuffer = CGPoint() + private var _sizeBuffer = [CGPoint](repeating: CGPoint(), count: 2) + + @objc open func drawDataSet(context: CGContext, dataSet: IBubbleChartDataSet, dataSetIndex: Int) + { + guard let dataProvider = dataProvider else { return } + + let trans = dataProvider.getTransformer(forAxis: dataSet.axisDependency) + + let phaseY = animator.phaseY + + _xBounds.set(chart: dataProvider, dataSet: dataSet, animator: animator) + + let valueToPixelMatrix = trans.valueToPixelMatrix + + _sizeBuffer[0].x = 0.0 + _sizeBuffer[0].y = 0.0 + _sizeBuffer[1].x = 1.0 + _sizeBuffer[1].y = 0.0 + + trans.pointValuesToPixel(&_sizeBuffer) + + context.saveGState() + defer { context.restoreGState() } + + let normalizeSize = dataSet.isNormalizeSizeEnabled + + // calcualte the full width of 1 step on the x-axis + let maxBubbleWidth: CGFloat = abs(_sizeBuffer[1].x - _sizeBuffer[0].x) + let maxBubbleHeight: CGFloat = abs(viewPortHandler.contentBottom - viewPortHandler.contentTop) + let referenceSize: CGFloat = min(maxBubbleHeight, maxBubbleWidth) + + for j in _xBounds + { + guard let entry = dataSet.entryForIndex(j) as? BubbleChartDataEntry else { continue } + + _pointBuffer.x = CGFloat(entry.x) + _pointBuffer.y = CGFloat(entry.y * phaseY) + _pointBuffer = _pointBuffer.applying(valueToPixelMatrix) + + let shapeSize = getShapeSize(entrySize: entry.size, maxSize: dataSet.maxSize, reference: referenceSize, normalizeSize: normalizeSize) + let shapeHalf = shapeSize / 2.0 + + guard + viewPortHandler.isInBoundsTop(_pointBuffer.y + shapeHalf), + viewPortHandler.isInBoundsBottom(_pointBuffer.y - shapeHalf), + viewPortHandler.isInBoundsLeft(_pointBuffer.x + shapeHalf) + else { continue } + + guard viewPortHandler.isInBoundsRight(_pointBuffer.x - shapeHalf) else { break } + + let color = dataSet.color(atIndex: j) + + let rect = CGRect( + x: _pointBuffer.x - shapeHalf, + y: _pointBuffer.y - shapeHalf, + width: shapeSize, + height: shapeSize + ) + + context.setFillColor(color.cgColor) + context.fillEllipse(in: rect) + + // Create and append the corresponding accessibility element to accessibilityOrderedElements + if let chart = dataProvider as? BubbleChartView + { + let element = createAccessibleElement(withIndex: j, + container: chart, + dataSet: dataSet, + dataSetIndex: dataSetIndex, + shapeSize: shapeSize) + { (element) in + element.accessibilityFrame = rect + } + + accessibilityOrderedElements[dataSetIndex].append(element) + } + } + } + + open override func drawValues(context: CGContext) + { + guard let + dataProvider = dataProvider, + let bubbleData = dataProvider.bubbleData, + isDrawingValuesAllowed(dataProvider: dataProvider), + let dataSets = bubbleData.dataSets as? [IBubbleChartDataSet] + else { return } + + let phaseX = max(0.0, min(1.0, animator.phaseX)) + let phaseY = animator.phaseY + + var pt = CGPoint() + + for i in 0.. [[NSUIAccessibilityElement]] + { + guard let chart = dataProvider as? BubbleChartView else { return [] } + + let dataSetCount = chart.bubbleData?.dataSetCount ?? 0 + + return Array(repeating: [NSUIAccessibilityElement](), + count: dataSetCount) + } + + /// Creates an NSUIAccessibleElement representing individual bubbles location and relative size. + private func createAccessibleElement(withIndex idx: Int, + container: BubbleChartView, + dataSet: IBubbleChartDataSet, + dataSetIndex: Int, + shapeSize: CGFloat, + modifier: (NSUIAccessibilityElement) -> ()) -> NSUIAccessibilityElement + { + let element = NSUIAccessibilityElement(accessibilityContainer: container) + let xAxis = container.xAxis + + guard let e = dataSet.entryForIndex(idx) else { return element } + guard let dataProvider = dataProvider else { return element } + + // NOTE: The formatter can cause issues when the x-axis labels are consecutive ints. + // i.e. due to the Double conversion, if there are more than one data set that are grouped, + // there is the possibility of some labels being rounded up. A floor() might fix this, but seems to be a brute force solution. + let label = xAxis.valueFormatter?.stringForValue(e.x, axis: xAxis) ?? "\(e.x)" + + let elementValueText = dataSet.valueFormatter?.stringForValue(e.y, + entry: e, + dataSetIndex: dataSetIndex, + viewPortHandler: viewPortHandler) ?? "\(e.y)" + + let dataSetCount = dataProvider.bubbleData?.dataSetCount ?? -1 + let doesContainMultipleDataSets = dataSetCount > 1 + + element.accessibilityLabel = "\(doesContainMultipleDataSets ? (dataSet.label ?? "") + ", " : "") \(label): \(elementValueText), bubble size: \(String(format: "%.2f", (shapeSize/dataSet.maxSize) * 100)) %" + + modifier(element) + + return element + } +} diff --git a/Pods/Charts/Source/Charts/Renderers/CandleStickChartRenderer.swift b/Pods/Charts/Source/Charts/Renderers/CandleStickChartRenderer.swift new file mode 100644 index 00000000..2e8cda32 --- /dev/null +++ b/Pods/Charts/Source/Charts/Renderers/CandleStickChartRenderer.swift @@ -0,0 +1,420 @@ +// +// CandleStickChartRenderer.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 CandleStickChartRenderer: LineScatterCandleRadarRenderer +{ + @objc open weak var dataProvider: CandleChartDataProvider? + + @objc public init(dataProvider: CandleChartDataProvider, animator: Animator, viewPortHandler: ViewPortHandler) + { + super.init(animator: animator, viewPortHandler: viewPortHandler) + + self.dataProvider = dataProvider + } + + open override func drawData(context: CGContext) + { + guard let dataProvider = dataProvider, let candleData = dataProvider.candleData else { return } + + // If we redraw the data, remove and repopulate accessible elements to update label values and frames + accessibleChartElements.removeAll() + + // Make the chart header the first element in the accessible elements array + if let chart = dataProvider as? CandleStickChartView { + let element = createAccessibleHeader(usingChart: chart, + andData: candleData, + withDefaultDescription: "CandleStick Chart") + accessibleChartElements.append(element) + } + + for set in candleData.dataSets as! [ICandleChartDataSet] where set.isVisible + { + drawDataSet(context: context, dataSet: set) + } + } + + private var _shadowPoints = [CGPoint](repeating: CGPoint(), count: 4) + private var _rangePoints = [CGPoint](repeating: CGPoint(), count: 2) + private var _openPoints = [CGPoint](repeating: CGPoint(), count: 2) + private var _closePoints = [CGPoint](repeating: CGPoint(), count: 2) + private var _bodyRect = CGRect() + private var _lineSegments = [CGPoint](repeating: CGPoint(), count: 2) + + @objc open func drawDataSet(context: CGContext, dataSet: ICandleChartDataSet) + { + guard + let dataProvider = dataProvider + else { return } + + let trans = dataProvider.getTransformer(forAxis: dataSet.axisDependency) + + let phaseY = animator.phaseY + let barSpace = dataSet.barSpace + let showCandleBar = dataSet.showCandleBar + + _xBounds.set(chart: dataProvider, dataSet: dataSet, animator: animator) + + context.saveGState() + + context.setLineWidth(dataSet.shadowWidth) + + for j in _xBounds + { + // get the entry + guard let e = dataSet.entryForIndex(j) as? CandleChartDataEntry else { continue } + + let xPos = e.x + + let open = e.open + let close = e.close + let high = e.high + let low = e.low + + let doesContainMultipleDataSets = (dataProvider.candleData?.dataSets.count ?? 1) > 1 + var accessibilityMovementDescription = "neutral" + var accessibilityRect = CGRect(x: CGFloat(xPos) + 0.5 - barSpace, + y: CGFloat(low * phaseY), + width: (2 * barSpace) - 1.0, + height: (CGFloat(abs(high - low) * phaseY))) + trans.rectValueToPixel(&accessibilityRect) + + if showCandleBar + { + // calculate the shadow + + _shadowPoints[0].x = CGFloat(xPos) + _shadowPoints[1].x = CGFloat(xPos) + _shadowPoints[2].x = CGFloat(xPos) + _shadowPoints[3].x = CGFloat(xPos) + + if open > close + { + _shadowPoints[0].y = CGFloat(high * phaseY) + _shadowPoints[1].y = CGFloat(open * phaseY) + _shadowPoints[2].y = CGFloat(low * phaseY) + _shadowPoints[3].y = CGFloat(close * phaseY) + } + else if open < close + { + _shadowPoints[0].y = CGFloat(high * phaseY) + _shadowPoints[1].y = CGFloat(close * phaseY) + _shadowPoints[2].y = CGFloat(low * phaseY) + _shadowPoints[3].y = CGFloat(open * phaseY) + } + else + { + _shadowPoints[0].y = CGFloat(high * phaseY) + _shadowPoints[1].y = CGFloat(open * phaseY) + _shadowPoints[2].y = CGFloat(low * phaseY) + _shadowPoints[3].y = _shadowPoints[1].y + } + + trans.pointValuesToPixel(&_shadowPoints) + + // draw the shadows + + var shadowColor: NSUIColor! = nil + if dataSet.shadowColorSameAsCandle + { + if open > close + { + shadowColor = dataSet.decreasingColor ?? dataSet.color(atIndex: j) + } + else if open < close + { + shadowColor = dataSet.increasingColor ?? dataSet.color(atIndex: j) + } + else + { + shadowColor = dataSet.neutralColor ?? dataSet.color(atIndex: j) + } + } + + if shadowColor === nil + { + shadowColor = dataSet.shadowColor ?? dataSet.color(atIndex: j) + } + + context.setStrokeColor(shadowColor.cgColor) + context.strokeLineSegments(between: _shadowPoints) + + // calculate the body + + _bodyRect.origin.x = CGFloat(xPos) - 0.5 + barSpace + _bodyRect.origin.y = CGFloat(close * phaseY) + _bodyRect.size.width = (CGFloat(xPos) + 0.5 - barSpace) - _bodyRect.origin.x + _bodyRect.size.height = CGFloat(open * phaseY) - _bodyRect.origin.y + + trans.rectValueToPixel(&_bodyRect) + + // draw body differently for increasing and decreasing entry + + if open > close + { + accessibilityMovementDescription = "decreasing" + + let color = dataSet.decreasingColor ?? dataSet.color(atIndex: j) + + if dataSet.isDecreasingFilled + { + context.setFillColor(color.cgColor) + context.fill(_bodyRect) + } + else + { + context.setStrokeColor(color.cgColor) + context.stroke(_bodyRect) + } + } + else if open < close + { + accessibilityMovementDescription = "increasing" + + let color = dataSet.increasingColor ?? dataSet.color(atIndex: j) + + if dataSet.isIncreasingFilled + { + context.setFillColor(color.cgColor) + context.fill(_bodyRect) + } + else + { + context.setStrokeColor(color.cgColor) + context.stroke(_bodyRect) + } + } + else + { + let color = dataSet.neutralColor ?? dataSet.color(atIndex: j) + + context.setStrokeColor(color.cgColor) + context.stroke(_bodyRect) + } + } + else + { + _rangePoints[0].x = CGFloat(xPos) + _rangePoints[0].y = CGFloat(high * phaseY) + _rangePoints[1].x = CGFloat(xPos) + _rangePoints[1].y = CGFloat(low * phaseY) + + _openPoints[0].x = CGFloat(xPos) - 0.5 + barSpace + _openPoints[0].y = CGFloat(open * phaseY) + _openPoints[1].x = CGFloat(xPos) + _openPoints[1].y = CGFloat(open * phaseY) + + _closePoints[0].x = CGFloat(xPos) + 0.5 - barSpace + _closePoints[0].y = CGFloat(close * phaseY) + _closePoints[1].x = CGFloat(xPos) + _closePoints[1].y = CGFloat(close * phaseY) + + trans.pointValuesToPixel(&_rangePoints) + trans.pointValuesToPixel(&_openPoints) + trans.pointValuesToPixel(&_closePoints) + + // draw the ranges + var barColor: NSUIColor! = nil + + if open > close + { + accessibilityMovementDescription = "decreasing" + barColor = dataSet.decreasingColor ?? dataSet.color(atIndex: j) + } + else if open < close + { + accessibilityMovementDescription = "increasing" + barColor = dataSet.increasingColor ?? dataSet.color(atIndex: j) + } + else + { + barColor = dataSet.neutralColor ?? dataSet.color(atIndex: j) + } + + context.setStrokeColor(barColor.cgColor) + context.strokeLineSegments(between: _rangePoints) + context.strokeLineSegments(between: _openPoints) + context.strokeLineSegments(between: _closePoints) + } + + let axElement = createAccessibleElement(withIndex: j, + container: dataProvider, + dataSet: dataSet) + { (element) in + element.accessibilityLabel = "\(doesContainMultipleDataSets ? "\(dataSet.label ?? "Dataset")" : "") " + "\(xPos) - \(accessibilityMovementDescription). low: \(low), high: \(high), opening: \(open), closing: \(close)" + element.accessibilityFrame = accessibilityRect + } + + accessibleChartElements.append(axElement) + + } + + // Post this notification to let VoiceOver account for the redrawn frames + accessibilityPostLayoutChangedNotification() + + context.restoreGState() + } + + open override func drawValues(context: CGContext) + { + guard + let dataProvider = dataProvider, + let candleData = dataProvider.candleData + else { return } + + // if values are drawn + if isDrawingValuesAllowed(dataProvider: dataProvider) + { + var dataSets = candleData.dataSets + + let phaseY = animator.phaseY + + var pt = CGPoint() + + for i in 0 ..< dataSets.count + { + guard let + dataSet = dataSets[i] as? IBarLineScatterCandleBubbleChartDataSet, + shouldDrawValues(forDataSet: dataSet) + else { continue } + + let valueFont = dataSet.valueFont + + guard let formatter = dataSet.valueFormatter else { continue } + + let trans = dataProvider.getTransformer(forAxis: dataSet.axisDependency) + let valueToPixelMatrix = trans.valueToPixelMatrix + + let iconsOffset = dataSet.iconsOffset + + _xBounds.set(chart: dataProvider, dataSet: dataSet, animator: animator) + + let lineHeight = valueFont.lineHeight + let yOffset: CGFloat = lineHeight + 5.0 + + for j in _xBounds + { + guard let e = dataSet.entryForIndex(j) as? CandleChartDataEntry else { break } + + pt.x = CGFloat(e.x) + pt.y = CGFloat(e.high * phaseY) + pt = pt.applying(valueToPixelMatrix) + + if (!viewPortHandler.isInBoundsRight(pt.x)) + { + break + } + + if (!viewPortHandler.isInBoundsLeft(pt.x) || !viewPortHandler.isInBoundsY(pt.y)) + { + continue + } + + if dataSet.isDrawValuesEnabled + { + ChartUtils.drawText( + context: context, + text: formatter.stringForValue( + e.high, + entry: e, + dataSetIndex: i, + viewPortHandler: viewPortHandler), + point: CGPoint( + x: pt.x, + y: pt.y - yOffset), + align: .center, + attributes: [NSAttributedString.Key.font: valueFont, NSAttributedString.Key.foregroundColor: dataSet.valueTextColorAt(j)]) + } + + if let icon = e.icon, dataSet.isDrawIconsEnabled + { + ChartUtils.drawImage(context: context, + image: icon, + x: pt.x + iconsOffset.x, + y: pt.y + iconsOffset.y, + size: icon.size) + } + } + } + } + } + + open override func drawExtras(context: CGContext) + { + } + + open override func drawHighlighted(context: CGContext, indices: [Highlight]) + { + guard + let dataProvider = dataProvider, + let candleData = dataProvider.candleData + else { return } + + context.saveGState() + + for high in indices + { + guard + let set = candleData.getDataSetByIndex(high.dataSetIndex) as? ICandleChartDataSet, + set.isHighlightEnabled + else { continue } + + guard let e = set.entryForXValue(high.x, closestToY: high.y) as? CandleChartDataEntry else { continue } + + if !isInBoundsX(entry: e, dataSet: set) + { + continue + } + + let trans = dataProvider.getTransformer(forAxis: set.axisDependency) + + context.setStrokeColor(set.highlightColor.cgColor) + context.setLineWidth(set.highlightLineWidth) + + if set.highlightLineDashLengths != nil + { + context.setLineDash(phase: set.highlightLineDashPhase, lengths: set.highlightLineDashLengths!) + } + else + { + context.setLineDash(phase: 0.0, lengths: []) + } + + let lowValue = e.low * Double(animator.phaseY) + let highValue = e.high * Double(animator.phaseY) + let y = (lowValue + highValue) / 2.0 + + let pt = trans.pixelForValues(x: e.x, y: y) + + high.setDraw(pt: pt) + + // draw the lines + drawHighlightLines(context: context, point: pt, set: set) + } + + context.restoreGState() + } + + private func createAccessibleElement(withIndex idx: Int, + container: CandleChartDataProvider, + dataSet: ICandleChartDataSet, + modifier: (NSUIAccessibilityElement) -> ()) -> NSUIAccessibilityElement { + + let element = NSUIAccessibilityElement(accessibilityContainer: container) + + // The modifier allows changing of traits and frame depending on highlight, rotation, etc + modifier(element) + + return element + } +} diff --git a/Pods/Charts/Source/Charts/Renderers/ChartDataRendererBase.swift b/Pods/Charts/Source/Charts/Renderers/ChartDataRendererBase.swift new file mode 100644 index 00000000..68905ff5 --- /dev/null +++ b/Pods/Charts/Source/Charts/Renderers/ChartDataRendererBase.swift @@ -0,0 +1,94 @@ +// +// DataRenderer.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(ChartDataRendererBase) +open class DataRenderer: Renderer +{ + /// An array of accessibility elements that are presented to the ChartViewBase accessibility methods. + /// + /// Note that the order of elements in this array determines the order in which they are presented and navigated by + /// Accessibility clients such as VoiceOver. + /// + /// Renderers should ensure that the order of elements makes sense to a client presenting an audio-only interface to a user. + /// Subclasses should populate this array in drawData() or drawDataSet() to make the chart accessible. + @objc final var accessibleChartElements: [NSUIAccessibilityElement] = [] + + @objc public let animator: Animator + + @objc public init(animator: Animator, viewPortHandler: ViewPortHandler) + { + self.animator = animator + + super.init(viewPortHandler: viewPortHandler) + } + + @objc open func drawData(context: CGContext) + { + fatalError("drawData() cannot be called on DataRenderer") + } + + @objc open func drawValues(context: CGContext) + { + fatalError("drawValues() cannot be called on DataRenderer") + } + + @objc open func drawExtras(context: CGContext) + { + fatalError("drawExtras() cannot be called on DataRenderer") + } + + /// Draws all highlight indicators for the values that are currently highlighted. + /// + /// - Parameters: + /// - indices: the highlighted values + @objc open func drawHighlighted(context: CGContext, indices: [Highlight]) + { + fatalError("drawHighlighted() cannot be called on DataRenderer") + } + + /// An opportunity for initializing internal buffers used for rendering with a new size. + /// Since this might do memory allocations, it should only be called if necessary. + @objc open func initBuffers() { } + + @objc open func isDrawingValuesAllowed(dataProvider: ChartDataProvider?) -> Bool + { + guard let data = dataProvider?.data else { return false } + return data.entryCount < Int(CGFloat(dataProvider?.maxVisibleCount ?? 0) * viewPortHandler.scaleX) + } + + /// Creates an ```NSUIAccessibilityElement``` that acts as the first and primary header describing a chart view. + /// + /// - Parameters: + /// - chart: The chartView object being described + /// - data: A non optional data source about the chart + /// - defaultDescription: A simple string describing the type/design of Chart. + /// - Returns: A header ```NSUIAccessibilityElement``` that can be added to accessibleChartElements. + @objc internal func createAccessibleHeader(usingChart chart: ChartViewBase, + andData data: ChartData, + withDefaultDescription defaultDescription: String = "Chart") -> NSUIAccessibilityElement + { + let chartDescriptionText = chart.chartDescription?.text ?? defaultDescription + let dataSetDescriptions = data.dataSets.map { $0.label ?? "" } + let dataSetDescriptionText = dataSetDescriptions.joined(separator: ", ") + let dataSetCount = data.dataSets.count + + let + element = NSUIAccessibilityElement(accessibilityContainer: chart) + element.accessibilityLabel = chartDescriptionText + ". \(dataSetCount) dataset\(dataSetCount == 1 ? "" : "s"). \(dataSetDescriptionText)" + element.accessibilityFrame = chart.bounds + element.isHeader = true + + return element + } +} diff --git a/Pods/Charts/Source/Charts/Renderers/CombinedChartRenderer.swift b/Pods/Charts/Source/Charts/Renderers/CombinedChartRenderer.swift new file mode 100644 index 00000000..8446c9b6 --- /dev/null +++ b/Pods/Charts/Source/Charts/Renderers/CombinedChartRenderer.swift @@ -0,0 +1,209 @@ +// +// CombinedChartRenderer.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 CombinedChartRenderer: DataRenderer +{ + @objc open weak var chart: CombinedChartView? + + /// if set to true, all values are drawn above their bars, instead of below their top + @objc open var drawValueAboveBarEnabled = true + + /// if set to true, a grey area is drawn behind each bar that indicates the maximum value + @objc open var drawBarShadowEnabled = false + + internal var _renderers = [DataRenderer]() + + internal var _drawOrder: [CombinedChartView.DrawOrder] = [.bar, .bubble, .line, .candle, .scatter] + + @objc public init(chart: CombinedChartView, animator: Animator, viewPortHandler: ViewPortHandler) + { + super.init(animator: animator, viewPortHandler: viewPortHandler) + + self.chart = chart + + createRenderers() + } + + /// Creates the renderers needed for this combined-renderer in the required order. Also takes the DrawOrder into consideration. + internal func createRenderers() + { + _renderers = [DataRenderer]() + + guard let chart = chart else { return } + + for order in drawOrder + { + switch (order) + { + case .bar: + if chart.barData !== nil + { + _renderers.append(BarChartRenderer(dataProvider: chart, animator: animator, viewPortHandler: viewPortHandler)) + } + break + + case .line: + if chart.lineData !== nil + { + _renderers.append(LineChartRenderer(dataProvider: chart, animator: animator, viewPortHandler: viewPortHandler)) + } + break + + case .candle: + if chart.candleData !== nil + { + _renderers.append(CandleStickChartRenderer(dataProvider: chart, animator: animator, viewPortHandler: viewPortHandler)) + } + break + + case .scatter: + if chart.scatterData !== nil + { + _renderers.append(ScatterChartRenderer(dataProvider: chart, animator: animator, viewPortHandler: viewPortHandler)) + } + break + + case .bubble: + if chart.bubbleData !== nil + { + _renderers.append(BubbleChartRenderer(dataProvider: chart, animator: animator, viewPortHandler: viewPortHandler)) + } + break + } + } + + } + + open override func initBuffers() + { + _renderers.forEach { $0.initBuffers() } + } + + open override func drawData(context: CGContext) + { + // If we redraw the data, remove and repopulate accessible elements to update label values and frames + accessibleChartElements.removeAll() + + if + let combinedChart = chart, + let data = combinedChart.data { + // Make the chart header the first element in the accessible elements array + let element = createAccessibleHeader(usingChart: combinedChart, + andData: data, + withDefaultDescription: "Combined Chart") + accessibleChartElements.append(element) + } + + // TODO: Due to the potential complexity of data presented in Combined charts, a more usable way + // for VO accessibility would be to use axis based traversal rather than by dataset. + // Hence, accessibleChartElements is not populated below. (Individual renderers guard against dataSource being their respective views) + _renderers.forEach { $0.drawData(context: context) } + } + + open override func drawValues(context: CGContext) + { + _renderers.forEach { $0.drawValues(context: context) } + } + + open override func drawExtras(context: CGContext) + { + _renderers.forEach { $0.drawExtras(context: context) } + } + + open override func drawHighlighted(context: CGContext, indices: [Highlight]) + { + for renderer in _renderers + { + var data: ChartData? + + if renderer is BarChartRenderer + { + data = (renderer as! BarChartRenderer).dataProvider?.barData + } + else if renderer is LineChartRenderer + { + data = (renderer as! LineChartRenderer).dataProvider?.lineData + } + else if renderer is CandleStickChartRenderer + { + data = (renderer as! CandleStickChartRenderer).dataProvider?.candleData + } + else if renderer is ScatterChartRenderer + { + data = (renderer as! ScatterChartRenderer).dataProvider?.scatterData + } + else if renderer is BubbleChartRenderer + { + data = (renderer as! BubbleChartRenderer).dataProvider?.bubbleData + } + + let dataIndex: Int? = { + guard let data = data else { return nil } + return (chart?.data as? CombinedChartData)? + .allData + .firstIndex(of: data) + }() + + let dataIndices = indices.filter{ $0.dataIndex == dataIndex || $0.dataIndex == -1 } + + renderer.drawHighlighted(context: context, indices: dataIndices) + } + } + + /// - Returns: The sub-renderer object at the specified index. + @objc open func getSubRenderer(index: Int) -> DataRenderer? + { + if index >= _renderers.count || index < 0 + { + return nil + } + else + { + return _renderers[index] + } + } + + /// All sub-renderers. + @objc open var subRenderers: [DataRenderer] + { + get { return _renderers } + set { _renderers = newValue } + } + + // MARK: Accessors + + /// `true` if drawing values above bars is enabled, `false` ifnot + @objc open var isDrawValueAboveBarEnabled: Bool { return drawValueAboveBarEnabled } + + /// `true` if drawing shadows (maxvalue) for each bar is enabled, `false` ifnot + @objc open var isDrawBarShadowEnabled: Bool { return drawBarShadowEnabled } + + /// the order in which the provided data objects should be drawn. + /// The earlier you place them in the provided array, the further they will be in the background. + /// e.g. if you provide [DrawOrder.Bar, DrawOrder.Line], the bars will be drawn behind the lines. + open var drawOrder: [CombinedChartView.DrawOrder] + { + get + { + return _drawOrder + } + set + { + if newValue.count > 0 + { + _drawOrder = newValue + } + } + } +} diff --git a/Pods/Charts/Source/Charts/Renderers/HorizontalBarChartRenderer.swift b/Pods/Charts/Source/Charts/Renderers/HorizontalBarChartRenderer.swift new file mode 100644 index 00000000..309de7cf --- /dev/null +++ b/Pods/Charts/Source/Charts/Renderers/HorizontalBarChartRenderer.swift @@ -0,0 +1,624 @@ +// +// HorizontalBarChartRenderer.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 HorizontalBarChartRenderer: BarChartRenderer +{ + private class Buffer + { + var rects = [CGRect]() + } + + public override init(dataProvider: BarChartDataProvider, animator: Animator, viewPortHandler: ViewPortHandler) + { + super.init(dataProvider: dataProvider, animator: animator, viewPortHandler: viewPortHandler) + } + + // [CGRect] per dataset + private var _buffers = [Buffer]() + + open override func initBuffers() + { + if let barData = dataProvider?.barData + { + // Matche buffers count to dataset count + if _buffers.count != barData.dataSetCount + { + while _buffers.count < barData.dataSetCount + { + _buffers.append(Buffer()) + } + while _buffers.count > barData.dataSetCount + { + _buffers.removeLast() + } + } + + for i in stride(from: 0, to: barData.dataSetCount, by: 1) + { + let set = barData.dataSets[i] as! IBarChartDataSet + let size = set.entryCount * (set.isStacked ? set.stackSize : 1) + if _buffers[i].rects.count != size + { + _buffers[i].rects = [CGRect](repeating: CGRect(), count: size) + } + } + } + else + { + _buffers.removeAll() + } + } + + private func prepareBuffer(dataSet: IBarChartDataSet, index: Int) + { + guard let + dataProvider = dataProvider, + let barData = dataProvider.barData + else { return } + + let barWidthHalf = barData.barWidth / 2.0 + + let buffer = _buffers[index] + var bufferIndex = 0 + let containsStacks = dataSet.isStacked + + let isInverted = dataProvider.isInverted(axis: dataSet.axisDependency) + let phaseY = animator.phaseY + var barRect = CGRect() + var x: Double + var y: Double + + for i in stride(from: 0, to: min(Int(ceil(Double(dataSet.entryCount) * animator.phaseX)), dataSet.entryCount), by: 1) + { + guard let e = dataSet.entryForIndex(i) as? BarChartDataEntry else { continue } + + let vals = e.yValues + + x = e.x + y = e.y + + if !containsStacks || vals == nil + { + let bottom = CGFloat(x - barWidthHalf) + let top = CGFloat(x + barWidthHalf) + var right = isInverted + ? (y <= 0.0 ? CGFloat(y) : 0) + : (y >= 0.0 ? CGFloat(y) : 0) + var left = isInverted + ? (y >= 0.0 ? CGFloat(y) : 0) + : (y <= 0.0 ? CGFloat(y) : 0) + + // multiply the height of the rect with the phase + if right > 0 + { + right *= CGFloat(phaseY) + } + else + { + left *= CGFloat(phaseY) + } + + barRect.origin.x = left + barRect.size.width = right - left + barRect.origin.y = top + barRect.size.height = bottom - top + + buffer.rects[bufferIndex] = barRect + bufferIndex += 1 + } + else + { + var posY = 0.0 + var negY = -e.negativeSum + var yStart = 0.0 + + // fill the stack + for k in 0 ..< vals!.count + { + let value = vals![k] + + if value == 0.0 && (posY == 0.0 || negY == 0.0) + { + // Take care of the situation of a 0.0 value, which overlaps a non-zero bar + y = value + yStart = y + } + else if value >= 0.0 + { + y = posY + yStart = posY + value + posY = yStart + } + else + { + y = negY + yStart = negY + abs(value) + negY += abs(value) + } + + let bottom = CGFloat(x - barWidthHalf) + let top = CGFloat(x + barWidthHalf) + var right = isInverted + ? (y <= yStart ? CGFloat(y) : CGFloat(yStart)) + : (y >= yStart ? CGFloat(y) : CGFloat(yStart)) + var left = isInverted + ? (y >= yStart ? CGFloat(y) : CGFloat(yStart)) + : (y <= yStart ? CGFloat(y) : CGFloat(yStart)) + + // multiply the height of the rect with the phase + right *= CGFloat(phaseY) + left *= CGFloat(phaseY) + + barRect.origin.x = left + barRect.size.width = right - left + barRect.origin.y = top + barRect.size.height = bottom - top + + buffer.rects[bufferIndex] = barRect + bufferIndex += 1 + } + } + } + } + + private var _barShadowRectBuffer: CGRect = CGRect() + + open override func drawDataSet(context: CGContext, dataSet: IBarChartDataSet, index: Int) + { + guard let dataProvider = dataProvider else { return } + + let trans = dataProvider.getTransformer(forAxis: dataSet.axisDependency) + + prepareBuffer(dataSet: dataSet, index: index) + trans.rectValuesToPixel(&_buffers[index].rects) + + let borderWidth = dataSet.barBorderWidth + let borderColor = dataSet.barBorderColor + let drawBorder = borderWidth > 0.0 + + context.saveGState() + + // draw the bar shadow before the values + if dataProvider.isDrawBarShadowEnabled + { + guard let barData = dataProvider.barData else { return } + + let barWidth = barData.barWidth + let barWidthHalf = barWidth / 2.0 + var x: Double = 0.0 + + for i in stride(from: 0, to: min(Int(ceil(Double(dataSet.entryCount) * animator.phaseX)), dataSet.entryCount), by: 1) + { + guard let e = dataSet.entryForIndex(i) as? BarChartDataEntry else { continue } + + x = e.x + + _barShadowRectBuffer.origin.y = CGFloat(x - barWidthHalf) + _barShadowRectBuffer.size.height = CGFloat(barWidth) + + trans.rectValueToPixel(&_barShadowRectBuffer) + + if !viewPortHandler.isInBoundsTop(_barShadowRectBuffer.origin.y + _barShadowRectBuffer.size.height) + { + break + } + + if !viewPortHandler.isInBoundsBottom(_barShadowRectBuffer.origin.y) + { + continue + } + + _barShadowRectBuffer.origin.x = viewPortHandler.contentLeft + _barShadowRectBuffer.size.width = viewPortHandler.contentWidth + + context.setFillColor(dataSet.barShadowColor.cgColor) + context.fill(_barShadowRectBuffer) + } + } + + let buffer = _buffers[index] + + let isSingleColor = dataSet.colors.count == 1 + + if isSingleColor + { + context.setFillColor(dataSet.color(atIndex: 0).cgColor) + } + + // In case the chart is stacked, we need to accomodate individual bars within accessibilityOrdereredElements + let isStacked = dataSet.isStacked + let stackSize = isStacked ? dataSet.stackSize : 1 + + for j in stride(from: 0, to: buffer.rects.count, by: 1) + { + let barRect = buffer.rects[j] + + if (!viewPortHandler.isInBoundsTop(barRect.origin.y + barRect.size.height)) + { + break + } + + if (!viewPortHandler.isInBoundsBottom(barRect.origin.y)) + { + continue + } + + if !isSingleColor + { + // Set the color for the currently drawn value. If the index is out of bounds, reuse colors. + context.setFillColor(dataSet.color(atIndex: j).cgColor) + } + + context.fill(barRect) + + if drawBorder + { + context.setStrokeColor(borderColor.cgColor) + context.setLineWidth(borderWidth) + context.stroke(barRect) + } + + // Create and append the corresponding accessibility element to accessibilityOrderedElements (see BarChartRenderer) + if let chart = dataProvider as? BarChartView + { + let element = createAccessibleElement(withIndex: j, + container: chart, + dataSet: dataSet, + dataSetIndex: index, + stackSize: stackSize) + { (element) in + element.accessibilityFrame = barRect + } + + accessibilityOrderedElements[j/stackSize].append(element) + } + } + + context.restoreGState() + } + + open override func prepareBarHighlight( + x: Double, + y1: Double, + y2: Double, + barWidthHalf: Double, + trans: Transformer, + rect: inout CGRect) + { + let top = x - barWidthHalf + let bottom = x + barWidthHalf + let left = y1 + let right = y2 + + rect.origin.x = CGFloat(left) + rect.origin.y = CGFloat(top) + rect.size.width = CGFloat(right - left) + rect.size.height = CGFloat(bottom - top) + + trans.rectValueToPixelHorizontal(&rect, phaseY: animator.phaseY) + } + + open override func drawValues(context: CGContext) + { + // if values are drawn + if isDrawingValuesAllowed(dataProvider: dataProvider) + { + guard + let dataProvider = dataProvider, + let barData = dataProvider.barData + else { return } + + var dataSets = barData.dataSets + + let textAlign = NSTextAlignment.left + + let valueOffsetPlus: CGFloat = 5.0 + var posOffset: CGFloat + var negOffset: CGFloat + let drawValueAboveBar = dataProvider.isDrawValueAboveBarEnabled + + for dataSetIndex in 0 ..< barData.dataSetCount + { + guard let + dataSet = dataSets[dataSetIndex] as? IBarChartDataSet, + shouldDrawValues(forDataSet: dataSet) + else { continue } + + let isInverted = dataProvider.isInverted(axis: dataSet.axisDependency) + + let valueFont = dataSet.valueFont + let yOffset = -valueFont.lineHeight / 2.0 + + guard let formatter = dataSet.valueFormatter else { continue } + + let trans = dataProvider.getTransformer(forAxis: dataSet.axisDependency) + + let phaseY = animator.phaseY + + let iconsOffset = dataSet.iconsOffset + + let buffer = _buffers[dataSetIndex] + + // if only single values are drawn (sum) + if !dataSet.isStacked + { + for j in 0 ..< Int(ceil(Double(dataSet.entryCount) * animator.phaseX)) + { + guard let e = dataSet.entryForIndex(j) as? BarChartDataEntry else { continue } + + let rect = buffer.rects[j] + + let y = rect.origin.y + rect.size.height / 2.0 + + if !viewPortHandler.isInBoundsTop(rect.origin.y) + { + break + } + + if !viewPortHandler.isInBoundsX(rect.origin.x) + { + continue + } + + if !viewPortHandler.isInBoundsBottom(rect.origin.y) + { + continue + } + + let val = e.y + let valueText = formatter.stringForValue( + val, + entry: e, + dataSetIndex: dataSetIndex, + viewPortHandler: viewPortHandler) + + // calculate the correct offset depending on the draw position of the value + let valueTextWidth = valueText.size(withAttributes: [NSAttributedString.Key.font: valueFont]).width + posOffset = (drawValueAboveBar ? valueOffsetPlus : -(valueTextWidth + valueOffsetPlus)) + negOffset = (drawValueAboveBar ? -(valueTextWidth + valueOffsetPlus) : valueOffsetPlus) - rect.size.width + + if isInverted + { + posOffset = -posOffset - valueTextWidth + negOffset = -negOffset - valueTextWidth + } + + if dataSet.isDrawValuesEnabled + { + drawValue( + context: context, + value: valueText, + xPos: (rect.origin.x + rect.size.width) + + (val >= 0.0 ? posOffset : negOffset), + yPos: y + yOffset, + font: valueFont, + align: textAlign, + color: dataSet.valueTextColorAt(j)) + } + + if let icon = e.icon, dataSet.isDrawIconsEnabled + { + var px = (rect.origin.x + rect.size.width) + + (val >= 0.0 ? posOffset : negOffset) + var py = y + + px += iconsOffset.x + py += iconsOffset.y + + ChartUtils.drawImage( + context: context, + image: icon, + x: px, + y: py, + size: icon.size) + } + } + } + else + { + // if each value of a potential stack should be drawn + + var bufferIndex = 0 + + for index in 0 ..< Int(ceil(Double(dataSet.entryCount) * animator.phaseX)) + { + guard let e = dataSet.entryForIndex(index) as? BarChartDataEntry else { continue } + + let rect = buffer.rects[bufferIndex] + + let vals = e.yValues + + // we still draw stacked bars, but there is one non-stacked in between + if vals == nil + { + if !viewPortHandler.isInBoundsTop(rect.origin.y) + { + break + } + + if !viewPortHandler.isInBoundsX(rect.origin.x) + { + continue + } + + if !viewPortHandler.isInBoundsBottom(rect.origin.y) + { + continue + } + + let val = e.y + let valueText = formatter.stringForValue( + val, + entry: e, + dataSetIndex: dataSetIndex, + viewPortHandler: viewPortHandler) + + // calculate the correct offset depending on the draw position of the value + let valueTextWidth = valueText.size(withAttributes: [NSAttributedString.Key.font: valueFont]).width + posOffset = (drawValueAboveBar ? valueOffsetPlus : -(valueTextWidth + valueOffsetPlus)) + negOffset = (drawValueAboveBar ? -(valueTextWidth + valueOffsetPlus) : valueOffsetPlus) + + if isInverted + { + posOffset = -posOffset - valueTextWidth + negOffset = -negOffset - valueTextWidth + } + + if dataSet.isDrawValuesEnabled + { + drawValue( + context: context, + value: valueText, + xPos: (rect.origin.x + rect.size.width) + + (val >= 0.0 ? posOffset : negOffset), + yPos: rect.origin.y + yOffset, + font: valueFont, + align: textAlign, + color: dataSet.valueTextColorAt(index)) + } + + if let icon = e.icon, dataSet.isDrawIconsEnabled + { + var px = (rect.origin.x + rect.size.width) + + (val >= 0.0 ? posOffset : negOffset) + var py = rect.origin.y + + px += iconsOffset.x + py += iconsOffset.y + + ChartUtils.drawImage( + context: context, + image: icon, + x: px, + y: py, + size: icon.size) + } + } + else + { + let vals = vals! + var transformed = [CGPoint]() + + var posY = 0.0 + var negY = -e.negativeSum + + for k in 0 ..< vals.count + { + let value = vals[k] + var y: Double + + if value == 0.0 && (posY == 0.0 || negY == 0.0) + { + // Take care of the situation of a 0.0 value, which overlaps a non-zero bar + y = value + } + else if value >= 0.0 + { + posY += value + y = posY + } + else + { + y = negY + negY -= value + } + + transformed.append(CGPoint(x: CGFloat(y * phaseY), y: 0.0)) + } + + trans.pointValuesToPixel(&transformed) + + for k in 0 ..< transformed.count + { + let val = vals[k] + let valueText = formatter.stringForValue( + val, + entry: e, + dataSetIndex: dataSetIndex, + viewPortHandler: viewPortHandler) + + // calculate the correct offset depending on the draw position of the value + let valueTextWidth = valueText.size(withAttributes: [NSAttributedString.Key.font: valueFont]).width + posOffset = (drawValueAboveBar ? valueOffsetPlus : -(valueTextWidth + valueOffsetPlus)) + negOffset = (drawValueAboveBar ? -(valueTextWidth + valueOffsetPlus) : valueOffsetPlus) + + if isInverted + { + posOffset = -posOffset - valueTextWidth + negOffset = -negOffset - valueTextWidth + } + + let drawBelow = (val == 0.0 && negY == 0.0 && posY > 0.0) || val < 0.0 + + let x = transformed[k].x + (drawBelow ? negOffset : posOffset) + let y = rect.origin.y + rect.size.height / 2.0 + + if (!viewPortHandler.isInBoundsTop(y)) + { + break + } + + if (!viewPortHandler.isInBoundsX(x)) + { + continue + } + + if (!viewPortHandler.isInBoundsBottom(y)) + { + continue + } + + if dataSet.isDrawValuesEnabled + { + drawValue(context: context, + value: valueText, + xPos: x, + yPos: y + yOffset, + font: valueFont, + align: textAlign, + color: dataSet.valueTextColorAt(index)) + } + + if let icon = e.icon, dataSet.isDrawIconsEnabled + { + ChartUtils.drawImage( + context: context, + image: icon, + x: x + iconsOffset.x, + y: y + iconsOffset.y, + size: icon.size) + } + } + } + + bufferIndex = vals == nil ? (bufferIndex + 1) : (bufferIndex + vals!.count) + } + } + } + } + } + + open override func isDrawingValuesAllowed(dataProvider: ChartDataProvider?) -> Bool + { + guard let data = dataProvider?.data + else { return false } + return data.entryCount < Int(CGFloat(dataProvider?.maxVisibleCount ?? 0) * self.viewPortHandler.scaleY) + } + + /// Sets the drawing position of the highlight object based on the riven bar-rect. + internal override func setHighlightDrawPos(highlight high: Highlight, barRect: CGRect) + { + high.setDraw(x: barRect.midY, y: barRect.origin.x + barRect.size.width) + } +} diff --git a/Pods/Charts/Source/Charts/Renderers/LegendRenderer.swift b/Pods/Charts/Source/Charts/Renderers/LegendRenderer.swift new file mode 100755 index 00000000..f0b01d09 --- /dev/null +++ b/Pods/Charts/Source/Charts/Renderers/LegendRenderer.swift @@ -0,0 +1,575 @@ +// +// LegendRenderer.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(ChartLegendRenderer) +open class LegendRenderer: Renderer +{ + /// the legend object this renderer renders + @objc open var legend: Legend? + + @objc public init(viewPortHandler: ViewPortHandler, legend: Legend?) + { + super.init(viewPortHandler: viewPortHandler) + + self.legend = legend + } + + /// Prepares the legend and calculates all needed forms, labels and colors. + @objc open func computeLegend(data: ChartData) + { + guard let legend = legend else { return } + + if !legend.isLegendCustom + { + var entries: [LegendEntry] = [] + + // loop for building up the colors and labels used in the legend + for i in 0.. 0 && minEntries > 0) { + let labelIndex = j % minEntries + label = sLabels.indices.contains(labelIndex) ? sLabels[labelIndex] : nil + } else { + label = nil + } + + entries.append( + LegendEntry( + label: label, + form: dataSet.form, + formSize: dataSet.formSize, + formLineWidth: dataSet.formLineWidth, + formLineDashPhase: dataSet.formLineDashPhase, + formLineDashLengths: dataSet.formLineDashLengths, + formColor: clrs[j] + ) + ) + } + + if dataSet.label != nil + { + // add the legend description label + + entries.append( + LegendEntry( + label: dataSet.label, + form: .none, + formSize: CGFloat.nan, + formLineWidth: CGFloat.nan, + formLineDashPhase: 0.0, + formLineDashLengths: nil, + formColor: nil + ) + ) + } + } + else if dataSet is IPieChartDataSet + { + let pds = dataSet as! IPieChartDataSet + + for j in 0.. 0 + { + context.setLineDash(phase: formLineDashPhase, lengths: formLineDashLengths!) + } + else + { + context.setLineDash(phase: 0.0, lengths: []) + } + + context.setStrokeColor(formColor.cgColor) + + _formLineSegmentsBuffer[0].x = x + _formLineSegmentsBuffer[0].y = y + _formLineSegmentsBuffer[1].x = x + formSize + _formLineSegmentsBuffer[1].y = y + context.strokeLineSegments(between: _formLineSegmentsBuffer) + } + } + + /// Draws the provided label at the given position. + @objc open func drawLabel(context: CGContext, x: CGFloat, y: CGFloat, label: String, font: NSUIFont, textColor: NSUIColor) + { + ChartUtils.drawText(context: context, text: label, point: CGPoint(x: x, y: y), align: .left, attributes: [NSAttributedString.Key.font: font, NSAttributedString.Key.foregroundColor: textColor]) + } +} diff --git a/Pods/Charts/Source/Charts/Renderers/LineChartRenderer.swift b/Pods/Charts/Source/Charts/Renderers/LineChartRenderer.swift new file mode 100644 index 00000000..eedd92de --- /dev/null +++ b/Pods/Charts/Source/Charts/Renderers/LineChartRenderer.swift @@ -0,0 +1,781 @@ +// +// LineChartRenderer.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 LineChartRenderer: LineRadarRenderer +{ + // TODO: Currently, this nesting isn't necessary for LineCharts. However, it will make it much easier to add a custom rotor + // that navigates between datasets. + // NOTE: Unlike the other renderers, LineChartRenderer populates accessibleChartElements in drawCircles due to the nature of its drawing options. + /// A nested array of elements ordered logically (i.e not in visual/drawing order) for use with VoiceOver. + private lazy var accessibilityOrderedElements: [[NSUIAccessibilityElement]] = accessibilityCreateEmptyOrderedElements() + + @objc open weak var dataProvider: LineChartDataProvider? + + @objc public init(dataProvider: LineChartDataProvider, animator: Animator, viewPortHandler: ViewPortHandler) + { + super.init(animator: animator, viewPortHandler: viewPortHandler) + + self.dataProvider = dataProvider + } + + open override func drawData(context: CGContext) + { + guard let lineData = dataProvider?.lineData else { return } + + for i in 0 ..< lineData.dataSetCount + { + guard let set = lineData.getDataSetByIndex(i) else { continue } + + if set.isVisible + { + if !(set is ILineChartDataSet) + { + fatalError("Datasets for LineChartRenderer must conform to ILineChartDataSet") + } + + drawDataSet(context: context, dataSet: set as! ILineChartDataSet) + } + } + } + + @objc open func drawDataSet(context: CGContext, dataSet: ILineChartDataSet) + { + if dataSet.entryCount < 1 + { + return + } + + context.saveGState() + + context.setLineWidth(dataSet.lineWidth) + if dataSet.lineDashLengths != nil + { + context.setLineDash(phase: dataSet.lineDashPhase, lengths: dataSet.lineDashLengths!) + } + else + { + context.setLineDash(phase: 0.0, lengths: []) + } + + context.setLineCap(dataSet.lineCapType) + + // if drawing cubic lines is enabled + switch dataSet.mode + { + case .linear: fallthrough + case .stepped: + drawLinear(context: context, dataSet: dataSet) + + case .cubicBezier: + drawCubicBezier(context: context, dataSet: dataSet) + + case .horizontalBezier: + drawHorizontalBezier(context: context, dataSet: dataSet) + } + + context.restoreGState() + } + + @objc open func drawCubicBezier(context: CGContext, dataSet: ILineChartDataSet) + { + guard let dataProvider = dataProvider else { return } + + let trans = dataProvider.getTransformer(forAxis: dataSet.axisDependency) + + let phaseY = animator.phaseY + + _xBounds.set(chart: dataProvider, dataSet: dataSet, animator: animator) + + // get the color that is specified for this position from the DataSet + let drawingColor = dataSet.colors.first! + + let intensity = dataSet.cubicIntensity + + // the path for the cubic-spline + let cubicPath = CGMutablePath() + + let valueToPixelMatrix = trans.valueToPixelMatrix + + if _xBounds.range >= 1 + { + var prevDx: CGFloat = 0.0 + var prevDy: CGFloat = 0.0 + var curDx: CGFloat = 0.0 + var curDy: CGFloat = 0.0 + + // Take an extra point from the left, and an extra from the right. + // That's because we need 4 points for a cubic bezier (cubic=4), otherwise we get lines moving and doing weird stuff on the edges of the chart. + // So in the starting `prev` and `cur`, go -2, -1 + // And in the `lastIndex`, add +1 + + let firstIndex = _xBounds.min + 1 + let lastIndex = _xBounds.min + _xBounds.range + + var prevPrev: ChartDataEntry! = nil + var prev: ChartDataEntry! = dataSet.entryForIndex(max(firstIndex - 2, 0)) + var cur: ChartDataEntry! = dataSet.entryForIndex(max(firstIndex - 1, 0)) + var next: ChartDataEntry! = cur + var nextIndex: Int = -1 + + if cur == nil { return } + + // let the spline start + cubicPath.move(to: CGPoint(x: CGFloat(cur.x), y: CGFloat(cur.y * phaseY)), transform: valueToPixelMatrix) + + for j in stride(from: firstIndex, through: lastIndex, by: 1) + { + prevPrev = prev + prev = cur + cur = nextIndex == j ? next : dataSet.entryForIndex(j) + + nextIndex = j + 1 < dataSet.entryCount ? j + 1 : j + next = dataSet.entryForIndex(nextIndex) + + if next == nil { break } + + prevDx = CGFloat(cur.x - prevPrev.x) * intensity + prevDy = CGFloat(cur.y - prevPrev.y) * intensity + curDx = CGFloat(next.x - prev.x) * intensity + curDy = CGFloat(next.y - prev.y) * intensity + + cubicPath.addCurve( + to: CGPoint( + x: CGFloat(cur.x), + y: CGFloat(cur.y) * CGFloat(phaseY)), + control1: CGPoint( + x: CGFloat(prev.x) + prevDx, + y: (CGFloat(prev.y) + prevDy) * CGFloat(phaseY)), + control2: CGPoint( + x: CGFloat(cur.x) - curDx, + y: (CGFloat(cur.y) - curDy) * CGFloat(phaseY)), + transform: valueToPixelMatrix) + } + } + + context.saveGState() + + if dataSet.isDrawFilledEnabled + { + // Copy this path because we make changes to it + let fillPath = cubicPath.mutableCopy() + + drawCubicFill(context: context, dataSet: dataSet, spline: fillPath!, matrix: valueToPixelMatrix, bounds: _xBounds) + } + + context.beginPath() + context.addPath(cubicPath) + context.setStrokeColor(drawingColor.cgColor) + context.strokePath() + + context.restoreGState() + } + + @objc open func drawHorizontalBezier(context: CGContext, dataSet: ILineChartDataSet) + { + guard let dataProvider = dataProvider else { return } + + let trans = dataProvider.getTransformer(forAxis: dataSet.axisDependency) + + let phaseY = animator.phaseY + + _xBounds.set(chart: dataProvider, dataSet: dataSet, animator: animator) + + // get the color that is specified for this position from the DataSet + let drawingColor = dataSet.colors.first! + + // the path for the cubic-spline + let cubicPath = CGMutablePath() + + let valueToPixelMatrix = trans.valueToPixelMatrix + + if _xBounds.range >= 1 + { + var prev: ChartDataEntry! = dataSet.entryForIndex(_xBounds.min) + var cur: ChartDataEntry! = prev + + if cur == nil { return } + + // let the spline start + cubicPath.move(to: CGPoint(x: CGFloat(cur.x), y: CGFloat(cur.y * phaseY)), transform: valueToPixelMatrix) + + for j in _xBounds.dropFirst() + { + prev = cur + cur = dataSet.entryForIndex(j) + + let cpx = CGFloat(prev.x + (cur.x - prev.x) / 2.0) + + cubicPath.addCurve( + to: CGPoint( + x: CGFloat(cur.x), + y: CGFloat(cur.y * phaseY)), + control1: CGPoint( + x: cpx, + y: CGFloat(prev.y * phaseY)), + control2: CGPoint( + x: cpx, + y: CGFloat(cur.y * phaseY)), + transform: valueToPixelMatrix) + } + } + + context.saveGState() + + if dataSet.isDrawFilledEnabled + { + // Copy this path because we make changes to it + let fillPath = cubicPath.mutableCopy() + + drawCubicFill(context: context, dataSet: dataSet, spline: fillPath!, matrix: valueToPixelMatrix, bounds: _xBounds) + } + + context.beginPath() + context.addPath(cubicPath) + context.setStrokeColor(drawingColor.cgColor) + context.strokePath() + + context.restoreGState() + } + + open func drawCubicFill( + context: CGContext, + dataSet: ILineChartDataSet, + spline: CGMutablePath, + matrix: CGAffineTransform, + bounds: XBounds) + { + guard + let dataProvider = dataProvider + else { return } + + if bounds.range <= 0 + { + return + } + + let fillMin = dataSet.fillFormatter?.getFillLinePosition(dataSet: dataSet, dataProvider: dataProvider) ?? 0.0 + + var pt1 = CGPoint(x: CGFloat(dataSet.entryForIndex(bounds.min + bounds.range)?.x ?? 0.0), y: fillMin) + var pt2 = CGPoint(x: CGFloat(dataSet.entryForIndex(bounds.min)?.x ?? 0.0), y: fillMin) + pt1 = pt1.applying(matrix) + pt2 = pt2.applying(matrix) + + spline.addLine(to: pt1) + spline.addLine(to: pt2) + spline.closeSubpath() + + if dataSet.fill != nil + { + drawFilledPath(context: context, path: spline, fill: dataSet.fill!, fillAlpha: dataSet.fillAlpha) + } + else + { + drawFilledPath(context: context, path: spline, fillColor: dataSet.fillColor, fillAlpha: dataSet.fillAlpha) + } + } + + private var _lineSegments = [CGPoint](repeating: CGPoint(), count: 2) + + @objc open func drawLinear(context: CGContext, dataSet: ILineChartDataSet) + { + guard let dataProvider = dataProvider else { return } + + let trans = dataProvider.getTransformer(forAxis: dataSet.axisDependency) + + let valueToPixelMatrix = trans.valueToPixelMatrix + + let entryCount = dataSet.entryCount + let isDrawSteppedEnabled = dataSet.mode == .stepped + let pointsPerEntryPair = isDrawSteppedEnabled ? 4 : 2 + + let phaseY = animator.phaseY + + _xBounds.set(chart: dataProvider, dataSet: dataSet, animator: animator) + + // if drawing filled is enabled + if dataSet.isDrawFilledEnabled && entryCount > 0 + { + drawLinearFill(context: context, dataSet: dataSet, trans: trans, bounds: _xBounds) + } + + context.saveGState() + + if _lineSegments.count != pointsPerEntryPair + { + // Allocate once in correct size + _lineSegments = [CGPoint](repeating: CGPoint(), count: pointsPerEntryPair) + } + + for j in stride(from: _xBounds.min, through: _xBounds.range + _xBounds.min, by: 1) + { + var e: ChartDataEntry! = dataSet.entryForIndex(j) + + if e == nil { continue } + + _lineSegments[0].x = CGFloat(e.x) + _lineSegments[0].y = CGFloat(e.y * phaseY) + + if j < _xBounds.max + { + e = dataSet.entryForIndex(j + 1) + + if e == nil { break } + + if isDrawSteppedEnabled + { + _lineSegments[1] = CGPoint(x: CGFloat(e.x), y: _lineSegments[0].y) + _lineSegments[2] = _lineSegments[1] + _lineSegments[3] = CGPoint(x: CGFloat(e.x), y: CGFloat(e.y * phaseY)) + } + else + { + _lineSegments[1] = CGPoint(x: CGFloat(e.x), y: CGFloat(e.y * phaseY)) + } + } + else + { + _lineSegments[1] = _lineSegments[0] + } + + for i in 0..<_lineSegments.count + { + _lineSegments[i] = _lineSegments[i].applying(valueToPixelMatrix) + } + + if (!viewPortHandler.isInBoundsRight(_lineSegments[0].x)) + { + break + } + + // make sure the lines don't do shitty things outside bounds + if !viewPortHandler.isInBoundsLeft(_lineSegments[1].x) + || (!viewPortHandler.isInBoundsTop(_lineSegments[0].y) && !viewPortHandler.isInBoundsBottom(_lineSegments[1].y)) + { + continue + } + + // get the color that is set for this line-segment + context.setStrokeColor(dataSet.color(atIndex: j).cgColor) + context.strokeLineSegments(between: _lineSegments) + } + + context.restoreGState() + } + + open func drawLinearFill(context: CGContext, dataSet: ILineChartDataSet, trans: Transformer, bounds: XBounds) + { + guard let dataProvider = dataProvider else { return } + + let filled = generateFilledPath( + dataSet: dataSet, + fillMin: dataSet.fillFormatter?.getFillLinePosition(dataSet: dataSet, dataProvider: dataProvider) ?? 0.0, + bounds: bounds, + matrix: trans.valueToPixelMatrix) + + if dataSet.fill != nil + { + drawFilledPath(context: context, path: filled, fill: dataSet.fill!, fillAlpha: dataSet.fillAlpha) + } + else + { + drawFilledPath(context: context, path: filled, fillColor: dataSet.fillColor, fillAlpha: dataSet.fillAlpha) + } + } + + /// Generates the path that is used for filled drawing. + private func generateFilledPath(dataSet: ILineChartDataSet, fillMin: CGFloat, bounds: XBounds, matrix: CGAffineTransform) -> CGPath + { + let phaseY = animator.phaseY + let isDrawSteppedEnabled = dataSet.mode == .stepped + let matrix = matrix + + var e: ChartDataEntry! + + let filled = CGMutablePath() + + e = dataSet.entryForIndex(bounds.min) + if e != nil + { + filled.move(to: CGPoint(x: CGFloat(e.x), y: fillMin), transform: matrix) + filled.addLine(to: CGPoint(x: CGFloat(e.x), y: CGFloat(e.y * phaseY)), transform: matrix) + } + + // create a new path + for x in stride(from: (bounds.min + 1), through: bounds.range + bounds.min, by: 1) + { + guard let e = dataSet.entryForIndex(x) else { continue } + + if isDrawSteppedEnabled + { + guard let ePrev = dataSet.entryForIndex(x-1) else { continue } + filled.addLine(to: CGPoint(x: CGFloat(e.x), y: CGFloat(ePrev.y * phaseY)), transform: matrix) + } + + filled.addLine(to: CGPoint(x: CGFloat(e.x), y: CGFloat(e.y * phaseY)), transform: matrix) + } + + // close up + e = dataSet.entryForIndex(bounds.range + bounds.min) + if e != nil + { + filled.addLine(to: CGPoint(x: CGFloat(e.x), y: fillMin), transform: matrix) + } + filled.closeSubpath() + + return filled + } + + open override func drawValues(context: CGContext) + { + guard + let dataProvider = dataProvider, + let lineData = dataProvider.lineData + else { return } + + if isDrawingValuesAllowed(dataProvider: dataProvider) + { + var dataSets = lineData.dataSets + + let phaseY = animator.phaseY + + var pt = CGPoint() + + for i in 0 ..< dataSets.count + { + guard let + dataSet = dataSets[i] as? ILineChartDataSet, + shouldDrawValues(forDataSet: dataSet) + else { continue } + + let valueFont = dataSet.valueFont + + guard let formatter = dataSet.valueFormatter else { continue } + + let trans = dataProvider.getTransformer(forAxis: dataSet.axisDependency) + let valueToPixelMatrix = trans.valueToPixelMatrix + + let iconsOffset = dataSet.iconsOffset + + // make sure the values do not interfear with the circles + var valOffset = Int(dataSet.circleRadius * 1.75) + + if !dataSet.isDrawCirclesEnabled + { + valOffset = valOffset / 2 + } + + _xBounds.set(chart: dataProvider, dataSet: dataSet, animator: animator) + + for j in _xBounds + { + guard let e = dataSet.entryForIndex(j) else { break } + + pt.x = CGFloat(e.x) + pt.y = CGFloat(e.y * phaseY) + pt = pt.applying(valueToPixelMatrix) + + if (!viewPortHandler.isInBoundsRight(pt.x)) + { + break + } + + if (!viewPortHandler.isInBoundsLeft(pt.x) || !viewPortHandler.isInBoundsY(pt.y)) + { + continue + } + + if dataSet.isDrawValuesEnabled { + ChartUtils.drawText( + context: context, + text: formatter.stringForValue( + e.y, + entry: e, + dataSetIndex: i, + viewPortHandler: viewPortHandler), + point: CGPoint( + x: pt.x, + y: pt.y - CGFloat(valOffset) - valueFont.lineHeight), + align: .center, + attributes: [NSAttributedString.Key.font: valueFont, NSAttributedString.Key.foregroundColor: dataSet.valueTextColorAt(j)]) + } + + if let icon = e.icon, dataSet.isDrawIconsEnabled + { + ChartUtils.drawImage(context: context, + image: icon, + x: pt.x + iconsOffset.x, + y: pt.y + iconsOffset.y, + size: icon.size) + } + } + } + } + } + + open override func drawExtras(context: CGContext) + { + drawCircles(context: context) + } + + private func drawCircles(context: CGContext) + { + guard + let dataProvider = dataProvider, + let lineData = dataProvider.lineData + else { return } + + let phaseY = animator.phaseY + + let dataSets = lineData.dataSets + + var pt = CGPoint() + var rect = CGRect() + + // If we redraw the data, remove and repopulate accessible elements to update label values and frames + accessibleChartElements.removeAll() + accessibilityOrderedElements = accessibilityCreateEmptyOrderedElements() + + // Make the chart header the first element in the accessible elements array + if let chart = dataProvider as? LineChartView { + let element = createAccessibleHeader(usingChart: chart, + andData: lineData, + withDefaultDescription: "Line Chart") + accessibleChartElements.append(element) + } + + context.saveGState() + + for i in 0 ..< dataSets.count + { + guard let dataSet = lineData.getDataSetByIndex(i) as? ILineChartDataSet else { continue } + + if !dataSet.isVisible || dataSet.entryCount == 0 + { + continue + } + + let trans = dataProvider.getTransformer(forAxis: dataSet.axisDependency) + let valueToPixelMatrix = trans.valueToPixelMatrix + + _xBounds.set(chart: dataProvider, dataSet: dataSet, animator: animator) + + let circleRadius = dataSet.circleRadius + let circleDiameter = circleRadius * 2.0 + let circleHoleRadius = dataSet.circleHoleRadius + let circleHoleDiameter = circleHoleRadius * 2.0 + + let drawCircleHole = dataSet.isDrawCircleHoleEnabled && + circleHoleRadius < circleRadius && + circleHoleRadius > 0.0 + let drawTransparentCircleHole = drawCircleHole && + (dataSet.circleHoleColor == nil || + dataSet.circleHoleColor == NSUIColor.clear) + + for j in _xBounds + { + guard let e = dataSet.entryForIndex(j) else { break } + + pt.x = CGFloat(e.x) + pt.y = CGFloat(e.y * phaseY) + pt = pt.applying(valueToPixelMatrix) + + if (!viewPortHandler.isInBoundsRight(pt.x)) + { + break + } + + // make sure the circles don't do shitty things outside bounds + if (!viewPortHandler.isInBoundsLeft(pt.x) || !viewPortHandler.isInBoundsY(pt.y)) + { + continue + } + + // Accessibility element geometry + let scaleFactor: CGFloat = 3 + let accessibilityRect = CGRect(x: pt.x - (scaleFactor * circleRadius), + y: pt.y - (scaleFactor * circleRadius), + width: scaleFactor * circleDiameter, + height: scaleFactor * circleDiameter) + // Create and append the corresponding accessibility element to accessibilityOrderedElements + if let chart = dataProvider as? LineChartView + { + let element = createAccessibleElement(withIndex: j, + container: chart, + dataSet: dataSet, + dataSetIndex: i) + { (element) in + element.accessibilityFrame = accessibilityRect + } + + accessibilityOrderedElements[i].append(element) + } + + if !dataSet.isDrawCirclesEnabled + { + continue + } + + context.setFillColor(dataSet.getCircleColor(atIndex: j)!.cgColor) + + rect.origin.x = pt.x - circleRadius + rect.origin.y = pt.y - circleRadius + rect.size.width = circleDiameter + rect.size.height = circleDiameter + + if drawTransparentCircleHole + { + // Begin path for circle with hole + context.beginPath() + context.addEllipse(in: rect) + + // Cut hole in path + rect.origin.x = pt.x - circleHoleRadius + rect.origin.y = pt.y - circleHoleRadius + rect.size.width = circleHoleDiameter + rect.size.height = circleHoleDiameter + context.addEllipse(in: rect) + + // Fill in-between + context.fillPath(using: .evenOdd) + } + else + { + context.fillEllipse(in: rect) + + if drawCircleHole + { + context.setFillColor(dataSet.circleHoleColor!.cgColor) + + // The hole rect + rect.origin.x = pt.x - circleHoleRadius + rect.origin.y = pt.y - circleHoleRadius + rect.size.width = circleHoleDiameter + rect.size.height = circleHoleDiameter + + context.fillEllipse(in: rect) + } + } + } + } + + context.restoreGState() + + // Merge nested ordered arrays into the single accessibleChartElements. + accessibleChartElements.append(contentsOf: accessibilityOrderedElements.flatMap { $0 } ) + accessibilityPostLayoutChangedNotification() + } + + open override func drawHighlighted(context: CGContext, indices: [Highlight]) + { + guard + let dataProvider = dataProvider, + let lineData = dataProvider.lineData + else { return } + + let chartXMax = dataProvider.chartXMax + + context.saveGState() + + for high in indices + { + guard let set = lineData.getDataSetByIndex(high.dataSetIndex) as? ILineChartDataSet + , set.isHighlightEnabled + else { continue } + + guard let e = set.entryForXValue(high.x, closestToY: high.y) else { continue } + + if !isInBoundsX(entry: e, dataSet: set) + { + continue + } + + context.setStrokeColor(set.highlightColor.cgColor) + context.setLineWidth(set.highlightLineWidth) + if set.highlightLineDashLengths != nil + { + context.setLineDash(phase: set.highlightLineDashPhase, lengths: set.highlightLineDashLengths!) + } + else + { + context.setLineDash(phase: 0.0, lengths: []) + } + + let x = high.x // get the x-position + let y = high.y * Double(animator.phaseY) + + if x > chartXMax * animator.phaseX + { + continue + } + + let trans = dataProvider.getTransformer(forAxis: set.axisDependency) + + let pt = trans.pixelForValues(x: x, y: y) + + high.setDraw(pt: pt) + + // draw the lines + drawHighlightLines(context: context, point: pt, set: set) + } + + context.restoreGState() + } + + /// Creates a nested array of empty subarrays each of which will be populated with NSUIAccessibilityElements. + /// This is marked internal to support HorizontalBarChartRenderer as well. + private func accessibilityCreateEmptyOrderedElements() -> [[NSUIAccessibilityElement]] + { + guard let chart = dataProvider as? LineChartView else { return [] } + + let dataSetCount = chart.lineData?.dataSetCount ?? 0 + + return Array(repeating: [NSUIAccessibilityElement](), + count: dataSetCount) + } + + /// Creates an NSUIAccessibleElement representing the smallest meaningful bar of the chart + /// i.e. in case of a stacked chart, this returns each stack, not the combined bar. + /// Note that it is marked internal to support subclass modification in the HorizontalBarChart. + private func createAccessibleElement(withIndex idx: Int, + container: LineChartView, + dataSet: ILineChartDataSet, + dataSetIndex: Int, + modifier: (NSUIAccessibilityElement) -> ()) -> NSUIAccessibilityElement + { + let element = NSUIAccessibilityElement(accessibilityContainer: container) + let xAxis = container.xAxis + + guard let e = dataSet.entryForIndex(idx) else { return element } + guard let dataProvider = dataProvider else { return element } + + // NOTE: The formatter can cause issues when the x-axis labels are consecutive ints. + // i.e. due to the Double conversion, if there are more than one data set that are grouped, + // there is the possibility of some labels being rounded up. A floor() might fix this, but seems to be a brute force solution. + let label = xAxis.valueFormatter?.stringForValue(e.x, axis: xAxis) ?? "\(e.x)" + + let elementValueText = dataSet.valueFormatter?.stringForValue(e.y, + entry: e, + dataSetIndex: dataSetIndex, + viewPortHandler: viewPortHandler) ?? "\(e.y)" + + let dataSetCount = dataProvider.lineData?.dataSetCount ?? -1 + let doesContainMultipleDataSets = dataSetCount > 1 + + element.accessibilityLabel = "\(doesContainMultipleDataSets ? (dataSet.label ?? "") + ", " : "") \(label): \(elementValueText)" + + modifier(element) + + return element + } +} diff --git a/Pods/Charts/Source/Charts/Renderers/LineRadarRenderer.swift b/Pods/Charts/Source/Charts/Renderers/LineRadarRenderer.swift new file mode 100644 index 00000000..6b028250 --- /dev/null +++ b/Pods/Charts/Source/Charts/Renderers/LineRadarRenderer.swift @@ -0,0 +1,54 @@ +// +// LineRadarRenderer.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(LineRadarChartRenderer) +open class LineRadarRenderer: LineScatterCandleRadarRenderer +{ + public override init(animator: Animator, viewPortHandler: ViewPortHandler) + { + super.init(animator: animator, viewPortHandler: viewPortHandler) + } + + /// Draws the provided path in filled mode with the provided drawable. + @objc open func drawFilledPath(context: CGContext, path: CGPath, fill: Fill, fillAlpha: CGFloat) + { + + context.saveGState() + context.beginPath() + context.addPath(path) + + // filled is usually drawn with less alpha + context.setAlpha(fillAlpha) + + fill.fillPath(context: context, rect: viewPortHandler.contentRect) + + context.restoreGState() + } + + /// Draws the provided path in filled mode with the provided color and alpha. + @objc open func drawFilledPath(context: CGContext, path: CGPath, fillColor: NSUIColor, fillAlpha: CGFloat) + { + context.saveGState() + context.beginPath() + context.addPath(path) + + // filled is usually drawn with less alpha + context.setAlpha(fillAlpha) + + context.setFillColor(fillColor.cgColor) + context.fillPath() + + context.restoreGState() + } +} diff --git a/Pods/Charts/Source/Charts/Renderers/LineScatterCandleRadarRenderer.swift b/Pods/Charts/Source/Charts/Renderers/LineScatterCandleRadarRenderer.swift new file mode 100644 index 00000000..05203caf --- /dev/null +++ b/Pods/Charts/Source/Charts/Renderers/LineScatterCandleRadarRenderer.swift @@ -0,0 +1,49 @@ +// +// LineScatterCandleRadarRenderer.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(LineScatterCandleRadarChartRenderer) +open class LineScatterCandleRadarRenderer: BarLineScatterCandleBubbleRenderer +{ + public override init(animator: Animator, viewPortHandler: ViewPortHandler) + { + super.init(animator: animator, viewPortHandler: viewPortHandler) + } + + /// Draws vertical & horizontal highlight-lines if enabled. + /// :param: context + /// :param: points + /// :param: horizontal + /// :param: vertical + @objc open func drawHighlightLines(context: CGContext, point: CGPoint, set: ILineScatterCandleRadarChartDataSet) + { + + // draw vertical highlight lines + if set.isVerticalHighlightIndicatorEnabled + { + context.beginPath() + context.move(to: CGPoint(x: point.x, y: viewPortHandler.contentTop)) + context.addLine(to: CGPoint(x: point.x, y: viewPortHandler.contentBottom)) + context.strokePath() + } + + // draw horizontal highlight lines + if set.isHorizontalHighlightIndicatorEnabled + { + context.beginPath() + context.move(to: CGPoint(x: viewPortHandler.contentLeft, y: point.y)) + context.addLine(to: CGPoint(x: viewPortHandler.contentRight, y: point.y)) + context.strokePath() + } + } +} diff --git a/Pods/Charts/Source/Charts/Renderers/PieChartRenderer.swift b/Pods/Charts/Source/Charts/Renderers/PieChartRenderer.swift new file mode 100644 index 00000000..c9716111 --- /dev/null +++ b/Pods/Charts/Source/Charts/Renderers/PieChartRenderer.swift @@ -0,0 +1,929 @@ +// +// PieChartRenderer.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 PieChartRenderer: DataRenderer +{ + @objc open weak var chart: PieChartView? + + @objc public init(chart: PieChartView, animator: Animator, viewPortHandler: ViewPortHandler) + { + super.init(animator: animator, viewPortHandler: viewPortHandler) + + self.chart = chart + } + + open override func drawData(context: CGContext) + { + guard let chart = chart else { return } + + let pieData = chart.data + + if pieData != nil + { + // If we redraw the data, remove and repopulate accessible elements to update label values and frames + accessibleChartElements.removeAll() + + for set in pieData!.dataSets as! [IPieChartDataSet] + where set.isVisible && set.entryCount > 0 + { + drawDataSet(context: context, dataSet: set) + } + } + } + + @objc open func calculateMinimumRadiusForSpacedSlice( + center: CGPoint, + radius: CGFloat, + angle: CGFloat, + arcStartPointX: CGFloat, + arcStartPointY: CGFloat, + startAngle: CGFloat, + sweepAngle: CGFloat) -> CGFloat + { + let angleMiddle = startAngle + sweepAngle / 2.0 + + // Other point of the arc + let arcEndPointX = center.x + radius * cos((startAngle + sweepAngle).DEG2RAD) + let arcEndPointY = center.y + radius * sin((startAngle + sweepAngle).DEG2RAD) + + // Middle point on the arc + let arcMidPointX = center.x + radius * cos(angleMiddle.DEG2RAD) + let arcMidPointY = center.y + radius * sin(angleMiddle.DEG2RAD) + + // This is the base of the contained triangle + let basePointsDistance = sqrt( + pow(arcEndPointX - arcStartPointX, 2) + + pow(arcEndPointY - arcStartPointY, 2)) + + // After reducing space from both sides of the "slice", + // the angle of the contained triangle should stay the same. + // So let's find out the height of that triangle. + let containedTriangleHeight = (basePointsDistance / 2.0 * + tan((180.0 - angle).DEG2RAD / 2.0)) + + // Now we subtract that from the radius + var spacedRadius = radius - containedTriangleHeight + + // And now subtract the height of the arc that's between the triangle and the outer circle + spacedRadius -= sqrt( + pow(arcMidPointX - (arcEndPointX + arcStartPointX) / 2.0, 2) + + pow(arcMidPointY - (arcEndPointY + arcStartPointY) / 2.0, 2)) + + return spacedRadius + } + + /// Calculates the sliceSpace to use based on visible values and their size compared to the set sliceSpace. + @objc open func getSliceSpace(dataSet: IPieChartDataSet) -> CGFloat + { + guard + dataSet.automaticallyDisableSliceSpacing, + let data = chart?.data as? PieChartData + else { return dataSet.sliceSpace } + + let spaceSizeRatio = dataSet.sliceSpace / min(viewPortHandler.contentWidth, viewPortHandler.contentHeight) + let minValueRatio = dataSet.yMin / data.yValueSum * 2.0 + + let sliceSpace = spaceSizeRatio > CGFloat(minValueRatio) + ? 0.0 + : dataSet.sliceSpace + + return sliceSpace + } + + @objc open func drawDataSet(context: CGContext, dataSet: IPieChartDataSet) + { + guard let chart = chart else {return } + + var angle: CGFloat = 0.0 + let rotationAngle = chart.rotationAngle + + let phaseX = animator.phaseX + let phaseY = animator.phaseY + + let entryCount = dataSet.entryCount + var drawAngles = chart.drawAngles + let center = chart.centerCircleBox + let radius = chart.radius + let drawInnerArc = chart.drawHoleEnabled && !chart.drawSlicesUnderHoleEnabled + let userInnerRadius = drawInnerArc ? radius * chart.holeRadiusPercent : 0.0 + + var visibleAngleCount = 0 + for j in 0 ..< entryCount + { + guard let e = dataSet.entryForIndex(j) else { continue } + if ((abs(e.y) > Double.ulpOfOne)) + { + visibleAngleCount += 1 + } + } + + let sliceSpace = visibleAngleCount <= 1 ? 0.0 : getSliceSpace(dataSet: dataSet) + + context.saveGState() + + // Make the chart header the first element in the accessible elements array + // We can do this in drawDataSet, since we know PieChartView can have only 1 dataSet + // Also since there's only 1 dataset, we don't use the typical createAccessibleHeader() here. + // NOTE: - Since we want to summarize the total count of slices/portions/elements, use a default string here + // This is unlike when we are naming individual slices, wherein it's alright to not use a prefix as descriptor. + // i.e. We want to VO to say "3 Elements" even if the developer didn't specify an accessibility prefix + // If prefix is unspecified it is safe to assume they did not want to use "Element 1", so that uses a default empty string + let prefix: String = chart.data?.accessibilityEntryLabelPrefix ?? "Element" + let description = chart.chartDescription?.text ?? dataSet.label ?? chart.centerText ?? "Pie Chart" + + let + element = NSUIAccessibilityElement(accessibilityContainer: chart) + element.accessibilityLabel = description + ". \(entryCount) \(prefix + (entryCount == 1 ? "" : "s"))" + element.accessibilityFrame = chart.bounds + element.isHeader = true + accessibleChartElements.append(element) + + for j in 0 ..< entryCount + { + let sliceAngle = drawAngles[j] + var innerRadius = userInnerRadius + + guard let e = dataSet.entryForIndex(j) else { continue } + + // draw only if the value is greater than zero + if (abs(e.y) > Double.ulpOfOne) + { + if !chart.needsHighlight(index: j) + { + let accountForSliceSpacing = sliceSpace > 0.0 && sliceAngle <= 180.0 + + context.setFillColor(dataSet.color(atIndex: j).cgColor) + + let sliceSpaceAngleOuter = visibleAngleCount == 1 ? + 0.0 : + sliceSpace / radius.DEG2RAD + let startAngleOuter = rotationAngle + (angle + sliceSpaceAngleOuter / 2.0) * CGFloat(phaseY) + var sweepAngleOuter = (sliceAngle - sliceSpaceAngleOuter) * CGFloat(phaseY) + if sweepAngleOuter < 0.0 + { + sweepAngleOuter = 0.0 + } + + let arcStartPointX = center.x + radius * cos(startAngleOuter.DEG2RAD) + let arcStartPointY = center.y + radius * sin(startAngleOuter.DEG2RAD) + + let path = CGMutablePath() + + path.move(to: CGPoint(x: arcStartPointX, + y: arcStartPointY)) + + path.addRelativeArc(center: center, radius: radius, startAngle: startAngleOuter.DEG2RAD, delta: sweepAngleOuter.DEG2RAD) + + if drawInnerArc && + (innerRadius > 0.0 || accountForSliceSpacing) + { + if accountForSliceSpacing + { + var minSpacedRadius = calculateMinimumRadiusForSpacedSlice( + center: center, + radius: radius, + angle: sliceAngle * CGFloat(phaseY), + arcStartPointX: arcStartPointX, + arcStartPointY: arcStartPointY, + startAngle: startAngleOuter, + sweepAngle: sweepAngleOuter) + if minSpacedRadius < 0.0 + { + minSpacedRadius = -minSpacedRadius + } + innerRadius = min(max(innerRadius, minSpacedRadius), radius) + } + + let sliceSpaceAngleInner = visibleAngleCount == 1 || innerRadius == 0.0 ? + 0.0 : + sliceSpace / innerRadius.DEG2RAD + let startAngleInner = rotationAngle + (angle + sliceSpaceAngleInner / 2.0) * CGFloat(phaseY) + var sweepAngleInner = (sliceAngle - sliceSpaceAngleInner) * CGFloat(phaseY) + if sweepAngleInner < 0.0 + { + sweepAngleInner = 0.0 + } + let endAngleInner = startAngleInner + sweepAngleInner + + path.addLine( + to: CGPoint( + x: center.x + innerRadius * cos(endAngleInner.DEG2RAD), + y: center.y + innerRadius * sin(endAngleInner.DEG2RAD))) + + path.addRelativeArc(center: center, radius: innerRadius, startAngle: endAngleInner.DEG2RAD, delta: -sweepAngleInner.DEG2RAD) + } + else + { + if accountForSliceSpacing + { + let angleMiddle = startAngleOuter + sweepAngleOuter / 2.0 + + let sliceSpaceOffset = + calculateMinimumRadiusForSpacedSlice( + center: center, + radius: radius, + angle: sliceAngle * CGFloat(phaseY), + arcStartPointX: arcStartPointX, + arcStartPointY: arcStartPointY, + startAngle: startAngleOuter, + sweepAngle: sweepAngleOuter) + + let arcEndPointX = center.x + sliceSpaceOffset * cos(angleMiddle.DEG2RAD) + let arcEndPointY = center.y + sliceSpaceOffset * sin(angleMiddle.DEG2RAD) + + path.addLine( + to: CGPoint( + x: arcEndPointX, + y: arcEndPointY)) + } + else + { + path.addLine(to: center) + } + } + + path.closeSubpath() + + context.beginPath() + context.addPath(path) + context.fillPath(using: .evenOdd) + + let axElement = createAccessibleElement(withIndex: j, + container: chart, + dataSet: dataSet) + { (element) in + element.accessibilityFrame = path.boundingBoxOfPath + } + + accessibleChartElements.append(axElement) + } + } + + angle += sliceAngle * CGFloat(phaseX) + } + + // Post this notification to let VoiceOver account for the redrawn frames + accessibilityPostLayoutChangedNotification() + + context.restoreGState() + } + + open override func drawValues(context: CGContext) + { + guard + let chart = chart, + let data = chart.data + else { return } + + let center = chart.centerCircleBox + + // get whole the radius + let radius = chart.radius + let rotationAngle = chart.rotationAngle + var drawAngles = chart.drawAngles + var absoluteAngles = chart.absoluteAngles + + let phaseX = animator.phaseX + let phaseY = animator.phaseY + + var labelRadiusOffset = radius / 10.0 * 3.0 + + if chart.drawHoleEnabled + { + labelRadiusOffset = (radius - (radius * chart.holeRadiusPercent)) / 2.0 + } + + let labelRadius = radius - labelRadiusOffset + + var dataSets = data.dataSets + + let yValueSum = (data as! PieChartData).yValueSum + + let drawEntryLabels = chart.isDrawEntryLabelsEnabled + let usePercentValuesEnabled = chart.usePercentValuesEnabled + let entryLabelColor = chart.entryLabelColor + let entryLabelFont = chart.entryLabelFont + + var angle: CGFloat = 0.0 + var xIndex = 0 + + context.saveGState() + defer { context.restoreGState() } + + for i in 0 ..< dataSets.count + { + guard let dataSet = dataSets[i] as? IPieChartDataSet else { continue } + + let drawValues = dataSet.isDrawValuesEnabled + + if !drawValues && !drawEntryLabels && !dataSet.isDrawIconsEnabled + { + continue + } + + let iconsOffset = dataSet.iconsOffset + + let xValuePosition = dataSet.xValuePosition + let yValuePosition = dataSet.yValuePosition + + let valueFont = dataSet.valueFont + let entryLabelFont = dataSet.entryLabelFont + let lineHeight = valueFont.lineHeight + + guard let formatter = dataSet.valueFormatter else { continue } + + for j in 0 ..< dataSet.entryCount + { + guard let e = dataSet.entryForIndex(j) else { continue } + let pe = e as? PieChartDataEntry + + if xIndex == 0 + { + angle = 0.0 + } + else + { + angle = absoluteAngles[xIndex - 1] * CGFloat(phaseX) + } + + let sliceAngle = drawAngles[xIndex] + let sliceSpace = getSliceSpace(dataSet: dataSet) + let sliceSpaceMiddleAngle = sliceSpace / labelRadius.DEG2RAD + + // offset needed to center the drawn text in the slice + let angleOffset = (sliceAngle - sliceSpaceMiddleAngle / 2.0) / 2.0 + + angle = angle + angleOffset + + let transformedAngle = rotationAngle + angle * CGFloat(phaseY) + + let value = usePercentValuesEnabled ? e.y / yValueSum * 100.0 : e.y + let valueText = formatter.stringForValue( + value, + entry: e, + dataSetIndex: i, + viewPortHandler: viewPortHandler) + + let sliceXBase = cos(transformedAngle.DEG2RAD) + let sliceYBase = sin(transformedAngle.DEG2RAD) + + let drawXOutside = drawEntryLabels && xValuePosition == .outsideSlice + let drawYOutside = drawValues && yValuePosition == .outsideSlice + let drawXInside = drawEntryLabels && xValuePosition == .insideSlice + let drawYInside = drawValues && yValuePosition == .insideSlice + + let valueTextColor = dataSet.valueTextColorAt(j) + let entryLabelColor = dataSet.entryLabelColor + + if drawXOutside || drawYOutside + { + let valueLineLength1 = dataSet.valueLinePart1Length + let valueLineLength2 = dataSet.valueLinePart2Length + let valueLinePart1OffsetPercentage = dataSet.valueLinePart1OffsetPercentage + + var pt2: CGPoint + var labelPoint: CGPoint + var align: NSTextAlignment + + var line1Radius: CGFloat + + if chart.drawHoleEnabled + { + line1Radius = (radius - (radius * chart.holeRadiusPercent)) * valueLinePart1OffsetPercentage + (radius * chart.holeRadiusPercent) + } + else + { + line1Radius = radius * valueLinePart1OffsetPercentage + } + + let polyline2Length = dataSet.valueLineVariableLength + ? labelRadius * valueLineLength2 * abs(sin(transformedAngle.DEG2RAD)) + : labelRadius * valueLineLength2 + + let pt0 = CGPoint( + x: line1Radius * sliceXBase + center.x, + y: line1Radius * sliceYBase + center.y) + + let pt1 = CGPoint( + x: labelRadius * (1 + valueLineLength1) * sliceXBase + center.x, + y: labelRadius * (1 + valueLineLength1) * sliceYBase + center.y) + + if transformedAngle.truncatingRemainder(dividingBy: 360.0) >= 90.0 && transformedAngle.truncatingRemainder(dividingBy: 360.0) <= 270.0 + { + pt2 = CGPoint(x: pt1.x - polyline2Length, y: pt1.y) + align = .right + labelPoint = CGPoint(x: pt2.x - 5, y: pt2.y - lineHeight) + } + else + { + pt2 = CGPoint(x: pt1.x + polyline2Length, y: pt1.y) + align = .left + labelPoint = CGPoint(x: pt2.x + 5, y: pt2.y - lineHeight) + } + + DrawLine: do + { + if dataSet.useValueColorForLine + { + context.setStrokeColor(dataSet.color(atIndex: j).cgColor) + } + else if let valueLineColor = dataSet.valueLineColor + { + context.setStrokeColor(valueLineColor.cgColor) + } + else + { + return + } + context.setLineWidth(dataSet.valueLineWidth) + + context.move(to: CGPoint(x: pt0.x, y: pt0.y)) + context.addLine(to: CGPoint(x: pt1.x, y: pt1.y)) + context.addLine(to: CGPoint(x: pt2.x, y: pt2.y)) + + context.drawPath(using: CGPathDrawingMode.stroke) + } + + if drawXOutside && drawYOutside + { + ChartUtils.drawText( + context: context, + text: valueText, + point: labelPoint, + align: align, + attributes: [NSAttributedString.Key.font: valueFont, NSAttributedString.Key.foregroundColor: valueTextColor] + ) + + if j < data.entryCount && pe?.label != nil + { + ChartUtils.drawText( + context: context, + text: pe!.label!, + point: CGPoint(x: labelPoint.x, y: labelPoint.y + lineHeight), + align: align, + attributes: [ + NSAttributedString.Key.font: entryLabelFont ?? valueFont, + NSAttributedString.Key.foregroundColor: entryLabelColor ?? valueTextColor] + ) + } + } + else if drawXOutside + { + if j < data.entryCount && pe?.label != nil + { + ChartUtils.drawText( + context: context, + text: pe!.label!, + point: CGPoint(x: labelPoint.x, y: labelPoint.y + lineHeight / 2.0), + align: align, + attributes: [ + NSAttributedString.Key.font: entryLabelFont ?? valueFont, + NSAttributedString.Key.foregroundColor: entryLabelColor ?? valueTextColor] + ) + } + } + else if drawYOutside + { + ChartUtils.drawText( + context: context, + text: valueText, + point: CGPoint(x: labelPoint.x, y: labelPoint.y + lineHeight / 2.0), + align: align, + attributes: [NSAttributedString.Key.font: valueFont, NSAttributedString.Key.foregroundColor: valueTextColor] + ) + } + } + + if drawXInside || drawYInside + { + // calculate the text position + let x = labelRadius * sliceXBase + center.x + let y = labelRadius * sliceYBase + center.y - lineHeight + + if drawXInside && drawYInside + { + ChartUtils.drawText( + context: context, + text: valueText, + point: CGPoint(x: x, y: y), + align: .center, + attributes: [NSAttributedString.Key.font: valueFont, NSAttributedString.Key.foregroundColor: valueTextColor] + ) + + if j < data.entryCount && pe?.label != nil + { + ChartUtils.drawText( + context: context, + text: pe!.label!, + point: CGPoint(x: x, y: y + lineHeight), + align: .center, + attributes: [ + NSAttributedString.Key.font: entryLabelFont ?? valueFont, + NSAttributedString.Key.foregroundColor: entryLabelColor ?? valueTextColor] + ) + } + } + else if drawXInside + { + if j < data.entryCount && pe?.label != nil + { + ChartUtils.drawText( + context: context, + text: pe!.label!, + point: CGPoint(x: x, y: y + lineHeight / 2.0), + align: .center, + attributes: [ + NSAttributedString.Key.font: entryLabelFont ?? valueFont, + NSAttributedString.Key.foregroundColor: entryLabelColor ?? valueTextColor] + ) + } + } + else if drawYInside + { + ChartUtils.drawText( + context: context, + text: valueText, + point: CGPoint(x: x, y: y + lineHeight / 2.0), + align: .center, + attributes: [NSAttributedString.Key.font: valueFont, NSAttributedString.Key.foregroundColor: valueTextColor] + ) + } + } + + if let icon = e.icon, dataSet.isDrawIconsEnabled + { + // calculate the icon's position + + let x = (labelRadius + iconsOffset.y) * sliceXBase + center.x + var y = (labelRadius + iconsOffset.y) * sliceYBase + center.y + y += iconsOffset.x + + ChartUtils.drawImage(context: context, + image: icon, + x: x, + y: y, + size: icon.size) + } + + xIndex += 1 + } + } + } + + open override func drawExtras(context: CGContext) + { + drawHole(context: context) + drawCenterText(context: context) + } + + /// draws the hole in the center of the chart and the transparent circle / hole + private func drawHole(context: CGContext) + { + guard let chart = chart else { return } + + if chart.drawHoleEnabled + { + context.saveGState() + + let radius = chart.radius + let holeRadius = radius * chart.holeRadiusPercent + let center = chart.centerCircleBox + + if let holeColor = chart.holeColor + { + if holeColor != NSUIColor.clear + { + // draw the hole-circle + context.setFillColor(chart.holeColor!.cgColor) + context.fillEllipse(in: CGRect(x: center.x - holeRadius, y: center.y - holeRadius, width: holeRadius * 2.0, height: holeRadius * 2.0)) + } + } + + // only draw the circle if it can be seen (not covered by the hole) + if let transparentCircleColor = chart.transparentCircleColor + { + if transparentCircleColor != NSUIColor.clear && + chart.transparentCircleRadiusPercent > chart.holeRadiusPercent + { + let alpha = animator.phaseX * animator.phaseY + let secondHoleRadius = radius * chart.transparentCircleRadiusPercent + + // make transparent + context.setAlpha(CGFloat(alpha)) + context.setFillColor(transparentCircleColor.cgColor) + + // draw the transparent-circle + context.beginPath() + context.addEllipse(in: CGRect( + x: center.x - secondHoleRadius, + y: center.y - secondHoleRadius, + width: secondHoleRadius * 2.0, + height: secondHoleRadius * 2.0)) + context.addEllipse(in: CGRect( + x: center.x - holeRadius, + y: center.y - holeRadius, + width: holeRadius * 2.0, + height: holeRadius * 2.0)) + context.fillPath(using: .evenOdd) + } + } + + context.restoreGState() + } + } + + /// draws the description text in the center of the pie chart makes most sense when center-hole is enabled + private func drawCenterText(context: CGContext) + { + guard + let chart = chart, + let centerAttributedText = chart.centerAttributedText + else { return } + + if chart.drawCenterTextEnabled && centerAttributedText.length > 0 + { + let center = chart.centerCircleBox + let offset = chart.centerTextOffset + let innerRadius = chart.drawHoleEnabled && !chart.drawSlicesUnderHoleEnabled ? chart.radius * chart.holeRadiusPercent : chart.radius + + let x = center.x + offset.x + let y = center.y + offset.y + + let holeRect = CGRect( + x: x - innerRadius, + y: y - innerRadius, + width: innerRadius * 2.0, + height: innerRadius * 2.0) + var boundingRect = holeRect + + if chart.centerTextRadiusPercent > 0.0 + { + boundingRect = boundingRect.insetBy(dx: (boundingRect.width - boundingRect.width * chart.centerTextRadiusPercent) / 2.0, dy: (boundingRect.height - boundingRect.height * chart.centerTextRadiusPercent) / 2.0) + } + + let textBounds = centerAttributedText.boundingRect(with: boundingRect.size, options: [.usesLineFragmentOrigin, .usesFontLeading, .truncatesLastVisibleLine], context: nil) + + var drawingRect = boundingRect + drawingRect.origin.x += (boundingRect.size.width - textBounds.size.width) / 2.0 + drawingRect.origin.y += (boundingRect.size.height - textBounds.size.height) / 2.0 + drawingRect.size = textBounds.size + + context.saveGState() + + let clippingPath = CGPath(ellipseIn: holeRect, transform: nil) + context.beginPath() + context.addPath(clippingPath) + context.clip() + + centerAttributedText.draw(with: drawingRect, options: [.usesLineFragmentOrigin, .usesFontLeading, .truncatesLastVisibleLine], context: nil) + + context.restoreGState() + } + } + + open override func drawHighlighted(context: CGContext, indices: [Highlight]) + { + guard + let chart = chart, + let data = chart.data + else { return } + + context.saveGState() + + let phaseX = animator.phaseX + let phaseY = animator.phaseY + + var angle: CGFloat = 0.0 + let rotationAngle = chart.rotationAngle + + var drawAngles = chart.drawAngles + var absoluteAngles = chart.absoluteAngles + let center = chart.centerCircleBox + let radius = chart.radius + let drawInnerArc = chart.drawHoleEnabled && !chart.drawSlicesUnderHoleEnabled + let userInnerRadius = drawInnerArc ? radius * chart.holeRadiusPercent : 0.0 + + // Append highlighted accessibility slices into this array, so we can prioritize them over unselected slices + var highlightedAccessibleElements: [NSUIAccessibilityElement] = [] + + for i in 0 ..< indices.count + { + // get the index to highlight + let index = Int(indices[i].x) + if index >= drawAngles.count + { + continue + } + + guard let set = data.getDataSetByIndex(indices[i].dataSetIndex) as? IPieChartDataSet else { continue } + + if !set.isHighlightEnabled + { + continue + } + + let entryCount = set.entryCount + var visibleAngleCount = 0 + for j in 0 ..< entryCount + { + guard let e = set.entryForIndex(j) else { continue } + if ((abs(e.y) > Double.ulpOfOne)) + { + visibleAngleCount += 1 + } + } + + if index == 0 + { + angle = 0.0 + } + else + { + angle = absoluteAngles[index - 1] * CGFloat(phaseX) + } + + let sliceSpace = visibleAngleCount <= 1 ? 0.0 : set.sliceSpace + + let sliceAngle = drawAngles[index] + var innerRadius = userInnerRadius + + let shift = set.selectionShift + let highlightedRadius = radius + shift + + let accountForSliceSpacing = sliceSpace > 0.0 && sliceAngle <= 180.0 + + context.setFillColor(set.highlightColor?.cgColor ?? set.color(atIndex: index).cgColor) + + let sliceSpaceAngleOuter = visibleAngleCount == 1 ? + 0.0 : + sliceSpace / radius.DEG2RAD + + let sliceSpaceAngleShifted = visibleAngleCount == 1 ? + 0.0 : + sliceSpace / highlightedRadius.DEG2RAD + + let startAngleOuter = rotationAngle + (angle + sliceSpaceAngleOuter / 2.0) * CGFloat(phaseY) + var sweepAngleOuter = (sliceAngle - sliceSpaceAngleOuter) * CGFloat(phaseY) + if sweepAngleOuter < 0.0 + { + sweepAngleOuter = 0.0 + } + + let startAngleShifted = rotationAngle + (angle + sliceSpaceAngleShifted / 2.0) * CGFloat(phaseY) + var sweepAngleShifted = (sliceAngle - sliceSpaceAngleShifted) * CGFloat(phaseY) + if sweepAngleShifted < 0.0 + { + sweepAngleShifted = 0.0 + } + + let path = CGMutablePath() + + path.move(to: CGPoint(x: center.x + highlightedRadius * cos(startAngleShifted.DEG2RAD), + y: center.y + highlightedRadius * sin(startAngleShifted.DEG2RAD))) + + path.addRelativeArc(center: center, radius: highlightedRadius, startAngle: startAngleShifted.DEG2RAD, + delta: sweepAngleShifted.DEG2RAD) + + var sliceSpaceRadius: CGFloat = 0.0 + if accountForSliceSpacing + { + sliceSpaceRadius = calculateMinimumRadiusForSpacedSlice( + center: center, + radius: radius, + angle: sliceAngle * CGFloat(phaseY), + arcStartPointX: center.x + radius * cos(startAngleOuter.DEG2RAD), + arcStartPointY: center.y + radius * sin(startAngleOuter.DEG2RAD), + startAngle: startAngleOuter, + sweepAngle: sweepAngleOuter) + } + + if drawInnerArc && + (innerRadius > 0.0 || accountForSliceSpacing) + { + if accountForSliceSpacing + { + var minSpacedRadius = sliceSpaceRadius + if minSpacedRadius < 0.0 + { + minSpacedRadius = -minSpacedRadius + } + innerRadius = min(max(innerRadius, minSpacedRadius), radius) + } + + let sliceSpaceAngleInner = visibleAngleCount == 1 || innerRadius == 0.0 ? + 0.0 : + sliceSpace / innerRadius.DEG2RAD + let startAngleInner = rotationAngle + (angle + sliceSpaceAngleInner / 2.0) * CGFloat(phaseY) + var sweepAngleInner = (sliceAngle - sliceSpaceAngleInner) * CGFloat(phaseY) + if sweepAngleInner < 0.0 + { + sweepAngleInner = 0.0 + } + let endAngleInner = startAngleInner + sweepAngleInner + + path.addLine( + to: CGPoint( + x: center.x + innerRadius * cos(endAngleInner.DEG2RAD), + y: center.y + innerRadius * sin(endAngleInner.DEG2RAD))) + + path.addRelativeArc(center: center, radius: innerRadius, + startAngle: endAngleInner.DEG2RAD, + delta: -sweepAngleInner.DEG2RAD) + } + else + { + if accountForSliceSpacing + { + let angleMiddle = startAngleOuter + sweepAngleOuter / 2.0 + + let arcEndPointX = center.x + sliceSpaceRadius * cos(angleMiddle.DEG2RAD) + let arcEndPointY = center.y + sliceSpaceRadius * sin(angleMiddle.DEG2RAD) + + path.addLine( + to: CGPoint( + x: arcEndPointX, + y: arcEndPointY)) + } + else + { + path.addLine(to: center) + } + } + + path.closeSubpath() + + context.beginPath() + context.addPath(path) + context.fillPath(using: .evenOdd) + + let axElement = createAccessibleElement(withIndex: index, + container: chart, + dataSet: set) + { (element) in + element.accessibilityFrame = path.boundingBoxOfPath + element.isSelected = true + } + + highlightedAccessibleElements.append(axElement) + } + + // Prepend selected slices before the already rendered unselected ones. + // NOTE: - This relies on drawDataSet() being called before drawHighlighted in PieChartView. + accessibleChartElements.insert(contentsOf: highlightedAccessibleElements, at: 1) + + context.restoreGState() + } + + /// Creates an NSUIAccessibilityElement representing a slice of the PieChart. + /// The element only has it's container and label set based on the chart and dataSet. Use the modifier to alter traits and frame. + private func createAccessibleElement(withIndex idx: Int, + container: PieChartView, + dataSet: IPieChartDataSet, + modifier: (NSUIAccessibilityElement) -> ()) -> NSUIAccessibilityElement { + + let element = NSUIAccessibilityElement(accessibilityContainer: container) + + guard let e = dataSet.entryForIndex(idx) else { return element } + guard let formatter = dataSet.valueFormatter else { return element } + guard let data = container.data as? PieChartData else { return element } + + var elementValueText = formatter.stringForValue( + e.y, + entry: e, + dataSetIndex: idx, + viewPortHandler: viewPortHandler) + + if container.usePercentValuesEnabled { + let value = e.y / data.yValueSum * 100.0 + let valueText = formatter.stringForValue( + value, + entry: e, + dataSetIndex: idx, + viewPortHandler: viewPortHandler) + + elementValueText = valueText + } + + let pieChartDataEntry = (dataSet.entryForIndex(idx) as? PieChartDataEntry) + let isCount = data.accessibilityEntryLabelSuffixIsCount + let prefix = data.accessibilityEntryLabelPrefix?.appending("\(idx + 1)") ?? pieChartDataEntry?.label ?? "" + let suffix = data.accessibilityEntryLabelSuffix ?? "" + element.accessibilityLabel = "\(prefix) : \(elementValueText) \(suffix + (isCount ? (e.y == 1.0 ? "" : "s") : "") )" + + // The modifier allows changing of traits and frame depending on highlight, rotation, etc + modifier(element) + + return element + } +} diff --git a/Pods/Charts/Source/Charts/Renderers/RadarChartRenderer.swift b/Pods/Charts/Source/Charts/Renderers/RadarChartRenderer.swift new file mode 100644 index 00000000..c2ab79fc --- /dev/null +++ b/Pods/Charts/Source/Charts/Renderers/RadarChartRenderer.swift @@ -0,0 +1,475 @@ +// +// RadarChartRenderer.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 RadarChartRenderer: LineRadarRenderer +{ + private lazy var accessibilityXLabels: [String] = { + guard let chart = chart else { return [] } + guard let formatter = chart.xAxis.valueFormatter else { return [] } + + let maxEntryCount = chart.data?.maxEntryCountSet?.entryCount ?? 0 + return stride(from: 0, to: maxEntryCount, by: 1).map { + formatter.stringForValue(Double($0), axis: chart.xAxis) + } + }() + + @objc open weak var chart: RadarChartView? + + @objc public init(chart: RadarChartView, animator: Animator, viewPortHandler: ViewPortHandler) + { + super.init(animator: animator, viewPortHandler: viewPortHandler) + + self.chart = chart + } + + open override func drawData(context: CGContext) + { + guard let chart = chart else { return } + + let radarData = chart.data + + if radarData != nil + { + let mostEntries = radarData?.maxEntryCountSet?.entryCount ?? 0 + + // If we redraw the data, remove and repopulate accessible elements to update label values and frames + self.accessibleChartElements.removeAll() + + // Make the chart header the first element in the accessible elements array + if let accessibilityHeaderData = radarData as? RadarChartData { + let element = createAccessibleHeader(usingChart: chart, + andData: accessibilityHeaderData, + withDefaultDescription: "Radar Chart") + self.accessibleChartElements.append(element) + } + + for set in radarData!.dataSets as! [IRadarChartDataSet] where set.isVisible + { + drawDataSet(context: context, dataSet: set, mostEntries: mostEntries) + } + } + } + + /// Draws the RadarDataSet + /// + /// - Parameters: + /// - context: + /// - dataSet: + /// - mostEntries: the entry count of the dataset with the most entries + internal func drawDataSet(context: CGContext, dataSet: IRadarChartDataSet, mostEntries: Int) + { + guard let chart = chart else { return } + + context.saveGState() + + let phaseX = animator.phaseX + let phaseY = animator.phaseY + + let sliceangle = chart.sliceAngle + + // calculate the factor that is needed for transforming the value to pixels + let factor = chart.factor + + let center = chart.centerOffsets + let entryCount = dataSet.entryCount + let path = CGMutablePath() + var hasMovedToPoint = false + + let prefix: String = chart.data?.accessibilityEntryLabelPrefix ?? "Item" + let description = dataSet.label ?? "" + + // Make a tuple of (xLabels, value, originalIndex) then sort it + // This is done, so that the labels are narrated in decreasing order of their corresponding value + // Otherwise, there is no non-visual logic to the data presented + let accessibilityEntryValues = Array(0 ..< entryCount).map { (dataSet.entryForIndex($0)?.y ?? 0, $0) } + let accessibilityAxisLabelValueTuples = zip(accessibilityXLabels, accessibilityEntryValues).map { ($0, $1.0, $1.1) }.sorted { $0.1 > $1.1 } + let accessibilityDataSetDescription: String = description + ". \(entryCount) \(prefix + (entryCount == 1 ? "" : "s")). " + let accessibilityFrameWidth: CGFloat = 22.0 // To allow a tap target of 44x44 + + var accessibilityEntryElements: [NSUIAccessibilityElement] = [] + + for j in 0 ..< entryCount + { + guard let e = dataSet.entryForIndex(j) else { continue } + + let p = center.moving(distance: CGFloat((e.y - chart.chartYMin) * Double(factor) * phaseY), + atAngle: sliceangle * CGFloat(j) * CGFloat(phaseX) + chart.rotationAngle) + + if p.x.isNaN + { + continue + } + + if !hasMovedToPoint + { + path.move(to: p) + hasMovedToPoint = true + } + else + { + path.addLine(to: p) + } + + let accessibilityLabel = accessibilityAxisLabelValueTuples[j].0 + let accessibilityValue = accessibilityAxisLabelValueTuples[j].1 + let accessibilityValueIndex = accessibilityAxisLabelValueTuples[j].2 + + let axp = center.moving(distance: CGFloat((accessibilityValue - chart.chartYMin) * Double(factor) * phaseY), + atAngle: sliceangle * CGFloat(accessibilityValueIndex) * CGFloat(phaseX) + chart.rotationAngle) + + let axDescription = description + " - " + accessibilityLabel + ": \(accessibilityValue) \(chart.data?.accessibilityEntryLabelSuffix ?? "")" + let axElement = createAccessibleElement(withDescription: axDescription, + container: chart, + dataSet: dataSet) + { (element) in + element.accessibilityFrame = CGRect(x: axp.x - accessibilityFrameWidth, + y: axp.y - accessibilityFrameWidth, + width: 2 * accessibilityFrameWidth, + height: 2 * accessibilityFrameWidth) + } + + accessibilityEntryElements.append(axElement) + } + + // if this is the largest set, close it + if dataSet.entryCount < mostEntries + { + // if this is not the largest set, draw a line to the center before closing + path.addLine(to: center) + } + + path.closeSubpath() + + // draw filled + if dataSet.isDrawFilledEnabled + { + if dataSet.fill != nil + { + drawFilledPath(context: context, path: path, fill: dataSet.fill!, fillAlpha: dataSet.fillAlpha) + } + else + { + drawFilledPath(context: context, path: path, fillColor: dataSet.fillColor, fillAlpha: dataSet.fillAlpha) + } + } + + // draw the line (only if filled is disabled or alpha is below 255) + if !dataSet.isDrawFilledEnabled || dataSet.fillAlpha < 1.0 + { + context.setStrokeColor(dataSet.color(atIndex: 0).cgColor) + context.setLineWidth(dataSet.lineWidth) + context.setAlpha(1.0) + + context.beginPath() + context.addPath(path) + context.strokePath() + + let axElement = createAccessibleElement(withDescription: accessibilityDataSetDescription, + container: chart, + dataSet: dataSet) + { (element) in + element.isHeader = true + element.accessibilityFrame = path.boundingBoxOfPath + } + + accessibleChartElements.append(axElement) + accessibleChartElements.append(contentsOf: accessibilityEntryElements) + } + + accessibilityPostLayoutChangedNotification() + + context.restoreGState() + } + + open override func drawValues(context: CGContext) + { + guard + let chart = chart, + let data = chart.data + else { return } + + let phaseX = animator.phaseX + let phaseY = animator.phaseY + + let sliceangle = chart.sliceAngle + + // calculate the factor that is needed for transforming the value to pixels + let factor = chart.factor + + let center = chart.centerOffsets + + let yoffset = CGFloat(5.0) + + for i in 0 ..< data.dataSetCount + { + guard let + dataSet = data.getDataSetByIndex(i) as? IRadarChartDataSet, + shouldDrawValues(forDataSet: dataSet) + else { continue } + + let entryCount = dataSet.entryCount + + let iconsOffset = dataSet.iconsOffset + + for j in 0 ..< entryCount + { + guard let e = dataSet.entryForIndex(j) else { continue } + + let p = center.moving(distance: CGFloat(e.y - chart.chartYMin) * factor * CGFloat(phaseY), + atAngle: sliceangle * CGFloat(j) * CGFloat(phaseX) + chart.rotationAngle) + + let valueFont = dataSet.valueFont + + guard let formatter = dataSet.valueFormatter else { continue } + + if dataSet.isDrawValuesEnabled + { + ChartUtils.drawText( + context: context, + text: formatter.stringForValue( + e.y, + entry: e, + dataSetIndex: i, + viewPortHandler: viewPortHandler), + point: CGPoint(x: p.x, y: p.y - yoffset - valueFont.lineHeight), + align: .center, + attributes: [NSAttributedString.Key.font: valueFont, + NSAttributedString.Key.foregroundColor: dataSet.valueTextColorAt(j)] + ) + } + + if let icon = e.icon, dataSet.isDrawIconsEnabled + { + var pIcon = center.moving(distance: CGFloat(e.y) * factor * CGFloat(phaseY) + iconsOffset.y, + atAngle: sliceangle * CGFloat(j) * CGFloat(phaseX) + chart.rotationAngle) + pIcon.y += iconsOffset.x + + ChartUtils.drawImage(context: context, + image: icon, + x: pIcon.x, + y: pIcon.y, + size: icon.size) + } + } + } + } + + open override func drawExtras(context: CGContext) + { + drawWeb(context: context) + } + + private var _webLineSegmentsBuffer = [CGPoint](repeating: CGPoint(), count: 2) + + @objc open func drawWeb(context: CGContext) + { + guard + let chart = chart, + let data = chart.data + else { return } + + let sliceangle = chart.sliceAngle + + context.saveGState() + + // calculate the factor that is needed for transforming the value to + // pixels + let factor = chart.factor + let rotationangle = chart.rotationAngle + + let center = chart.centerOffsets + + // draw the web lines that come from the center + context.setLineWidth(chart.webLineWidth) + context.setStrokeColor(chart.webColor.cgColor) + context.setAlpha(chart.webAlpha) + + let xIncrements = 1 + chart.skipWebLineCount + let maxEntryCount = chart.data?.maxEntryCountSet?.entryCount ?? 0 + + for i in stride(from: 0, to: maxEntryCount, by: xIncrements) + { + let p = center.moving(distance: CGFloat(chart.yRange) * factor, + atAngle: sliceangle * CGFloat(i) + rotationangle) + + _webLineSegmentsBuffer[0].x = center.x + _webLineSegmentsBuffer[0].y = center.y + _webLineSegmentsBuffer[1].x = p.x + _webLineSegmentsBuffer[1].y = p.y + + context.strokeLineSegments(between: _webLineSegmentsBuffer) + } + + // draw the inner-web + context.setLineWidth(chart.innerWebLineWidth) + context.setStrokeColor(chart.innerWebColor.cgColor) + context.setAlpha(chart.webAlpha) + + let labelCount = chart.yAxis.entryCount + + for j in 0 ..< labelCount + { + for i in 0 ..< data.entryCount + { + let r = CGFloat(chart.yAxis.entries[j] - chart.chartYMin) * factor + + let p1 = center.moving(distance: r, atAngle: sliceangle * CGFloat(i) + rotationangle) + let p2 = center.moving(distance: r, atAngle: sliceangle * CGFloat(i + 1) + rotationangle) + + _webLineSegmentsBuffer[0].x = p1.x + _webLineSegmentsBuffer[0].y = p1.y + _webLineSegmentsBuffer[1].x = p2.x + _webLineSegmentsBuffer[1].y = p2.y + + context.strokeLineSegments(between: _webLineSegmentsBuffer) + } + } + + context.restoreGState() + } + + private var _highlightPointBuffer = CGPoint() + + open override func drawHighlighted(context: CGContext, indices: [Highlight]) + { + guard + let chart = chart, + let radarData = chart.data as? RadarChartData + else { return } + + context.saveGState() + + let sliceangle = chart.sliceAngle + + // calculate the factor that is needed for transforming the value pixels + let factor = chart.factor + + let center = chart.centerOffsets + + for high in indices + { + guard + let set = chart.data?.getDataSetByIndex(high.dataSetIndex) as? IRadarChartDataSet, + set.isHighlightEnabled + else { continue } + + guard let e = set.entryForIndex(Int(high.x)) as? RadarChartDataEntry + else { continue } + + if !isInBoundsX(entry: e, dataSet: set) + { + continue + } + + context.setLineWidth(radarData.highlightLineWidth) + if radarData.highlightLineDashLengths != nil + { + context.setLineDash(phase: radarData.highlightLineDashPhase, lengths: radarData.highlightLineDashLengths!) + } + else + { + context.setLineDash(phase: 0.0, lengths: []) + } + + context.setStrokeColor(set.highlightColor.cgColor) + + let y = e.y - chart.chartYMin + + _highlightPointBuffer = center.moving(distance: CGFloat(y) * factor * CGFloat(animator.phaseY), + atAngle: sliceangle * CGFloat(high.x) * CGFloat(animator.phaseX) + chart.rotationAngle) + + high.setDraw(pt: _highlightPointBuffer) + + // draw the lines + drawHighlightLines(context: context, point: _highlightPointBuffer, set: set) + + if set.isDrawHighlightCircleEnabled + { + if !_highlightPointBuffer.x.isNaN && !_highlightPointBuffer.y.isNaN + { + var strokeColor = set.highlightCircleStrokeColor + if strokeColor == nil + { + strokeColor = set.color(atIndex: 0) + } + if set.highlightCircleStrokeAlpha < 1.0 + { + strokeColor = strokeColor?.withAlphaComponent(set.highlightCircleStrokeAlpha) + } + + drawHighlightCircle( + context: context, + atPoint: _highlightPointBuffer, + innerRadius: set.highlightCircleInnerRadius, + outerRadius: set.highlightCircleOuterRadius, + fillColor: set.highlightCircleFillColor, + strokeColor: strokeColor, + strokeWidth: set.highlightCircleStrokeWidth) + } + } + } + + context.restoreGState() + } + + internal func drawHighlightCircle( + context: CGContext, + atPoint point: CGPoint, + innerRadius: CGFloat, + outerRadius: CGFloat, + fillColor: NSUIColor?, + strokeColor: NSUIColor?, + strokeWidth: CGFloat) + { + context.saveGState() + + if let fillColor = fillColor + { + context.beginPath() + context.addEllipse(in: CGRect(x: point.x - outerRadius, y: point.y - outerRadius, width: outerRadius * 2.0, height: outerRadius * 2.0)) + if innerRadius > 0.0 + { + context.addEllipse(in: CGRect(x: point.x - innerRadius, y: point.y - innerRadius, width: innerRadius * 2.0, height: innerRadius * 2.0)) + } + + context.setFillColor(fillColor.cgColor) + context.fillPath(using: .evenOdd) + } + + if let strokeColor = strokeColor + { + context.beginPath() + context.addEllipse(in: CGRect(x: point.x - outerRadius, y: point.y - outerRadius, width: outerRadius * 2.0, height: outerRadius * 2.0)) + context.setStrokeColor(strokeColor.cgColor) + context.setLineWidth(strokeWidth) + context.strokePath() + } + + context.restoreGState() + } + + private func createAccessibleElement(withDescription description: String, + container: RadarChartView, + dataSet: IRadarChartDataSet, + modifier: (NSUIAccessibilityElement) -> ()) -> NSUIAccessibilityElement { + + let element = NSUIAccessibilityElement(accessibilityContainer: container) + element.accessibilityLabel = description + + // The modifier allows changing of traits and frame depending on highlight, rotation, etc + modifier(element) + + return element + } +} diff --git a/Pods/Charts/Source/Charts/Renderers/Renderer.swift b/Pods/Charts/Source/Charts/Renderers/Renderer.swift new file mode 100644 index 00000000..e57a9b85 --- /dev/null +++ b/Pods/Charts/Source/Charts/Renderers/Renderer.swift @@ -0,0 +1,26 @@ +// +// Renderer.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(ChartRenderer) +open class Renderer: NSObject +{ + /// the component that handles the drawing area of the chart and it's offsets + @objc public let viewPortHandler: ViewPortHandler + + @objc public init(viewPortHandler: ViewPortHandler) + { + self.viewPortHandler = viewPortHandler + super.init() + } +} diff --git a/Pods/Charts/Source/Charts/Renderers/Scatter/ChevronDownShapeRenderer.swift b/Pods/Charts/Source/Charts/Renderers/Scatter/ChevronDownShapeRenderer.swift new file mode 100644 index 00000000..2d035bf3 --- /dev/null +++ b/Pods/Charts/Source/Charts/Renderers/Scatter/ChevronDownShapeRenderer.swift @@ -0,0 +1,36 @@ +// +// ChevronDownShapeRenderer.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 ChevronDownShapeRenderer : NSObject, IShapeRenderer +{ + open func renderShape( + context: CGContext, + dataSet: IScatterChartDataSet, + viewPortHandler: ViewPortHandler, + point: CGPoint, + color: NSUIColor) + { + let shapeSize = dataSet.scatterShapeSize + let shapeHalf = shapeSize / 2.0 + + context.setLineWidth(1.0) + context.setStrokeColor(color.cgColor) + + context.beginPath() + context.move(to: CGPoint(x: point.x, y: point.y + 2 * shapeHalf)) + context.addLine(to: CGPoint(x: point.x + 2 * shapeHalf, y: point.y)) + context.move(to: CGPoint(x: point.x, y: point.y + 2 * shapeHalf)) + context.addLine(to: CGPoint(x: point.x - 2 * shapeHalf, y: point.y)) + context.strokePath() + } +} diff --git a/Pods/Charts/Source/Charts/Renderers/Scatter/ChevronUpShapeRenderer.swift b/Pods/Charts/Source/Charts/Renderers/Scatter/ChevronUpShapeRenderer.swift new file mode 100644 index 00000000..725533e7 --- /dev/null +++ b/Pods/Charts/Source/Charts/Renderers/Scatter/ChevronUpShapeRenderer.swift @@ -0,0 +1,36 @@ +// +// ChevronUpShapeRenderer.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 ChevronUpShapeRenderer : NSObject, IShapeRenderer +{ + open func renderShape( + context: CGContext, + dataSet: IScatterChartDataSet, + viewPortHandler: ViewPortHandler, + point: CGPoint, + color: NSUIColor) + { + let shapeSize = dataSet.scatterShapeSize + let shapeHalf = shapeSize / 2.0 + + context.setLineWidth(1.0) + context.setStrokeColor(color.cgColor) + + context.beginPath() + context.move(to: CGPoint(x: point.x, y: point.y - 2 * shapeHalf)) + context.addLine(to: CGPoint(x: point.x + 2 * shapeHalf, y: point.y)) + context.move(to: CGPoint(x: point.x, y: point.y - 2 * shapeHalf)) + context.addLine(to: CGPoint(x: point.x - 2 * shapeHalf, y: point.y)) + context.strokePath() + } +} diff --git a/Pods/Charts/Source/Charts/Renderers/Scatter/CircleShapeRenderer.swift b/Pods/Charts/Source/Charts/Renderers/Scatter/CircleShapeRenderer.swift new file mode 100644 index 00000000..b94a5113 --- /dev/null +++ b/Pods/Charts/Source/Charts/Renderers/Scatter/CircleShapeRenderer.swift @@ -0,0 +1,63 @@ +// +// CircleShapeRenderer.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 CircleShapeRenderer : NSObject, IShapeRenderer +{ + open func renderShape( + context: CGContext, + dataSet: IScatterChartDataSet, + viewPortHandler: ViewPortHandler, + point: CGPoint, + color: NSUIColor) + { + let shapeSize = dataSet.scatterShapeSize + let shapeHalf = shapeSize / 2.0 + let shapeHoleSizeHalf = dataSet.scatterShapeHoleRadius + let shapeHoleSize = shapeHoleSizeHalf * 2.0 + let shapeHoleColor = dataSet.scatterShapeHoleColor + let shapeStrokeSize = (shapeSize - shapeHoleSize) / 2.0 + let shapeStrokeSizeHalf = shapeStrokeSize / 2.0 + + if shapeHoleSize > 0.0 + { + context.setStrokeColor(color.cgColor) + context.setLineWidth(shapeStrokeSize) + var rect = CGRect() + rect.origin.x = point.x - shapeHoleSizeHalf - shapeStrokeSizeHalf + rect.origin.y = point.y - shapeHoleSizeHalf - shapeStrokeSizeHalf + rect.size.width = shapeHoleSize + shapeStrokeSize + rect.size.height = shapeHoleSize + shapeStrokeSize + context.strokeEllipse(in: rect) + + if let shapeHoleColor = shapeHoleColor + { + context.setFillColor(shapeHoleColor.cgColor) + rect.origin.x = point.x - shapeHoleSizeHalf + rect.origin.y = point.y - shapeHoleSizeHalf + rect.size.width = shapeHoleSize + rect.size.height = shapeHoleSize + context.fillEllipse(in: rect) + } + } + else + { + context.setFillColor(color.cgColor) + var rect = CGRect() + rect.origin.x = point.x - shapeHalf + rect.origin.y = point.y - shapeHalf + rect.size.width = shapeSize + rect.size.height = shapeSize + context.fillEllipse(in: rect) + } + } +} diff --git a/Pods/Charts/Source/Charts/Renderers/Scatter/CrossShapeRenderer.swift b/Pods/Charts/Source/Charts/Renderers/Scatter/CrossShapeRenderer.swift new file mode 100644 index 00000000..18785d3d --- /dev/null +++ b/Pods/Charts/Source/Charts/Renderers/Scatter/CrossShapeRenderer.swift @@ -0,0 +1,36 @@ +// +// CrossShapeRenderer.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 CrossShapeRenderer : NSObject, IShapeRenderer +{ + open func renderShape( + context: CGContext, + dataSet: IScatterChartDataSet, + viewPortHandler: ViewPortHandler, + point: CGPoint, + color: NSUIColor) + { + let shapeSize = dataSet.scatterShapeSize + let shapeHalf = shapeSize / 2.0 + + context.setLineWidth(1.0) + context.setStrokeColor(color.cgColor) + + context.beginPath() + context.move(to: CGPoint(x: point.x - shapeHalf, y: point.y)) + context.addLine(to: CGPoint(x: point.x + shapeHalf, y: point.y)) + context.move(to: CGPoint(x: point.x, y: point.y - shapeHalf)) + context.addLine(to: CGPoint(x: point.x, y: point.y + shapeHalf)) + context.strokePath() + } +} diff --git a/Pods/Charts/Source/Charts/Renderers/Scatter/IShapeRenderer.swift b/Pods/Charts/Source/Charts/Renderers/Scatter/IShapeRenderer.swift new file mode 100644 index 00000000..ff12ee3f --- /dev/null +++ b/Pods/Charts/Source/Charts/Renderers/Scatter/IShapeRenderer.swift @@ -0,0 +1,32 @@ +// +// IShapeRenderer.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 IShapeRenderer: class +{ + /// Renders the provided ScatterDataSet with a shape. + /// + /// - Parameters: + /// - context: CGContext for drawing on + /// - dataSet: The DataSet to be drawn + /// - viewPortHandler: Contains information about the current state of the view + /// - point: Position to draw the shape at + /// - color: Color to draw the shape + func renderShape( + context: CGContext, + dataSet: IScatterChartDataSet, + viewPortHandler: ViewPortHandler, + point: CGPoint, + color: NSUIColor) +} diff --git a/Pods/Charts/Source/Charts/Renderers/Scatter/SquareShapeRenderer.swift b/Pods/Charts/Source/Charts/Renderers/Scatter/SquareShapeRenderer.swift new file mode 100644 index 00000000..ea692e33 --- /dev/null +++ b/Pods/Charts/Source/Charts/Renderers/Scatter/SquareShapeRenderer.swift @@ -0,0 +1,63 @@ +// +// SquareShapeRenderer.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 SquareShapeRenderer : NSObject, IShapeRenderer +{ + open func renderShape( + context: CGContext, + dataSet: IScatterChartDataSet, + viewPortHandler: ViewPortHandler, + point: CGPoint, + color: NSUIColor) + { + let shapeSize = dataSet.scatterShapeSize + let shapeHalf = shapeSize / 2.0 + let shapeHoleSizeHalf = dataSet.scatterShapeHoleRadius + let shapeHoleSize = shapeHoleSizeHalf * 2.0 + let shapeHoleColor = dataSet.scatterShapeHoleColor + let shapeStrokeSize = (shapeSize - shapeHoleSize) / 2.0 + let shapeStrokeSizeHalf = shapeStrokeSize / 2.0 + + if shapeHoleSize > 0.0 + { + context.setStrokeColor(color.cgColor) + context.setLineWidth(shapeStrokeSize) + var rect = CGRect() + rect.origin.x = point.x - shapeHoleSizeHalf - shapeStrokeSizeHalf + rect.origin.y = point.y - shapeHoleSizeHalf - shapeStrokeSizeHalf + rect.size.width = shapeHoleSize + shapeStrokeSize + rect.size.height = shapeHoleSize + shapeStrokeSize + context.stroke(rect) + + if let shapeHoleColor = shapeHoleColor + { + context.setFillColor(shapeHoleColor.cgColor) + rect.origin.x = point.x - shapeHoleSizeHalf + rect.origin.y = point.y - shapeHoleSizeHalf + rect.size.width = shapeHoleSize + rect.size.height = shapeHoleSize + context.fill(rect) + } + } + else + { + context.setFillColor(color.cgColor) + var rect = CGRect() + rect.origin.x = point.x - shapeHalf + rect.origin.y = point.y - shapeHalf + rect.size.width = shapeSize + rect.size.height = shapeSize + context.fill(rect) + } + } +} diff --git a/Pods/Charts/Source/Charts/Renderers/Scatter/TriangleShapeRenderer.swift b/Pods/Charts/Source/Charts/Renderers/Scatter/TriangleShapeRenderer.swift new file mode 100644 index 00000000..fa313b76 --- /dev/null +++ b/Pods/Charts/Source/Charts/Renderers/Scatter/TriangleShapeRenderer.swift @@ -0,0 +1,66 @@ +// +// TriangleShapeRenderer.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 TriangleShapeRenderer : NSObject, IShapeRenderer +{ + open func renderShape( + context: CGContext, + dataSet: IScatterChartDataSet, + viewPortHandler: ViewPortHandler, + point: CGPoint, + color: NSUIColor) + { + let shapeSize = dataSet.scatterShapeSize + let shapeHalf = shapeSize / 2.0 + let shapeHoleSizeHalf = dataSet.scatterShapeHoleRadius + let shapeHoleSize = shapeHoleSizeHalf * 2.0 + let shapeHoleColor = dataSet.scatterShapeHoleColor + let shapeStrokeSize = (shapeSize - shapeHoleSize) / 2.0 + + context.setFillColor(color.cgColor) + + // create a triangle path + context.beginPath() + context.move(to: CGPoint(x: point.x, y: point.y - shapeHalf)) + context.addLine(to: CGPoint(x: point.x + shapeHalf, y: point.y + shapeHalf)) + context.addLine(to: CGPoint(x: point.x - shapeHalf, y: point.y + shapeHalf)) + + if shapeHoleSize > 0.0 + { + context.addLine(to: CGPoint(x: point.x, y: point.y - shapeHalf)) + + context.move(to: CGPoint(x: point.x - shapeHalf + shapeStrokeSize, y: point.y + shapeHalf - shapeStrokeSize)) + context.addLine(to: CGPoint(x: point.x + shapeHalf - shapeStrokeSize, y: point.y + shapeHalf - shapeStrokeSize)) + context.addLine(to: CGPoint(x: point.x, y: point.y - shapeHalf + shapeStrokeSize)) + context.addLine(to: CGPoint(x: point.x - shapeHalf + shapeStrokeSize, y: point.y + shapeHalf - shapeStrokeSize)) + } + + context.closePath() + + context.fillPath() + + if shapeHoleSize > 0.0 && shapeHoleColor != nil + { + context.setFillColor(shapeHoleColor!.cgColor) + + // create a triangle path + context.beginPath() + context.move(to: CGPoint(x: point.x, y: point.y - shapeHalf + shapeStrokeSize)) + context.addLine(to: CGPoint(x: point.x + shapeHalf - shapeStrokeSize, y: point.y + shapeHalf - shapeStrokeSize)) + context.addLine(to: CGPoint(x: point.x - shapeHalf + shapeStrokeSize, y: point.y + shapeHalf - shapeStrokeSize)) + context.closePath() + + context.fillPath() + } + } +} diff --git a/Pods/Charts/Source/Charts/Renderers/Scatter/XShapeRenderer.swift b/Pods/Charts/Source/Charts/Renderers/Scatter/XShapeRenderer.swift new file mode 100644 index 00000000..8a546c5f --- /dev/null +++ b/Pods/Charts/Source/Charts/Renderers/Scatter/XShapeRenderer.swift @@ -0,0 +1,36 @@ +// +// XShapeRenderer.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 XShapeRenderer : NSObject, IShapeRenderer +{ + open func renderShape( + context: CGContext, + dataSet: IScatterChartDataSet, + viewPortHandler: ViewPortHandler, + point: CGPoint, + color: NSUIColor) + { + let shapeSize = dataSet.scatterShapeSize + let shapeHalf = shapeSize / 2.0 + + context.setLineWidth(1.0) + context.setStrokeColor(color.cgColor) + + context.beginPath() + context.move(to: CGPoint(x: point.x - shapeHalf, y: point.y - shapeHalf)) + context.addLine(to: CGPoint(x: point.x + shapeHalf, y: point.y + shapeHalf)) + context.move(to: CGPoint(x: point.x + shapeHalf, y: point.y - shapeHalf)) + context.addLine(to: CGPoint(x: point.x - shapeHalf, y: point.y + shapeHalf)) + context.strokePath() + } +} diff --git a/Pods/Charts/Source/Charts/Renderers/ScatterChartRenderer.swift b/Pods/Charts/Source/Charts/Renderers/ScatterChartRenderer.swift new file mode 100644 index 00000000..57d348b2 --- /dev/null +++ b/Pods/Charts/Source/Charts/Renderers/ScatterChartRenderer.swift @@ -0,0 +1,249 @@ +// +// ScatterChartRenderer.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 ScatterChartRenderer: LineScatterCandleRadarRenderer +{ + @objc open weak var dataProvider: ScatterChartDataProvider? + + @objc public init(dataProvider: ScatterChartDataProvider, animator: Animator, viewPortHandler: ViewPortHandler) + { + super.init(animator: animator, viewPortHandler: viewPortHandler) + + self.dataProvider = dataProvider + } + + open override func drawData(context: CGContext) + { + guard let scatterData = dataProvider?.scatterData else { return } + + // If we redraw the data, remove and repopulate accessible elements to update label values and frames + accessibleChartElements.removeAll() + + if let chart = dataProvider as? ScatterChartView { + // Make the chart header the first element in the accessible elements array + let element = createAccessibleHeader(usingChart: chart, + andData: scatterData, + withDefaultDescription: "Scatter Chart") + accessibleChartElements.append(element) + } + + // TODO: Due to the potential complexity of data presented in Scatter charts, a more usable way + // for VO accessibility would be to use axis based traversal rather than by dataset. + // Hence, accessibleChartElements is not populated below. (Individual renderers guard against dataSource being their respective views) + for i in 0 ..< scatterData.dataSetCount + { + guard let set = scatterData.getDataSetByIndex(i) else { continue } + + if set.isVisible + { + if !(set is IScatterChartDataSet) + { + fatalError("Datasets for ScatterChartRenderer must conform to IScatterChartDataSet") + } + + drawDataSet(context: context, dataSet: set as! IScatterChartDataSet) + } + } + } + + private var _lineSegments = [CGPoint](repeating: CGPoint(), count: 2) + + @objc open func drawDataSet(context: CGContext, dataSet: IScatterChartDataSet) + { + guard let dataProvider = dataProvider else { return } + + let trans = dataProvider.getTransformer(forAxis: dataSet.axisDependency) + + let phaseY = animator.phaseY + + let entryCount = dataSet.entryCount + + var point = CGPoint() + + let valueToPixelMatrix = trans.valueToPixelMatrix + + if let renderer = dataSet.shapeRenderer + { + context.saveGState() + + for j in 0 ..< Int(min(ceil(Double(entryCount) * animator.phaseX), Double(entryCount))) + { + guard let e = dataSet.entryForIndex(j) else { continue } + + point.x = CGFloat(e.x) + point.y = CGFloat(e.y * phaseY) + point = point.applying(valueToPixelMatrix) + + if !viewPortHandler.isInBoundsRight(point.x) + { + break + } + + if !viewPortHandler.isInBoundsLeft(point.x) || + !viewPortHandler.isInBoundsY(point.y) + { + continue + } + + renderer.renderShape(context: context, dataSet: dataSet, viewPortHandler: viewPortHandler, point: point, color: dataSet.color(atIndex: j)) + } + + context.restoreGState() + } + else + { + print("There's no IShapeRenderer specified for ScatterDataSet", terminator: "\n") + } + } + + open override func drawValues(context: CGContext) + { + guard + let dataProvider = dataProvider, + let scatterData = dataProvider.scatterData + else { return } + + // if values are drawn + if isDrawingValuesAllowed(dataProvider: dataProvider) + { + guard let dataSets = scatterData.dataSets as? [IScatterChartDataSet] else { return } + + let phaseY = animator.phaseY + + var pt = CGPoint() + + for i in 0 ..< scatterData.dataSetCount + { + let dataSet = dataSets[i] + guard let + formatter = dataSet.valueFormatter, + shouldDrawValues(forDataSet: dataSet) + else { continue } + + let valueFont = dataSet.valueFont + + let trans = dataProvider.getTransformer(forAxis: dataSet.axisDependency) + let valueToPixelMatrix = trans.valueToPixelMatrix + + let iconsOffset = dataSet.iconsOffset + + let shapeSize = dataSet.scatterShapeSize + let lineHeight = valueFont.lineHeight + + _xBounds.set(chart: dataProvider, dataSet: dataSet, animator: animator) + + for j in _xBounds + { + guard let e = dataSet.entryForIndex(j) else { break } + + pt.x = CGFloat(e.x) + pt.y = CGFloat(e.y * phaseY) + pt = pt.applying(valueToPixelMatrix) + + if (!viewPortHandler.isInBoundsRight(pt.x)) + { + break + } + + // make sure the lines don't do shitty things outside bounds + if (!viewPortHandler.isInBoundsLeft(pt.x) + || !viewPortHandler.isInBoundsY(pt.y)) + { + continue + } + + let text = formatter.stringForValue( + e.y, + entry: e, + dataSetIndex: i, + viewPortHandler: viewPortHandler) + + if dataSet.isDrawValuesEnabled + { + ChartUtils.drawText( + context: context, + text: text, + point: CGPoint( + x: pt.x, + y: pt.y - shapeSize - lineHeight), + align: .center, + attributes: [NSAttributedString.Key.font: valueFont, NSAttributedString.Key.foregroundColor: dataSet.valueTextColorAt(j)] + ) + } + + if let icon = e.icon, dataSet.isDrawIconsEnabled + { + ChartUtils.drawImage(context: context, + image: icon, + x: pt.x + iconsOffset.x, + y: pt.y + iconsOffset.y, + size: icon.size) + } + } + } + } + } + + open override func drawExtras(context: CGContext) + { + + } + + open override func drawHighlighted(context: CGContext, indices: [Highlight]) + { + guard + let dataProvider = dataProvider, + let scatterData = dataProvider.scatterData + else { return } + + context.saveGState() + + for high in indices + { + guard + let set = scatterData.getDataSetByIndex(high.dataSetIndex) as? IScatterChartDataSet, + set.isHighlightEnabled + else { continue } + + guard let entry = set.entryForXValue(high.x, closestToY: high.y) else { continue } + + if !isInBoundsX(entry: entry, dataSet: set) { continue } + + context.setStrokeColor(set.highlightColor.cgColor) + context.setLineWidth(set.highlightLineWidth) + if set.highlightLineDashLengths != nil + { + context.setLineDash(phase: set.highlightLineDashPhase, lengths: set.highlightLineDashLengths!) + } + else + { + context.setLineDash(phase: 0.0, lengths: []) + } + + let x = entry.x // get the x-position + let y = entry.y * Double(animator.phaseY) + + let trans = dataProvider.getTransformer(forAxis: set.axisDependency) + + let pt = trans.pixelForValues(x: x, y: y) + + high.setDraw(pt: pt) + + // draw the lines + drawHighlightLines(context: context, point: pt, set: set) + } + + context.restoreGState() + } +} diff --git a/Pods/Charts/Source/Charts/Renderers/XAxisRenderer.swift b/Pods/Charts/Source/Charts/Renderers/XAxisRenderer.swift new file mode 100644 index 00000000..6ea1ba77 --- /dev/null +++ b/Pods/Charts/Source/Charts/Renderers/XAxisRenderer.swift @@ -0,0 +1,440 @@ +// +// XAxisRenderer.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(ChartXAxisRenderer) +open class XAxisRenderer: AxisRendererBase +{ + @objc public init(viewPortHandler: ViewPortHandler, xAxis: XAxis?, transformer: Transformer?) + { + super.init(viewPortHandler: viewPortHandler, transformer: transformer, axis: xAxis) + } + + open override func computeAxis(min: Double, max: Double, inverted: Bool) + { + var min = min, max = max + + if let transformer = self.transformer + { + // calculate the starting and entry point of the y-labels (depending on + // zoom / contentrect bounds) + if viewPortHandler.contentWidth > 10 && !viewPortHandler.isFullyZoomedOutX + { + let p1 = transformer.valueForTouchPoint(CGPoint(x: viewPortHandler.contentLeft, y: viewPortHandler.contentTop)) + let p2 = transformer.valueForTouchPoint(CGPoint(x: viewPortHandler.contentRight, y: viewPortHandler.contentTop)) + + if inverted + { + min = Double(p2.x) + max = Double(p1.x) + } + else + { + min = Double(p1.x) + max = Double(p2.x) + } + } + } + + computeAxisValues(min: min, max: max) + } + + open override func computeAxisValues(min: Double, max: Double) + { + super.computeAxisValues(min: min, max: max) + + computeSize() + } + + @objc open func computeSize() + { + guard let + xAxis = self.axis as? XAxis + else { return } + + let longest = xAxis.getLongestLabel() + + let labelSize = longest.size(withAttributes: [NSAttributedString.Key.font: xAxis.labelFont]) + + let labelWidth = labelSize.width + let labelHeight = labelSize.height + + let labelRotatedSize = labelSize.rotatedBy(degrees: xAxis.labelRotationAngle) + + xAxis.labelWidth = labelWidth + xAxis.labelHeight = labelHeight + xAxis.labelRotatedWidth = labelRotatedSize.width + xAxis.labelRotatedHeight = labelRotatedSize.height + } + + open override func renderAxisLabels(context: CGContext) + { + guard let xAxis = self.axis as? XAxis else { return } + + if !xAxis.isEnabled || !xAxis.isDrawLabelsEnabled + { + return + } + + let yOffset = xAxis.yOffset + + if xAxis.labelPosition == .top + { + drawLabels(context: context, pos: viewPortHandler.contentTop - yOffset, anchor: CGPoint(x: 0.5, y: 1.0)) + } + else if xAxis.labelPosition == .topInside + { + drawLabels(context: context, pos: viewPortHandler.contentTop + yOffset + xAxis.labelRotatedHeight, anchor: CGPoint(x: 0.5, y: 1.0)) + } + else if xAxis.labelPosition == .bottom + { + drawLabels(context: context, pos: viewPortHandler.contentBottom + yOffset, anchor: CGPoint(x: 0.5, y: 0.0)) + } + else if xAxis.labelPosition == .bottomInside + { + drawLabels(context: context, pos: viewPortHandler.contentBottom - yOffset - xAxis.labelRotatedHeight, anchor: CGPoint(x: 0.5, y: 0.0)) + } + else + { // BOTH SIDED + drawLabels(context: context, pos: viewPortHandler.contentTop - yOffset, anchor: CGPoint(x: 0.5, y: 1.0)) + drawLabels(context: context, pos: viewPortHandler.contentBottom + yOffset, anchor: CGPoint(x: 0.5, y: 0.0)) + } + } + + private var _axisLineSegmentsBuffer = [CGPoint](repeating: CGPoint(), count: 2) + + open override func renderAxisLine(context: CGContext) + { + guard let xAxis = self.axis as? XAxis else { return } + + if !xAxis.isEnabled || !xAxis.isDrawAxisLineEnabled + { + return + } + + context.saveGState() + + context.setStrokeColor(xAxis.axisLineColor.cgColor) + context.setLineWidth(xAxis.axisLineWidth) + if xAxis.axisLineDashLengths != nil + { + context.setLineDash(phase: xAxis.axisLineDashPhase, lengths: xAxis.axisLineDashLengths) + } + else + { + context.setLineDash(phase: 0.0, lengths: []) + } + + if xAxis.labelPosition == .top + || xAxis.labelPosition == .topInside + || xAxis.labelPosition == .bothSided + { + _axisLineSegmentsBuffer[0].x = viewPortHandler.contentLeft + _axisLineSegmentsBuffer[0].y = viewPortHandler.contentTop + _axisLineSegmentsBuffer[1].x = viewPortHandler.contentRight + _axisLineSegmentsBuffer[1].y = viewPortHandler.contentTop + context.strokeLineSegments(between: _axisLineSegmentsBuffer) + } + + if xAxis.labelPosition == .bottom + || xAxis.labelPosition == .bottomInside + || xAxis.labelPosition == .bothSided + { + _axisLineSegmentsBuffer[0].x = viewPortHandler.contentLeft + _axisLineSegmentsBuffer[0].y = viewPortHandler.contentBottom + _axisLineSegmentsBuffer[1].x = viewPortHandler.contentRight + _axisLineSegmentsBuffer[1].y = viewPortHandler.contentBottom + context.strokeLineSegments(between: _axisLineSegmentsBuffer) + } + + context.restoreGState() + } + + /// draws the x-labels on the specified y-position + @objc open func drawLabels(context: CGContext, pos: CGFloat, anchor: CGPoint) + { + guard + let xAxis = self.axis as? XAxis, + let transformer = self.transformer + else { return } + + let paraStyle = NSParagraphStyle.default.mutableCopy() as! NSMutableParagraphStyle + paraStyle.alignment = .center + + let labelAttrs: [NSAttributedString.Key : Any] = [ + .font: xAxis.labelFont, + .foregroundColor: xAxis.labelTextColor, + .paragraphStyle: paraStyle + ] + let labelRotationAngleRadians = xAxis.labelRotationAngle.DEG2RAD + + let centeringEnabled = xAxis.isCenterAxisLabelsEnabled + + let valueToPixelMatrix = transformer.valueToPixelMatrix + + var position = CGPoint(x: 0.0, y: 0.0) + + var labelMaxSize = CGSize() + + if xAxis.isWordWrapEnabled + { + labelMaxSize.width = xAxis.wordWrapWidthPercent * valueToPixelMatrix.a + } + + let entries = xAxis.entries + + for i in stride(from: 0, to: entries.count, by: 1) + { + if centeringEnabled + { + position.x = CGFloat(xAxis.centeredEntries[i]) + } + else + { + position.x = CGFloat(entries[i]) + } + + position.y = 0.0 + position = position.applying(valueToPixelMatrix) + + if viewPortHandler.isInBoundsX(position.x) + { + let label = xAxis.valueFormatter?.stringForValue(xAxis.entries[i], axis: xAxis) ?? "" + + let labelns = label as NSString + + if xAxis.isAvoidFirstLastClippingEnabled + { + // avoid clipping of the last + if i == xAxis.entryCount - 1 && xAxis.entryCount > 1 + { + let width = labelns.boundingRect(with: labelMaxSize, options: .usesLineFragmentOrigin, attributes: labelAttrs, context: nil).size.width + + if width > viewPortHandler.offsetRight * 2.0 + && position.x + width > viewPortHandler.chartWidth + { + position.x -= width / 2.0 + } + } + else if i == 0 + { // avoid clipping of the first + let width = labelns.boundingRect(with: labelMaxSize, options: .usesLineFragmentOrigin, attributes: labelAttrs, context: nil).size.width + position.x += width / 2.0 + } + } + + drawLabel(context: context, + formattedLabel: label, + x: position.x, + y: pos, + attributes: labelAttrs, + constrainedToSize: labelMaxSize, + anchor: anchor, + angleRadians: labelRotationAngleRadians) + } + } + } + + @objc open func drawLabel( + context: CGContext, + formattedLabel: String, + x: CGFloat, + y: CGFloat, + attributes: [NSAttributedString.Key : Any], + constrainedToSize: CGSize, + anchor: CGPoint, + angleRadians: CGFloat) + { + ChartUtils.drawMultilineText( + context: context, + text: formattedLabel, + point: CGPoint(x: x, y: y), + attributes: attributes, + constrainedToSize: constrainedToSize, + anchor: anchor, + angleRadians: angleRadians) + } + + open override func renderGridLines(context: CGContext) + { + guard + let xAxis = self.axis as? XAxis, + let transformer = self.transformer + else { return } + + if !xAxis.isDrawGridLinesEnabled || !xAxis.isEnabled + { + return + } + + context.saveGState() + defer { context.restoreGState() } + context.clip(to: self.gridClippingRect) + + context.setShouldAntialias(xAxis.gridAntialiasEnabled) + context.setStrokeColor(xAxis.gridColor.cgColor) + context.setLineWidth(xAxis.gridLineWidth) + context.setLineCap(xAxis.gridLineCap) + + if xAxis.gridLineDashLengths != nil + { + context.setLineDash(phase: xAxis.gridLineDashPhase, lengths: xAxis.gridLineDashLengths) + } + else + { + context.setLineDash(phase: 0.0, lengths: []) + } + + let valueToPixelMatrix = transformer.valueToPixelMatrix + + var position = CGPoint(x: 0.0, y: 0.0) + + let entries = xAxis.entries + + for i in stride(from: 0, to: entries.count, by: 1) + { + position.x = CGFloat(entries[i]) + position.y = position.x + position = position.applying(valueToPixelMatrix) + + drawGridLine(context: context, x: position.x, y: position.y) + } + } + + @objc open var gridClippingRect: CGRect + { + var contentRect = viewPortHandler.contentRect + let dx = self.axis?.gridLineWidth ?? 0.0 + contentRect.origin.x -= dx / 2.0 + contentRect.size.width += dx + return contentRect + } + + @objc open func drawGridLine(context: CGContext, x: CGFloat, y: CGFloat) + { + if x >= viewPortHandler.offsetLeft + && x <= viewPortHandler.chartWidth + { + context.beginPath() + context.move(to: CGPoint(x: x, y: viewPortHandler.contentTop)) + context.addLine(to: CGPoint(x: x, y: viewPortHandler.contentBottom)) + context.strokePath() + } + } + + open override func renderLimitLines(context: CGContext) + { + guard + let xAxis = self.axis as? XAxis, + let transformer = self.transformer, + !xAxis.limitLines.isEmpty + else { return } + + let trans = transformer.valueToPixelMatrix + + var position = CGPoint(x: 0.0, y: 0.0) + + for l in xAxis.limitLines where l.isEnabled + { + context.saveGState() + defer { context.restoreGState() } + + var clippingRect = viewPortHandler.contentRect + clippingRect.origin.x -= l.lineWidth / 2.0 + clippingRect.size.width += l.lineWidth + context.clip(to: clippingRect) + + position.x = CGFloat(l.limit) + position.y = 0.0 + position = position.applying(trans) + + renderLimitLineLine(context: context, limitLine: l, position: position) + renderLimitLineLabel(context: context, limitLine: l, position: position, yOffset: 2.0 + l.yOffset) + } + } + + @objc open func renderLimitLineLine(context: CGContext, limitLine: ChartLimitLine, position: CGPoint) + { + + context.beginPath() + context.move(to: CGPoint(x: position.x, y: viewPortHandler.contentTop)) + context.addLine(to: CGPoint(x: position.x, y: viewPortHandler.contentBottom)) + + context.setStrokeColor(limitLine.lineColor.cgColor) + context.setLineWidth(limitLine.lineWidth) + if limitLine.lineDashLengths != nil + { + context.setLineDash(phase: limitLine.lineDashPhase, lengths: limitLine.lineDashLengths!) + } + else + { + context.setLineDash(phase: 0.0, lengths: []) + } + + context.strokePath() + } + + @objc open func renderLimitLineLabel(context: CGContext, limitLine: ChartLimitLine, position: CGPoint, yOffset: CGFloat) + { + + let label = limitLine.label + guard limitLine.drawLabelEnabled, !label.isEmpty else { return } + + let labelLineHeight = limitLine.valueFont.lineHeight + + let xOffset: CGFloat = limitLine.lineWidth + limitLine.xOffset + let attributes: [NSAttributedString.Key : Any] = [ + .font : limitLine.valueFont, + .foregroundColor : limitLine.valueTextColor + ] + + let (point, align): (CGPoint, NSTextAlignment) + switch limitLine.labelPosition { + case .topRight: + point = CGPoint( + x: position.x + xOffset, + y: viewPortHandler.contentTop + yOffset + ) + align = .left + + case .bottomRight: + point = CGPoint( + x: position.x + xOffset, + y: viewPortHandler.contentBottom - labelLineHeight - yOffset + ) + align = .left + + case .topLeft: + point = CGPoint( + x: position.x - xOffset, + y: viewPortHandler.contentTop + yOffset + ) + align = .right + + case .bottomLeft: + point = CGPoint( + x: position.x - xOffset, + y: viewPortHandler.contentBottom - labelLineHeight - yOffset + ) + align = .right + } + + ChartUtils.drawText( + context: context, + text: label, + point: point, + align: align, + attributes: attributes + ) + } +} diff --git a/Pods/Charts/Source/Charts/Renderers/XAxisRendererHorizontalBarChart.swift b/Pods/Charts/Source/Charts/Renderers/XAxisRendererHorizontalBarChart.swift new file mode 100644 index 00000000..ce777746 --- /dev/null +++ b/Pods/Charts/Source/Charts/Renderers/XAxisRendererHorizontalBarChart.swift @@ -0,0 +1,356 @@ +// +// XAxisRendererHorizontalBarChart.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 XAxisRendererHorizontalBarChart: XAxisRenderer +{ + internal weak var chart: BarChartView? + + @objc public init(viewPortHandler: ViewPortHandler, xAxis: XAxis?, transformer: Transformer?, chart: BarChartView) + { + super.init(viewPortHandler: viewPortHandler, xAxis: xAxis, transformer: transformer) + + self.chart = chart + } + + open override func computeAxis(min: Double, max: Double, inverted: Bool) + { + var min = min, max = max + + if let transformer = self.transformer + { + // calculate the starting and entry point of the y-labels (depending on + // zoom / contentrect bounds) + if viewPortHandler.contentWidth > 10 && !viewPortHandler.isFullyZoomedOutY + { + let p1 = transformer.valueForTouchPoint(CGPoint(x: viewPortHandler.contentLeft, y: viewPortHandler.contentBottom)) + let p2 = transformer.valueForTouchPoint(CGPoint(x: viewPortHandler.contentLeft, y: viewPortHandler.contentTop)) + + if inverted + { + min = Double(p2.y) + max = Double(p1.y) + } + else + { + min = Double(p1.y) + max = Double(p2.y) + } + } + } + + computeAxisValues(min: min, max: max) + } + + open override func computeSize() + { + guard let + xAxis = self.axis as? XAxis + else { return } + + let longest = xAxis.getLongestLabel() as NSString + + let labelSize = longest.size(withAttributes: [NSAttributedString.Key.font: xAxis.labelFont]) + + let labelWidth = floor(labelSize.width + xAxis.xOffset * 3.5) + let labelHeight = labelSize.height + let labelRotatedSize = CGSize(width: labelSize.width, height: labelHeight).rotatedBy(degrees: xAxis.labelRotationAngle) + + xAxis.labelWidth = labelWidth + xAxis.labelHeight = labelHeight + xAxis.labelRotatedWidth = round(labelRotatedSize.width + xAxis.xOffset * 3.5) + xAxis.labelRotatedHeight = round(labelRotatedSize.height) + } + + open override func renderAxisLabels(context: CGContext) + { + guard + let xAxis = self.axis as? XAxis + else { return } + + if !xAxis.isEnabled || !xAxis.isDrawLabelsEnabled || chart?.data === nil + { + return + } + + let xoffset = xAxis.xOffset + + if xAxis.labelPosition == .top + { + drawLabels(context: context, pos: viewPortHandler.contentRight + xoffset, anchor: CGPoint(x: 0.0, y: 0.5)) + } + else if xAxis.labelPosition == .topInside + { + drawLabels(context: context, pos: viewPortHandler.contentRight - xoffset, anchor: CGPoint(x: 1.0, y: 0.5)) + } + else if xAxis.labelPosition == .bottom + { + drawLabels(context: context, pos: viewPortHandler.contentLeft - xoffset, anchor: CGPoint(x: 1.0, y: 0.5)) + } + else if xAxis.labelPosition == .bottomInside + { + drawLabels(context: context, pos: viewPortHandler.contentLeft + xoffset, anchor: CGPoint(x: 0.0, y: 0.5)) + } + else + { // BOTH SIDED + drawLabels(context: context, pos: viewPortHandler.contentRight + xoffset, anchor: CGPoint(x: 0.0, y: 0.5)) + drawLabels(context: context, pos: viewPortHandler.contentLeft - xoffset, anchor: CGPoint(x: 1.0, y: 0.5)) + } + } + + /// draws the x-labels on the specified y-position + open override func drawLabels(context: CGContext, pos: CGFloat, anchor: CGPoint) + { + guard + let xAxis = self.axis as? XAxis, + let transformer = self.transformer + else { return } + + let labelFont = xAxis.labelFont + let labelTextColor = xAxis.labelTextColor + let labelRotationAngleRadians = xAxis.labelRotationAngle.DEG2RAD + + let centeringEnabled = xAxis.isCenterAxisLabelsEnabled + + // pre allocate to save performance (dont allocate in loop) + var position = CGPoint(x: 0.0, y: 0.0) + + for i in stride(from: 0, to: xAxis.entryCount, by: 1) + { + // only fill x values + + position.x = 0.0 + + if centeringEnabled + { + position.y = CGFloat(xAxis.centeredEntries[i]) + } + else + { + position.y = CGFloat(xAxis.entries[i]) + } + + transformer.pointValueToPixel(&position) + + if viewPortHandler.isInBoundsY(position.y) + { + if let label = xAxis.valueFormatter?.stringForValue(xAxis.entries[i], axis: xAxis) + { + drawLabel( + context: context, + formattedLabel: label, + x: pos, + y: position.y, + attributes: [NSAttributedString.Key.font: labelFont, NSAttributedString.Key.foregroundColor: labelTextColor], + anchor: anchor, + angleRadians: labelRotationAngleRadians) + } + } + } + } + + @objc open func drawLabel( + context: CGContext, + formattedLabel: String, + x: CGFloat, + y: CGFloat, + attributes: [NSAttributedString.Key : Any], + anchor: CGPoint, + angleRadians: CGFloat) + { + ChartUtils.drawText( + context: context, + text: formattedLabel, + point: CGPoint(x: x, y: y), + attributes: attributes, + anchor: anchor, + angleRadians: angleRadians) + } + + open override var gridClippingRect: CGRect + { + var contentRect = viewPortHandler.contentRect + let dy = self.axis?.gridLineWidth ?? 0.0 + contentRect.origin.y -= dy / 2.0 + contentRect.size.height += dy + return contentRect + } + + private var _gridLineSegmentsBuffer = [CGPoint](repeating: CGPoint(), count: 2) + + open override func drawGridLine(context: CGContext, x: CGFloat, y: CGFloat) + { + if viewPortHandler.isInBoundsY(y) + { + context.beginPath() + context.move(to: CGPoint(x: viewPortHandler.contentLeft, y: y)) + context.addLine(to: CGPoint(x: viewPortHandler.contentRight, y: y)) + context.strokePath() + } + } + + open override func renderAxisLine(context: CGContext) + { + guard let xAxis = self.axis as? XAxis else { return } + + if !xAxis.isEnabled || !xAxis.isDrawAxisLineEnabled + { + return + } + + context.saveGState() + + context.setStrokeColor(xAxis.axisLineColor.cgColor) + context.setLineWidth(xAxis.axisLineWidth) + if xAxis.axisLineDashLengths != nil + { + context.setLineDash(phase: xAxis.axisLineDashPhase, lengths: xAxis.axisLineDashLengths) + } + else + { + context.setLineDash(phase: 0.0, lengths: []) + } + + if xAxis.labelPosition == .top || + xAxis.labelPosition == .topInside || + xAxis.labelPosition == .bothSided + { + context.beginPath() + context.move(to: CGPoint(x: viewPortHandler.contentRight, y: viewPortHandler.contentTop)) + context.addLine(to: CGPoint(x: viewPortHandler.contentRight, y: viewPortHandler.contentBottom)) + context.strokePath() + } + + if xAxis.labelPosition == .bottom || + xAxis.labelPosition == .bottomInside || + xAxis.labelPosition == .bothSided + { + context.beginPath() + context.move(to: CGPoint(x: viewPortHandler.contentLeft, y: viewPortHandler.contentTop)) + context.addLine(to: CGPoint(x: viewPortHandler.contentLeft, y: viewPortHandler.contentBottom)) + context.strokePath() + } + + context.restoreGState() + } + + open override func renderLimitLines(context: CGContext) + { + guard + let xAxis = self.axis as? XAxis, + let transformer = self.transformer + else { return } + + var limitLines = xAxis.limitLines + + if limitLines.count == 0 + { + return + } + + let trans = transformer.valueToPixelMatrix + + var position = CGPoint(x: 0.0, y: 0.0) + + for i in 0 ..< limitLines.count + { + let l = limitLines[i] + + if !l.isEnabled + { + continue + } + + context.saveGState() + defer { context.restoreGState() } + + var clippingRect = viewPortHandler.contentRect + clippingRect.origin.y -= l.lineWidth / 2.0 + clippingRect.size.height += l.lineWidth + context.clip(to: clippingRect) + + position.x = 0.0 + position.y = CGFloat(l.limit) + position = position.applying(trans) + + context.beginPath() + context.move(to: CGPoint(x: viewPortHandler.contentLeft, y: position.y)) + context.addLine(to: CGPoint(x: viewPortHandler.contentRight, y: position.y)) + + context.setStrokeColor(l.lineColor.cgColor) + context.setLineWidth(l.lineWidth) + if l.lineDashLengths != nil + { + context.setLineDash(phase: l.lineDashPhase, lengths: l.lineDashLengths!) + } + else + { + context.setLineDash(phase: 0.0, lengths: []) + } + + context.strokePath() + + let label = l.label + + // if drawing the limit-value label is enabled + if l.drawLabelEnabled && label.count > 0 + { + let labelLineHeight = l.valueFont.lineHeight + + let xOffset: CGFloat = 4.0 + l.xOffset + let yOffset: CGFloat = l.lineWidth + labelLineHeight + l.yOffset + + if l.labelPosition == .topRight + { + ChartUtils.drawText(context: context, + text: label, + point: CGPoint( + x: viewPortHandler.contentRight - xOffset, + y: position.y - yOffset), + align: .right, + attributes: [NSAttributedString.Key.font: l.valueFont, NSAttributedString.Key.foregroundColor: l.valueTextColor]) + } + else if l.labelPosition == .bottomRight + { + ChartUtils.drawText(context: context, + text: label, + point: CGPoint( + x: viewPortHandler.contentRight - xOffset, + y: position.y + yOffset - labelLineHeight), + align: .right, + attributes: [NSAttributedString.Key.font: l.valueFont, NSAttributedString.Key.foregroundColor: l.valueTextColor]) + } + else if l.labelPosition == .topLeft + { + ChartUtils.drawText(context: context, + text: label, + point: CGPoint( + x: viewPortHandler.contentLeft + xOffset, + y: position.y - yOffset), + align: .left, + attributes: [NSAttributedString.Key.font: l.valueFont, NSAttributedString.Key.foregroundColor: l.valueTextColor]) + } + else + { + ChartUtils.drawText(context: context, + text: label, + point: CGPoint( + x: viewPortHandler.contentLeft + xOffset, + y: position.y + yOffset - labelLineHeight), + align: .left, + attributes: [NSAttributedString.Key.font: l.valueFont, NSAttributedString.Key.foregroundColor: l.valueTextColor]) + } + } + } + } +} diff --git a/Pods/Charts/Source/Charts/Renderers/XAxisRendererRadarChart.swift b/Pods/Charts/Source/Charts/Renderers/XAxisRendererRadarChart.swift new file mode 100644 index 00000000..c5fcedf5 --- /dev/null +++ b/Pods/Charts/Source/Charts/Renderers/XAxisRendererRadarChart.swift @@ -0,0 +1,91 @@ +// +// XAxisRendererRadarChart.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 XAxisRendererRadarChart: XAxisRenderer +{ + @objc open weak var chart: RadarChartView? + + @objc public init(viewPortHandler: ViewPortHandler, xAxis: XAxis?, chart: RadarChartView) + { + super.init(viewPortHandler: viewPortHandler, xAxis: xAxis, transformer: nil) + + self.chart = chart + } + + open override func renderAxisLabels(context: CGContext) + { + guard let + xAxis = axis as? XAxis, + let chart = chart + else { return } + + if !xAxis.isEnabled || !xAxis.isDrawLabelsEnabled + { + return + } + + let labelFont = xAxis.labelFont + let labelTextColor = xAxis.labelTextColor + let labelRotationAngleRadians = xAxis.labelRotationAngle.RAD2DEG + let drawLabelAnchor = CGPoint(x: 0.5, y: 0.25) + + let sliceangle = chart.sliceAngle + + // calculate the factor that is needed for transforming the value to pixels + let factor = chart.factor + + let center = chart.centerOffsets + + for i in stride(from: 0, to: chart.data?.maxEntryCountSet?.entryCount ?? 0, by: 1) + { + + let label = xAxis.valueFormatter?.stringForValue(Double(i), axis: xAxis) ?? "" + + let angle = (sliceangle * CGFloat(i) + chart.rotationAngle).truncatingRemainder(dividingBy: 360.0) + + let p = center.moving(distance: CGFloat(chart.yRange) * factor + xAxis.labelRotatedWidth / 2.0, atAngle: angle) + + drawLabel(context: context, + formattedLabel: label, + x: p.x, + y: p.y - xAxis.labelRotatedHeight / 2.0, + attributes: [NSAttributedString.Key.font: labelFont, NSAttributedString.Key.foregroundColor: labelTextColor], + anchor: drawLabelAnchor, + angleRadians: labelRotationAngleRadians) + } + } + + @objc open func drawLabel( + context: CGContext, + formattedLabel: String, + x: CGFloat, + y: CGFloat, + attributes: [NSAttributedString.Key : Any], + anchor: CGPoint, + angleRadians: CGFloat) + { + ChartUtils.drawText( + context: context, + text: formattedLabel, + point: CGPoint(x: x, y: y), + attributes: attributes, + anchor: anchor, + angleRadians: angleRadians) + } + + open override func renderLimitLines(context: CGContext) + { + /// XAxis LimitLines on RadarChart not yet supported. + } +} diff --git a/Pods/Charts/Source/Charts/Renderers/YAxisRenderer.swift b/Pods/Charts/Source/Charts/Renderers/YAxisRenderer.swift new file mode 100644 index 00000000..4fb3dd2e --- /dev/null +++ b/Pods/Charts/Source/Charts/Renderers/YAxisRenderer.swift @@ -0,0 +1,386 @@ +// +// YAxisRenderer.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(ChartYAxisRenderer) +open class YAxisRenderer: AxisRendererBase +{ + @objc public init(viewPortHandler: ViewPortHandler, yAxis: YAxis?, transformer: Transformer?) + { + super.init(viewPortHandler: viewPortHandler, transformer: transformer, axis: yAxis) + } + + /// draws the y-axis labels to the screen + open override func renderAxisLabels(context: CGContext) + { + guard let yAxis = self.axis as? YAxis else { return } + + if !yAxis.isEnabled || !yAxis.isDrawLabelsEnabled + { + return + } + + let xoffset = yAxis.xOffset + let yoffset = yAxis.labelFont.lineHeight / 2.5 + yAxis.yOffset + + let dependency = yAxis.axisDependency + let labelPosition = yAxis.labelPosition + + var xPos = CGFloat(0.0) + + var textAlign: NSTextAlignment + + if dependency == .left + { + if labelPosition == .outsideChart + { + textAlign = .right + xPos = viewPortHandler.offsetLeft - xoffset + } + else + { + textAlign = .left + xPos = viewPortHandler.offsetLeft + xoffset + } + + } + else + { + if labelPosition == .outsideChart + { + textAlign = .left + xPos = viewPortHandler.contentRight + xoffset + } + else + { + textAlign = .right + xPos = viewPortHandler.contentRight - xoffset + } + } + + drawYLabels( + context: context, + fixedPosition: xPos, + positions: transformedPositions(), + offset: yoffset - yAxis.labelFont.lineHeight, + textAlign: textAlign) + } + + open override func renderAxisLine(context: CGContext) + { + guard let yAxis = self.axis as? YAxis else { return } + + if !yAxis.isEnabled || !yAxis.drawAxisLineEnabled + { + return + } + + context.saveGState() + + context.setStrokeColor(yAxis.axisLineColor.cgColor) + context.setLineWidth(yAxis.axisLineWidth) + if yAxis.axisLineDashLengths != nil + { + context.setLineDash(phase: yAxis.axisLineDashPhase, lengths: yAxis.axisLineDashLengths) + } + else + { + context.setLineDash(phase: 0.0, lengths: []) + } + + if yAxis.axisDependency == .left + { + context.beginPath() + context.move(to: CGPoint(x: viewPortHandler.contentLeft, y: viewPortHandler.contentTop)) + context.addLine(to: CGPoint(x: viewPortHandler.contentLeft, y: viewPortHandler.contentBottom)) + context.strokePath() + } + else + { + context.beginPath() + context.move(to: CGPoint(x: viewPortHandler.contentRight, y: viewPortHandler.contentTop)) + context.addLine(to: CGPoint(x: viewPortHandler.contentRight, y: viewPortHandler.contentBottom)) + context.strokePath() + } + + context.restoreGState() + } + + /// draws the y-labels on the specified x-position + internal func drawYLabels( + context: CGContext, + fixedPosition: CGFloat, + positions: [CGPoint], + offset: CGFloat, + textAlign: NSTextAlignment) + { + guard + let yAxis = self.axis as? YAxis + else { return } + + let labelFont = yAxis.labelFont + let labelTextColor = yAxis.labelTextColor + + let from = yAxis.isDrawBottomYLabelEntryEnabled ? 0 : 1 + let to = yAxis.isDrawTopYLabelEntryEnabled ? yAxis.entryCount : (yAxis.entryCount - 1) + + for i in stride(from: from, to: to, by: 1) + { + let text = yAxis.getFormattedLabel(i) + + ChartUtils.drawText( + context: context, + text: text, + point: CGPoint(x: fixedPosition, y: positions[i].y + offset), + align: textAlign, + attributes: [.font: labelFont, .foregroundColor: labelTextColor] + ) + } + } + + open override func renderGridLines(context: CGContext) + { + guard let + yAxis = self.axis as? YAxis + else { return } + + if !yAxis.isEnabled + { + return + } + + if yAxis.drawGridLinesEnabled + { + let positions = transformedPositions() + + context.saveGState() + defer { context.restoreGState() } + context.clip(to: self.gridClippingRect) + + context.setShouldAntialias(yAxis.gridAntialiasEnabled) + context.setStrokeColor(yAxis.gridColor.cgColor) + context.setLineWidth(yAxis.gridLineWidth) + context.setLineCap(yAxis.gridLineCap) + + if yAxis.gridLineDashLengths != nil + { + context.setLineDash(phase: yAxis.gridLineDashPhase, lengths: yAxis.gridLineDashLengths) + + } + else + { + context.setLineDash(phase: 0.0, lengths: []) + } + + // draw the grid + positions.forEach { drawGridLine(context: context, position: $0) } + } + + if yAxis.drawZeroLineEnabled + { + // draw zero line + drawZeroLine(context: context) + } + } + + @objc open var gridClippingRect: CGRect + { + var contentRect = viewPortHandler.contentRect + let dy = self.axis?.gridLineWidth ?? 0.0 + contentRect.origin.y -= dy / 2.0 + contentRect.size.height += dy + return contentRect + } + + @objc open func drawGridLine( + context: CGContext, + position: CGPoint) + { + context.beginPath() + context.move(to: CGPoint(x: viewPortHandler.contentLeft, y: position.y)) + context.addLine(to: CGPoint(x: viewPortHandler.contentRight, y: position.y)) + context.strokePath() + } + + @objc open func transformedPositions() -> [CGPoint] + { + guard + let yAxis = self.axis as? YAxis, + let transformer = self.transformer + else { return [CGPoint]() } + + var positions = [CGPoint]() + positions.reserveCapacity(yAxis.entryCount) + + let entries = yAxis.entries + + for i in stride(from: 0, to: yAxis.entryCount, by: 1) + { + positions.append(CGPoint(x: 0.0, y: entries[i])) + } + + transformer.pointValuesToPixel(&positions) + + return positions + } + + /// Draws the zero line at the specified position. + @objc open func drawZeroLine(context: CGContext) + { + guard + let yAxis = self.axis as? YAxis, + let transformer = self.transformer, + let zeroLineColor = yAxis.zeroLineColor + else { return } + + context.saveGState() + defer { context.restoreGState() } + + var clippingRect = viewPortHandler.contentRect + clippingRect.origin.y -= yAxis.zeroLineWidth / 2.0 + clippingRect.size.height += yAxis.zeroLineWidth + context.clip(to: clippingRect) + + context.setStrokeColor(zeroLineColor.cgColor) + context.setLineWidth(yAxis.zeroLineWidth) + + let pos = transformer.pixelForValues(x: 0.0, y: 0.0) + + if yAxis.zeroLineDashLengths != nil + { + context.setLineDash(phase: yAxis.zeroLineDashPhase, lengths: yAxis.zeroLineDashLengths!) + } + else + { + context.setLineDash(phase: 0.0, lengths: []) + } + + context.move(to: CGPoint(x: viewPortHandler.contentLeft, y: pos.y)) + context.addLine(to: CGPoint(x: viewPortHandler.contentRight, y: pos.y)) + context.drawPath(using: CGPathDrawingMode.stroke) + } + + open override func renderLimitLines(context: CGContext) + { + guard + let yAxis = self.axis as? YAxis, + let transformer = self.transformer + else { return } + + var limitLines = yAxis.limitLines + + if limitLines.count == 0 + { + return + } + + context.saveGState() + + let trans = transformer.valueToPixelMatrix + + var position = CGPoint(x: 0.0, y: 0.0) + + for i in 0 ..< limitLines.count + { + let l = limitLines[i] + + if !l.isEnabled + { + continue + } + + context.saveGState() + defer { context.restoreGState() } + + var clippingRect = viewPortHandler.contentRect + clippingRect.origin.y -= l.lineWidth / 2.0 + clippingRect.size.height += l.lineWidth + context.clip(to: clippingRect) + + position.x = 0.0 + position.y = CGFloat(l.limit) + position = position.applying(trans) + + context.beginPath() + context.move(to: CGPoint(x: viewPortHandler.contentLeft, y: position.y)) + context.addLine(to: CGPoint(x: viewPortHandler.contentRight, y: position.y)) + + context.setStrokeColor(l.lineColor.cgColor) + context.setLineWidth(l.lineWidth) + if l.lineDashLengths != nil + { + context.setLineDash(phase: l.lineDashPhase, lengths: l.lineDashLengths!) + } + else + { + context.setLineDash(phase: 0.0, lengths: []) + } + + context.strokePath() + + let label = l.label + + // if drawing the limit-value label is enabled + if l.drawLabelEnabled && label.count > 0 + { + let labelLineHeight = l.valueFont.lineHeight + + let xOffset: CGFloat = 4.0 + l.xOffset + let yOffset: CGFloat = l.lineWidth + labelLineHeight + l.yOffset + + if l.labelPosition == .topRight + { + ChartUtils.drawText(context: context, + text: label, + point: CGPoint( + x: viewPortHandler.contentRight - xOffset, + y: position.y - yOffset), + align: .right, + attributes: [NSAttributedString.Key.font: l.valueFont, NSAttributedString.Key.foregroundColor: l.valueTextColor]) + } + else if l.labelPosition == .bottomRight + { + ChartUtils.drawText(context: context, + text: label, + point: CGPoint( + x: viewPortHandler.contentRight - xOffset, + y: position.y + yOffset - labelLineHeight), + align: .right, + attributes: [NSAttributedString.Key.font: l.valueFont, NSAttributedString.Key.foregroundColor: l.valueTextColor]) + } + else if l.labelPosition == .topLeft + { + ChartUtils.drawText(context: context, + text: label, + point: CGPoint( + x: viewPortHandler.contentLeft + xOffset, + y: position.y - yOffset), + align: .left, + attributes: [NSAttributedString.Key.font: l.valueFont, NSAttributedString.Key.foregroundColor: l.valueTextColor]) + } + else + { + ChartUtils.drawText(context: context, + text: label, + point: CGPoint( + x: viewPortHandler.contentLeft + xOffset, + y: position.y + yOffset - labelLineHeight), + align: .left, + attributes: [NSAttributedString.Key.font: l.valueFont, NSAttributedString.Key.foregroundColor: l.valueTextColor]) + } + } + } + + context.restoreGState() + } +} diff --git a/Pods/Charts/Source/Charts/Renderers/YAxisRendererHorizontalBarChart.swift b/Pods/Charts/Source/Charts/Renderers/YAxisRendererHorizontalBarChart.swift new file mode 100644 index 00000000..e9c1af0e --- /dev/null +++ b/Pods/Charts/Source/Charts/Renderers/YAxisRendererHorizontalBarChart.swift @@ -0,0 +1,363 @@ +// +// YAxisRendererHorizontalBarChart.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 YAxisRendererHorizontalBarChart: YAxisRenderer +{ + public override init(viewPortHandler: ViewPortHandler, yAxis: YAxis?, transformer: Transformer?) + { + super.init(viewPortHandler: viewPortHandler, yAxis: yAxis, transformer: transformer) + } + + /// Computes the axis values. + open override func computeAxis(min: Double, max: Double, inverted: Bool) + { + guard let transformer = self.transformer else { return } + + var min = min, max = max + + // calculate the starting and entry point of the y-labels (depending on zoom / contentrect bounds) + if viewPortHandler.contentHeight > 10.0 && !viewPortHandler.isFullyZoomedOutX + { + let p1 = transformer.valueForTouchPoint(CGPoint(x: viewPortHandler.contentLeft, y: viewPortHandler.contentTop)) + let p2 = transformer.valueForTouchPoint(CGPoint(x: viewPortHandler.contentRight, y: viewPortHandler.contentTop)) + + if !inverted + { + min = Double(p1.x) + max = Double(p2.x) + } + else + { + min = Double(p2.x) + max = Double(p1.x) + } + } + + computeAxisValues(min: min, max: max) + } + + /// draws the y-axis labels to the screen + open override func renderAxisLabels(context: CGContext) + { + guard let yAxis = axis as? YAxis else { return } + + if !yAxis.isEnabled || !yAxis.isDrawLabelsEnabled + { + return + } + + let lineHeight = yAxis.labelFont.lineHeight + let baseYOffset: CGFloat = 2.5 + + let dependency = yAxis.axisDependency + let labelPosition = yAxis.labelPosition + + var yPos: CGFloat = 0.0 + + if dependency == .left + { + if labelPosition == .outsideChart + { + yPos = viewPortHandler.contentTop - baseYOffset + } + else + { + yPos = viewPortHandler.contentTop - baseYOffset + } + } + else + { + if labelPosition == .outsideChart + { + yPos = viewPortHandler.contentBottom + lineHeight + baseYOffset + } + else + { + yPos = viewPortHandler.contentBottom + lineHeight + baseYOffset + } + } + + // For compatibility with Android code, we keep above calculation the same, + // And here we pull the line back up + yPos -= lineHeight + + drawYLabels( + context: context, + fixedPosition: yPos, + positions: transformedPositions(), + offset: yAxis.yOffset) + } + + open override func renderAxisLine(context: CGContext) + { + guard let yAxis = axis as? YAxis else { return } + + if !yAxis.isEnabled || !yAxis.drawAxisLineEnabled + { + return + } + + context.saveGState() + + context.setStrokeColor(yAxis.axisLineColor.cgColor) + context.setLineWidth(yAxis.axisLineWidth) + if yAxis.axisLineDashLengths != nil + { + context.setLineDash(phase: yAxis.axisLineDashPhase, lengths: yAxis.axisLineDashLengths) + } + else + { + context.setLineDash(phase: 0.0, lengths: []) + } + + if yAxis.axisDependency == .left + { + context.beginPath() + context.move(to: CGPoint(x: viewPortHandler.contentLeft, y: viewPortHandler.contentTop)) + context.addLine(to: CGPoint(x: viewPortHandler.contentRight, y: viewPortHandler.contentTop)) + context.strokePath() + } + else + { + context.beginPath() + context.move(to: CGPoint(x: viewPortHandler.contentLeft, y: viewPortHandler.contentBottom)) + context.addLine(to: CGPoint(x: viewPortHandler.contentRight, y: viewPortHandler.contentBottom)) + context.strokePath() } + + context.restoreGState() + } + + /// draws the y-labels on the specified x-position + @objc open func drawYLabels( + context: CGContext, + fixedPosition: CGFloat, + positions: [CGPoint], + offset: CGFloat) + { + guard let + yAxis = axis as? YAxis + else { return } + + let labelFont = yAxis.labelFont + let labelTextColor = yAxis.labelTextColor + + let from = yAxis.isDrawBottomYLabelEntryEnabled ? 0 : 1 + let to = yAxis.isDrawTopYLabelEntryEnabled ? yAxis.entryCount : (yAxis.entryCount - 1) + + for i in stride(from: from, to: to, by: 1) + { + let text = yAxis.getFormattedLabel(i) + + ChartUtils.drawText( + context: context, + text: text, + point: CGPoint(x: positions[i].x, y: fixedPosition - offset), + align: .center, + attributes: [NSAttributedString.Key.font: labelFont, NSAttributedString.Key.foregroundColor: labelTextColor]) + } + } + + open override var gridClippingRect: CGRect + { + var contentRect = viewPortHandler.contentRect + let dx = self.axis?.gridLineWidth ?? 0.0 + contentRect.origin.x -= dx / 2.0 + contentRect.size.width += dx + return contentRect + } + + open override func drawGridLine( + context: CGContext, + position: CGPoint) + { + context.beginPath() + context.move(to: CGPoint(x: position.x, y: viewPortHandler.contentTop)) + context.addLine(to: CGPoint(x: position.x, y: viewPortHandler.contentBottom)) + context.strokePath() + } + + open override func transformedPositions() -> [CGPoint] + { + guard + let yAxis = self.axis as? YAxis, + let transformer = self.transformer + else { return [CGPoint]() } + + var positions = [CGPoint]() + positions.reserveCapacity(yAxis.entryCount) + + let entries = yAxis.entries + + for i in stride(from: 0, to: yAxis.entryCount, by: 1) + { + positions.append(CGPoint(x: entries[i], y: 0.0)) + } + + transformer.pointValuesToPixel(&positions) + + return positions + } + + /// Draws the zero line at the specified position. + open override func drawZeroLine(context: CGContext) + { + guard + let yAxis = self.axis as? YAxis, + let transformer = self.transformer, + let zeroLineColor = yAxis.zeroLineColor + else { return } + + context.saveGState() + defer { context.restoreGState() } + + var clippingRect = viewPortHandler.contentRect + clippingRect.origin.x -= yAxis.zeroLineWidth / 2.0 + clippingRect.size.width += yAxis.zeroLineWidth + context.clip(to: clippingRect) + + context.setStrokeColor(zeroLineColor.cgColor) + context.setLineWidth(yAxis.zeroLineWidth) + + let pos = transformer.pixelForValues(x: 0.0, y: 0.0) + + if yAxis.zeroLineDashLengths != nil + { + context.setLineDash(phase: yAxis.zeroLineDashPhase, lengths: yAxis.zeroLineDashLengths!) + } + else + { + context.setLineDash(phase: 0.0, lengths: []) + } + + context.move(to: CGPoint(x: pos.x - 1.0, y: viewPortHandler.contentTop)) + context.addLine(to: CGPoint(x: pos.x - 1.0, y: viewPortHandler.contentBottom)) + context.drawPath(using: CGPathDrawingMode.stroke) + } + + private var _limitLineSegmentsBuffer = [CGPoint](repeating: CGPoint(), count: 2) + + open override func renderLimitLines(context: CGContext) + { + guard + let yAxis = axis as? YAxis, + let transformer = self.transformer + else { return } + + var limitLines = yAxis.limitLines + + if limitLines.count <= 0 + { + return + } + + context.saveGState() + + let trans = transformer.valueToPixelMatrix + + var position = CGPoint(x: 0.0, y: 0.0) + + for i in 0 ..< limitLines.count + { + let l = limitLines[i] + + if !l.isEnabled + { + continue + } + + context.saveGState() + defer { context.restoreGState() } + + var clippingRect = viewPortHandler.contentRect + clippingRect.origin.x -= l.lineWidth / 2.0 + clippingRect.size.width += l.lineWidth + context.clip(to: clippingRect) + + position.x = CGFloat(l.limit) + position.y = 0.0 + position = position.applying(trans) + + context.beginPath() + context.move(to: CGPoint(x: position.x, y: viewPortHandler.contentTop)) + context.addLine(to: CGPoint(x: position.x, y: viewPortHandler.contentBottom)) + + context.setStrokeColor(l.lineColor.cgColor) + context.setLineWidth(l.lineWidth) + if l.lineDashLengths != nil + { + context.setLineDash(phase: l.lineDashPhase, lengths: l.lineDashLengths!) + } + else + { + context.setLineDash(phase: 0.0, lengths: []) + } + + context.strokePath() + + let label = l.label + + // if drawing the limit-value label is enabled + if l.drawLabelEnabled && label.count > 0 + { + let labelLineHeight = l.valueFont.lineHeight + + let xOffset: CGFloat = l.lineWidth + l.xOffset + let yOffset: CGFloat = 2.0 + l.yOffset + + if l.labelPosition == .topRight + { + ChartUtils.drawText(context: context, + text: label, + point: CGPoint( + x: position.x + xOffset, + y: viewPortHandler.contentTop + yOffset), + align: .left, + attributes: [NSAttributedString.Key.font: l.valueFont, NSAttributedString.Key.foregroundColor: l.valueTextColor]) + } + else if l.labelPosition == .bottomRight + { + ChartUtils.drawText(context: context, + text: label, + point: CGPoint( + x: position.x + xOffset, + y: viewPortHandler.contentBottom - labelLineHeight - yOffset), + align: .left, + attributes: [NSAttributedString.Key.font: l.valueFont, NSAttributedString.Key.foregroundColor: l.valueTextColor]) + } + else if l.labelPosition == .topLeft + { + ChartUtils.drawText(context: context, + text: label, + point: CGPoint( + x: position.x - xOffset, + y: viewPortHandler.contentTop + yOffset), + align: .right, + attributes: [NSAttributedString.Key.font: l.valueFont, NSAttributedString.Key.foregroundColor: l.valueTextColor]) + } + else + { + ChartUtils.drawText(context: context, + text: label, + point: CGPoint( + x: position.x - xOffset, + y: viewPortHandler.contentBottom - labelLineHeight - yOffset), + align: .right, + attributes: [NSAttributedString.Key.font: l.valueFont, NSAttributedString.Key.foregroundColor: l.valueTextColor]) + } + } + } + + context.restoreGState() + } +} diff --git a/Pods/Charts/Source/Charts/Renderers/YAxisRendererRadarChart.swift b/Pods/Charts/Source/Charts/Renderers/YAxisRendererRadarChart.swift new file mode 100644 index 00000000..c98971e9 --- /dev/null +++ b/Pods/Charts/Source/Charts/Renderers/YAxisRendererRadarChart.swift @@ -0,0 +1,273 @@ +// +// YAxisRendererRadarChart.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 YAxisRendererRadarChart: YAxisRenderer +{ + private weak var chart: RadarChartView? + + @objc public init(viewPortHandler: ViewPortHandler, yAxis: YAxis?, chart: RadarChartView) + { + super.init(viewPortHandler: viewPortHandler, yAxis: yAxis, transformer: nil) + + self.chart = chart + } + + open override func computeAxisValues(min yMin: Double, max yMax: Double) + { + guard let + axis = axis as? YAxis + else { return } + + let labelCount = axis.labelCount + let range = abs(yMax - yMin) + + if labelCount == 0 || range <= 0 || range.isInfinite + { + axis.entries = [Double]() + axis.centeredEntries = [Double]() + return + } + + // Find out how much spacing (in yValue space) between axis values + let rawInterval = range / Double(labelCount) + var interval = rawInterval.roundedToNextSignficant() + + // If granularity is enabled, then do not allow the interval to go below specified granularity. + // This is used to avoid repeated values when rounding values for display. + if axis.isGranularityEnabled + { + interval = interval < axis.granularity ? axis.granularity : interval + } + + // Normalize interval + let intervalMagnitude = pow(10.0, floor(log10(interval))).roundedToNextSignficant() + let intervalSigDigit = Int(interval / intervalMagnitude) + + if intervalSigDigit > 5 + { + // Use one order of magnitude higher, to avoid intervals like 0.9 or 90 + // if it's 0.0 after floor(), we use the old value + interval = floor(10.0 * intervalMagnitude) == 0.0 ? interval : floor(10.0 * intervalMagnitude) + } + + let centeringEnabled = axis.isCenterAxisLabelsEnabled + var n = centeringEnabled ? 1 : 0 + + // force label count + if axis.isForceLabelsEnabled + { + let step = Double(range) / Double(labelCount - 1) + + // Ensure stops contains at least n elements. + axis.entries.removeAll(keepingCapacity: true) + axis.entries.reserveCapacity(labelCount) + + var v = yMin + + for _ in 0 ..< labelCount + { + axis.entries.append(v) + v += step + } + + n = labelCount + } + else + { + // no forced count + + var first = interval == 0.0 ? 0.0 : ceil(yMin / interval) * interval + + if centeringEnabled + { + first -= interval + } + + let last = interval == 0.0 ? 0.0 : (floor(yMax / interval) * interval).nextUp + + if interval != 0.0 + { + for _ in stride(from: first, through: last, by: interval) + { + n += 1 + } + } + + n += 1 + + // Ensure stops contains at least n elements. + axis.entries.removeAll(keepingCapacity: true) + axis.entries.reserveCapacity(labelCount) + + var f = first + var i = 0 + while i < n + { + if f == 0.0 + { + // Fix for IEEE negative zero case (Where value == -0.0, and 0.0 == -0.0) + f = 0.0 + } + + axis.entries.append(Double(f)) + + f += interval + i += 1 + } + } + + // set decimals + if interval < 1 + { + axis.decimals = Int(ceil(-log10(interval))) + } + else + { + axis.decimals = 0 + } + + if centeringEnabled + { + axis.centeredEntries.reserveCapacity(n) + axis.centeredEntries.removeAll() + + let offset = (axis.entries[1] - axis.entries[0]) / 2.0 + + for i in 0 ..< n + { + axis.centeredEntries.append(axis.entries[i] + offset) + } + } + + axis._axisMinimum = axis.entries[0] + axis._axisMaximum = axis.entries[n-1] + axis.axisRange = abs(axis._axisMaximum - axis._axisMinimum) + } + + open override func renderAxisLabels(context: CGContext) + { + guard let + yAxis = axis as? YAxis, + let chart = chart + else { return } + + if !yAxis.isEnabled || !yAxis.isDrawLabelsEnabled + { + return + } + + let labelFont = yAxis.labelFont + let labelTextColor = yAxis.labelTextColor + + let center = chart.centerOffsets + let factor = chart.factor + + let labelLineHeight = yAxis.labelFont.lineHeight + + let from = yAxis.isDrawBottomYLabelEntryEnabled ? 0 : 1 + let to = yAxis.isDrawTopYLabelEntryEnabled ? yAxis.entryCount : (yAxis.entryCount - 1) + + let alignment: NSTextAlignment = yAxis.labelAlignment + let xOffset: CGFloat = yAxis.labelXOffset + + for j in stride(from: from, to: to, by: 1) + { + let r = CGFloat(yAxis.entries[j] - yAxis._axisMinimum) * factor + + let p = center.moving(distance: r, atAngle: chart.rotationAngle) + + let label = yAxis.getFormattedLabel(j) + + ChartUtils.drawText( + context: context, + text: label, + point: CGPoint(x: p.x + xOffset, y: p.y - labelLineHeight), + align: alignment, + attributes: [ + NSAttributedString.Key.font: labelFont, + NSAttributedString.Key.foregroundColor: labelTextColor + ]) + } + } + + open override func renderLimitLines(context: CGContext) + { + guard + let yAxis = axis as? YAxis, + let chart = chart, + let data = chart.data + else { return } + + var limitLines = yAxis.limitLines + + if limitLines.count == 0 + { + return + } + + context.saveGState() + + let sliceangle = chart.sliceAngle + + // calculate the factor that is needed for transforming the value to pixels + let factor = chart.factor + + let center = chart.centerOffsets + + for i in 0 ..< limitLines.count + { + let l = limitLines[i] + + if !l.isEnabled + { + continue + } + + context.setStrokeColor(l.lineColor.cgColor) + context.setLineWidth(l.lineWidth) + if l.lineDashLengths != nil + { + context.setLineDash(phase: l.lineDashPhase, lengths: l.lineDashLengths!) + } + else + { + context.setLineDash(phase: 0.0, lengths: []) + } + + let r = CGFloat(l.limit - chart.chartYMin) * factor + + context.beginPath() + + for j in 0 ..< (data.maxEntryCountSet?.entryCount ?? 0) + { + let p = center.moving(distance: r, atAngle: sliceangle * CGFloat(j) + chart.rotationAngle) + + if j == 0 + { + context.move(to: CGPoint(x: p.x, y: p.y)) + } + else + { + context.addLine(to: CGPoint(x: p.x, y: p.y)) + } + } + + context.closePath() + + context.strokePath() + } + + context.restoreGState() + } +} diff --git a/Pods/Charts/Source/Charts/Utils/ChartColorTemplates.swift b/Pods/Charts/Source/Charts/Utils/ChartColorTemplates.swift new file mode 100644 index 00000000..534f9cb8 --- /dev/null +++ b/Pods/Charts/Source/Charts/Utils/ChartColorTemplates.swift @@ -0,0 +1,198 @@ +// +// ChartColorTemplates.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 ChartColorTemplates: NSObject +{ + @objc open class func liberty () -> [NSUIColor] + { + return [ + NSUIColor(red: 207/255.0, green: 248/255.0, blue: 246/255.0, alpha: 1.0), + NSUIColor(red: 148/255.0, green: 212/255.0, blue: 212/255.0, alpha: 1.0), + NSUIColor(red: 136/255.0, green: 180/255.0, blue: 187/255.0, alpha: 1.0), + NSUIColor(red: 118/255.0, green: 174/255.0, blue: 175/255.0, alpha: 1.0), + NSUIColor(red: 42/255.0, green: 109/255.0, blue: 130/255.0, alpha: 1.0) + ] + } + + @objc open class func joyful () -> [NSUIColor] + { + return [ + NSUIColor(red: 217/255.0, green: 80/255.0, blue: 138/255.0, alpha: 1.0), + NSUIColor(red: 254/255.0, green: 149/255.0, blue: 7/255.0, alpha: 1.0), + NSUIColor(red: 254/255.0, green: 247/255.0, blue: 120/255.0, alpha: 1.0), + NSUIColor(red: 106/255.0, green: 167/255.0, blue: 134/255.0, alpha: 1.0), + NSUIColor(red: 53/255.0, green: 194/255.0, blue: 209/255.0, alpha: 1.0) + ] + } + + @objc open class func pastel () -> [NSUIColor] + { + return [ + NSUIColor(red: 64/255.0, green: 89/255.0, blue: 128/255.0, alpha: 1.0), + NSUIColor(red: 149/255.0, green: 165/255.0, blue: 124/255.0, alpha: 1.0), + NSUIColor(red: 217/255.0, green: 184/255.0, blue: 162/255.0, alpha: 1.0), + NSUIColor(red: 191/255.0, green: 134/255.0, blue: 134/255.0, alpha: 1.0), + NSUIColor(red: 179/255.0, green: 48/255.0, blue: 80/255.0, alpha: 1.0) + ] + } + + @objc open class func colorful () -> [NSUIColor] + { + return [ + NSUIColor(red: 193/255.0, green: 37/255.0, blue: 82/255.0, alpha: 1.0), + NSUIColor(red: 255/255.0, green: 102/255.0, blue: 0/255.0, alpha: 1.0), + NSUIColor(red: 245/255.0, green: 199/255.0, blue: 0/255.0, alpha: 1.0), + NSUIColor(red: 106/255.0, green: 150/255.0, blue: 31/255.0, alpha: 1.0), + NSUIColor(red: 179/255.0, green: 100/255.0, blue: 53/255.0, alpha: 1.0) + ] + } + + @objc open class func vordiplom () -> [NSUIColor] + { + return [ + NSUIColor(red: 192/255.0, green: 255/255.0, blue: 140/255.0, alpha: 1.0), + NSUIColor(red: 255/255.0, green: 247/255.0, blue: 140/255.0, alpha: 1.0), + NSUIColor(red: 255/255.0, green: 208/255.0, blue: 140/255.0, alpha: 1.0), + NSUIColor(red: 140/255.0, green: 234/255.0, blue: 255/255.0, alpha: 1.0), + NSUIColor(red: 255/255.0, green: 140/255.0, blue: 157/255.0, alpha: 1.0) + ] + } + + @objc open class func material () -> [NSUIColor] + { + return [ + NSUIColor(red: 46/255.0, green: 204/255.0, blue: 113/255.0, alpha: 1.0), + NSUIColor(red: 241/255.0, green: 196/255.0, blue: 15/255.0, alpha: 1.0), + NSUIColor(red: 231/255.0, green: 76/255.0, blue: 60/255.0, alpha: 1.0), + NSUIColor(red: 52/255.0, green: 152/255.0, blue: 219/255.0, alpha: 1.0) + ] + } + + @objc open class func colorFromString(_ colorString: String) -> NSUIColor + { + let leftParenCharset: CharacterSet = CharacterSet(charactersIn: "( ") + let commaCharset: CharacterSet = CharacterSet(charactersIn: ", ") + + let colorString = colorString.lowercased() + + if colorString.hasPrefix("#") + { + var argb: [UInt] = [255, 0, 0, 0] + let colorString = colorString.unicodeScalars + var length = colorString.count + var index = colorString.startIndex + let endIndex = colorString.endIndex + + index = colorString.index(after: index) + length = length - 1 + + if length == 3 || length == 6 || length == 8 + { + var i = length == 8 ? 0 : 1 + while index < endIndex + { + var c = colorString[index] + index = colorString.index(after: index) + + var val = (c.value >= 0x61 && c.value <= 0x66) ? (c.value - 0x61 + 10) : c.value - 0x30 + argb[i] = UInt(val) * 16 + if length == 3 + { + argb[i] = argb[i] + UInt(val) + } + else + { + c = colorString[index] + index = colorString.index(after: index) + + val = (c.value >= 0x61 && c.value <= 0x66) ? (c.value - 0x61 + 10) : c.value - 0x30 + argb[i] = argb[i] + UInt(val) + } + + i += 1 + } + } + + return NSUIColor(red: CGFloat(argb[1]) / 255.0, green: CGFloat(argb[2]) / 255.0, blue: CGFloat(argb[3]) / 255.0, alpha: CGFloat(argb[0]) / 255.0) + } + else if colorString.hasPrefix("rgba") + { + var a: Float = 1.0 + var r: Int32 = 0 + var g: Int32 = 0 + var b: Int32 = 0 + let scanner: Scanner = Scanner(string: colorString) + scanner.scanString("rgba", into: nil) + scanner.scanCharacters(from: leftParenCharset, into: nil) + scanner.scanInt32(&r) + scanner.scanCharacters(from: commaCharset, into: nil) + scanner.scanInt32(&g) + scanner.scanCharacters(from: commaCharset, into: nil) + scanner.scanInt32(&b) + scanner.scanCharacters(from: commaCharset, into: nil) + scanner.scanFloat(&a) + return NSUIColor( + red: CGFloat(r) / 255.0, + green: CGFloat(g) / 255.0, + blue: CGFloat(b) / 255.0, + alpha: CGFloat(a) + ) + } + else if colorString.hasPrefix("argb") + { + var a: Float = 1.0 + var r: Int32 = 0 + var g: Int32 = 0 + var b: Int32 = 0 + let scanner: Scanner = Scanner(string: colorString) + scanner.scanString("argb", into: nil) + scanner.scanCharacters(from: leftParenCharset, into: nil) + scanner.scanFloat(&a) + scanner.scanCharacters(from: commaCharset, into: nil) + scanner.scanInt32(&r) + scanner.scanCharacters(from: commaCharset, into: nil) + scanner.scanInt32(&g) + scanner.scanCharacters(from: commaCharset, into: nil) + scanner.scanInt32(&b) + return NSUIColor( + red: CGFloat(r) / 255.0, + green: CGFloat(g) / 255.0, + blue: CGFloat(b) / 255.0, + alpha: CGFloat(a) + ) + } + else if colorString.hasPrefix("rgb") + { + var r: Int32 = 0 + var g: Int32 = 0 + var b: Int32 = 0 + let scanner: Scanner = Scanner(string: colorString) + scanner.scanString("rgb", into: nil) + scanner.scanCharacters(from: leftParenCharset, into: nil) + scanner.scanInt32(&r) + scanner.scanCharacters(from: commaCharset, into: nil) + scanner.scanInt32(&g) + scanner.scanCharacters(from: commaCharset, into: nil) + scanner.scanInt32(&b) + return NSUIColor( + red: CGFloat(r) / 255.0, + green: CGFloat(g) / 255.0, + blue: CGFloat(b) / 255.0, + alpha: 1.0 + ) + } + + return NSUIColor.clear + } +} diff --git a/Pods/Charts/Source/Charts/Utils/ChartUtils.swift b/Pods/Charts/Source/Charts/Utils/ChartUtils.swift new file mode 100644 index 00000000..25ccfde3 --- /dev/null +++ b/Pods/Charts/Source/Charts/Utils/ChartUtils.swift @@ -0,0 +1,296 @@ +// +// Utils.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 + +extension Comparable { + func clamped(to range: ClosedRange) -> Self { + if self > range.upperBound { + return range.upperBound + } else if self < range.lowerBound { + return range.lowerBound + } else { + return self + } + } +} + +extension FloatingPoint +{ + var DEG2RAD: Self + { + return self * .pi / 180 + } + + var RAD2DEG: Self + { + return self * 180 / .pi + } + + /// - Note: Value must be in degrees + /// - Returns: An angle between 0.0 < 360.0 (not less than zero, less than 360) + var normalizedAngle: Self + { + let angle = truncatingRemainder(dividingBy: 360) + return (sign == .minus) ? angle + 360 : angle + } +} + +extension CGSize +{ + func rotatedBy(degrees: CGFloat) -> CGSize + { + let radians = degrees.DEG2RAD + return rotatedBy(radians: radians) + } + + func rotatedBy(radians: CGFloat) -> CGSize + { + return CGSize( + width: abs(width * cos(radians)) + abs(height * sin(radians)), + height: abs(width * sin(radians)) + abs(height * cos(radians)) + ) + } +} + +extension Double +{ + /// Rounds the number to the nearest multiple of it's order of magnitude, rounding away from zero if halfway. + func roundedToNextSignficant() -> Double + { + guard + !isInfinite, + !isNaN, + self != 0 + else { return self } + + let d = ceil(log10(self < 0 ? -self : self)) + let pw = 1 - Int(d) + let magnitude = pow(10.0, Double(pw)) + let shifted = (self * magnitude).rounded() + return shifted / magnitude + } + + var decimalPlaces: Int + { + guard + !isNaN, + !isInfinite, + self != 0.0 + else { return 0 } + + let i = self.roundedToNextSignficant() + + guard + !i.isInfinite, + !i.isNaN + else { return 0 } + + return Int(ceil(-log10(i))) + 2 + } +} + +extension CGPoint +{ + /// Calculates the position around a center point, depending on the distance from the center, and the angle of the position around the center. + func moving(distance: CGFloat, atAngle angle: CGFloat) -> CGPoint + { + return CGPoint(x: x + distance * cos(angle.DEG2RAD), + y: y + distance * sin(angle.DEG2RAD)) + } +} + +open class ChartUtils +{ + private static var _defaultValueFormatter: IValueFormatter = ChartUtils.generateDefaultValueFormatter() + + open class func drawImage( + context: CGContext, + image: NSUIImage, + x: CGFloat, + y: CGFloat, + size: CGSize) + { + var drawOffset = CGPoint() + drawOffset.x = x - (size.width / 2) + drawOffset.y = y - (size.height / 2) + + NSUIGraphicsPushContext(context) + + if image.size.width != size.width && image.size.height != size.height + { + let key = "resized_\(size.width)_\(size.height)" + + // Try to take scaled image from cache of this image + var scaledImage = objc_getAssociatedObject(image, key) as? NSUIImage + if scaledImage == nil + { + // Scale the image + NSUIGraphicsBeginImageContextWithOptions(size, false, 0.0) + + image.draw(in: CGRect(origin: CGPoint(x: 0, y: 0), size: size)) + + scaledImage = NSUIGraphicsGetImageFromCurrentImageContext() + NSUIGraphicsEndImageContext() + + // Put the scaled image in a cache owned by the original image + objc_setAssociatedObject(image, key, scaledImage, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) + } + + scaledImage?.draw(in: CGRect(origin: drawOffset, size: size)) + } + else + { + image.draw(in: CGRect(origin: drawOffset, size: size)) + } + + NSUIGraphicsPopContext() + } + + open class func drawText(context: CGContext, text: String, point: CGPoint, align: NSTextAlignment, attributes: [NSAttributedString.Key : Any]?) + { + var point = point + + if align == .center + { + point.x -= text.size(withAttributes: attributes).width / 2.0 + } + else if align == .right + { + point.x -= text.size(withAttributes: attributes).width + } + + NSUIGraphicsPushContext(context) + + (text as NSString).draw(at: point, withAttributes: attributes) + + NSUIGraphicsPopContext() + } + + open class func drawText(context: CGContext, text: String, point: CGPoint, attributes: [NSAttributedString.Key : Any]?, anchor: CGPoint, angleRadians: CGFloat) + { + var drawOffset = CGPoint() + + NSUIGraphicsPushContext(context) + + if angleRadians != 0.0 + { + let size = text.size(withAttributes: attributes) + + // Move the text drawing rect in a way that it always rotates around its center + drawOffset.x = -size.width * 0.5 + drawOffset.y = -size.height * 0.5 + + var translate = point + + // Move the "outer" rect relative to the anchor, assuming its centered + if anchor.x != 0.5 || anchor.y != 0.5 + { + let rotatedSize = size.rotatedBy(radians: angleRadians) + + translate.x -= rotatedSize.width * (anchor.x - 0.5) + translate.y -= rotatedSize.height * (anchor.y - 0.5) + } + + context.saveGState() + context.translateBy(x: translate.x, y: translate.y) + context.rotate(by: angleRadians) + + (text as NSString).draw(at: drawOffset, withAttributes: attributes) + + context.restoreGState() + } + else + { + if anchor.x != 0.0 || anchor.y != 0.0 + { + let size = text.size(withAttributes: attributes) + + drawOffset.x = -size.width * anchor.x + drawOffset.y = -size.height * anchor.y + } + + drawOffset.x += point.x + drawOffset.y += point.y + + (text as NSString).draw(at: drawOffset, withAttributes: attributes) + } + + NSUIGraphicsPopContext() + } + + internal class func drawMultilineText(context: CGContext, text: String, knownTextSize: CGSize, point: CGPoint, attributes: [NSAttributedString.Key : Any]?, constrainedToSize: CGSize, anchor: CGPoint, angleRadians: CGFloat) + { + var rect = CGRect(origin: CGPoint(), size: knownTextSize) + + NSUIGraphicsPushContext(context) + + if angleRadians != 0.0 + { + // Move the text drawing rect in a way that it always rotates around its center + rect.origin.x = -knownTextSize.width * 0.5 + rect.origin.y = -knownTextSize.height * 0.5 + + var translate = point + + // Move the "outer" rect relative to the anchor, assuming its centered + if anchor.x != 0.5 || anchor.y != 0.5 + { + let rotatedSize = knownTextSize.rotatedBy(radians: angleRadians) + + translate.x -= rotatedSize.width * (anchor.x - 0.5) + translate.y -= rotatedSize.height * (anchor.y - 0.5) + } + + context.saveGState() + context.translateBy(x: translate.x, y: translate.y) + context.rotate(by: angleRadians) + + (text as NSString).draw(with: rect, options: .usesLineFragmentOrigin, attributes: attributes, context: nil) + + context.restoreGState() + } + else + { + if anchor.x != 0.0 || anchor.y != 0.0 + { + rect.origin.x = -knownTextSize.width * anchor.x + rect.origin.y = -knownTextSize.height * anchor.y + } + + rect.origin.x += point.x + rect.origin.y += point.y + + (text as NSString).draw(with: rect, options: .usesLineFragmentOrigin, attributes: attributes, context: nil) + } + + NSUIGraphicsPopContext() + } + + internal class func drawMultilineText(context: CGContext, text: String, point: CGPoint, attributes: [NSAttributedString.Key : Any]?, constrainedToSize: CGSize, anchor: CGPoint, angleRadians: CGFloat) + { + let rect = text.boundingRect(with: constrainedToSize, options: .usesLineFragmentOrigin, attributes: attributes, context: nil) + drawMultilineText(context: context, text: text, knownTextSize: rect.size, point: point, attributes: attributes, constrainedToSize: constrainedToSize, anchor: anchor, angleRadians: angleRadians) + } + + private class func generateDefaultValueFormatter() -> IValueFormatter + { + let formatter = DefaultValueFormatter(decimals: 1) + return formatter + } + + /// - Returns: The default value formatter used for all chart components that needs a default + open class func defaultValueFormatter() -> IValueFormatter + { + return _defaultValueFormatter + } +} diff --git a/Pods/Charts/Source/Charts/Utils/Fill.swift b/Pods/Charts/Source/Charts/Utils/Fill.swift new file mode 100644 index 00000000..1294b3ef --- /dev/null +++ b/Pods/Charts/Source/Charts/Utils/Fill.swift @@ -0,0 +1,323 @@ +// +// Fill.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(ChartFillType) +public enum FillType: Int +{ + case empty + case color + case linearGradient + case radialGradient + case image + case tiledImage + case layer +} + +@objc(ChartFill) +open class Fill: NSObject +{ + private var _type: FillType = FillType.empty + private var _color: CGColor? + private var _gradient: CGGradient? + private var _gradientAngle: CGFloat = 0.0 + private var _gradientStartOffsetPercent: CGPoint = CGPoint() + private var _gradientStartRadiusPercent: CGFloat = 0.0 + private var _gradientEndOffsetPercent: CGPoint = CGPoint() + private var _gradientEndRadiusPercent: CGFloat = 0.0 + private var _image: CGImage? + private var _layer: CGLayer? + + // MARK: Properties + + @objc open var type: FillType + { + return _type + } + + @objc open var color: CGColor? + { + return _color + } + + @objc open var gradient: CGGradient? + { + return _gradient + } + + @objc open var gradientAngle: CGFloat + { + return _gradientAngle + } + + @objc open var gradientStartOffsetPercent: CGPoint + { + return _gradientStartOffsetPercent + } + + @objc open var gradientStartRadiusPercent: CGFloat + { + return _gradientStartRadiusPercent + } + + @objc open var gradientEndOffsetPercent: CGPoint + { + return _gradientEndOffsetPercent + } + + @objc open var gradientEndRadiusPercent: CGFloat + { + return _gradientEndRadiusPercent + } + + @objc open var image: CGImage? + { + return _image + } + + @objc open var layer: CGLayer? + { + return _layer + } + + // MARK: Constructors + + public override init() + { + } + + @objc public init(CGColor: CGColor) + { + _type = .color + _color = CGColor + } + + @objc public convenience init(color: NSUIColor) + { + self.init(CGColor: color.cgColor) + } + + @objc public init(linearGradient: CGGradient, angle: CGFloat) + { + _type = .linearGradient + _gradient = linearGradient + _gradientAngle = angle + } + + @objc public init( + radialGradient: CGGradient, + startOffsetPercent: CGPoint, + startRadiusPercent: CGFloat, + endOffsetPercent: CGPoint, + endRadiusPercent: CGFloat + ) + { + _type = .radialGradient + _gradient = radialGradient + _gradientStartOffsetPercent = startOffsetPercent + _gradientStartRadiusPercent = startRadiusPercent + _gradientEndOffsetPercent = endOffsetPercent + _gradientEndRadiusPercent = endRadiusPercent + } + + @objc public convenience init(radialGradient: CGGradient) + { + self.init( + radialGradient: radialGradient, + startOffsetPercent: CGPoint(x: 0.0, y: 0.0), + startRadiusPercent: 0.0, + endOffsetPercent: CGPoint(x: 0.0, y: 0.0), + endRadiusPercent: 1.0 + ) + } + + @objc public init(CGImage: CGImage, tiled: Bool) + { + _type = tiled ? .tiledImage : .image + _image = CGImage + } + + @objc public convenience init(image: NSUIImage, tiled: Bool) + { + self.init(CGImage: image.cgImage!, tiled: tiled) + } + + @objc public convenience init(CGImage: CGImage) + { + self.init(CGImage: CGImage, tiled: false) + } + + @objc public convenience init(image: NSUIImage) + { + self.init(image: image, tiled: false) + } + + @objc public init(CGLayer: CGLayer) + { + _type = .layer + _layer = CGLayer + } + + // MARK: Constructors + + @objc open class func fillWithCGColor(_ CGColor: CGColor) -> Fill + { + return Fill(CGColor: CGColor) + } + + @objc open class func fillWithColor(_ color: NSUIColor) -> Fill + { + return Fill(color: color) + } + + @objc open class func fillWithLinearGradient( + _ linearGradient: CGGradient, + angle: CGFloat) -> Fill + { + return Fill(linearGradient: linearGradient, angle: angle) + } + + @objc open class func fillWithRadialGradient( + _ radialGradient: CGGradient, + startOffsetPercent: CGPoint, + startRadiusPercent: CGFloat, + endOffsetPercent: CGPoint, + endRadiusPercent: CGFloat + ) -> Fill + { + return Fill( + radialGradient: radialGradient, + startOffsetPercent: startOffsetPercent, + startRadiusPercent: startRadiusPercent, + endOffsetPercent: endOffsetPercent, + endRadiusPercent: endRadiusPercent + ) + } + + @objc open class func fillWithRadialGradient(_ radialGradient: CGGradient) -> Fill + { + return Fill(radialGradient: radialGradient) + } + + @objc open class func fillWithCGImage(_ CGImage: CGImage, tiled: Bool) -> Fill + { + return Fill(CGImage: CGImage, tiled: tiled) + } + + @objc open class func fillWithImage(_ image: NSUIImage, tiled: Bool) -> Fill + { + return Fill(image: image, tiled: tiled) + } + + @objc open class func fillWithCGImage(_ CGImage: CGImage) -> Fill + { + return Fill(CGImage: CGImage) + } + + @objc open class func fillWithImage(_ image: NSUIImage) -> Fill + { + return Fill(image: image) + } + + @objc open class func fillWithCGLayer(_ CGLayer: CGLayer) -> Fill + { + return Fill(CGLayer: CGLayer) + } + + // MARK: Drawing code + + /// Draws the provided path in filled mode with the provided area + @objc open func fillPath( + context: CGContext, + rect: CGRect) + { + let fillType = _type + if fillType == .empty + { + return + } + + context.saveGState() + + switch fillType + { + case .color: + + context.setFillColor(_color!) + context.fillPath() + + case .image: + + context.clip() + context.draw(_image!, in: rect) + + case .tiledImage: + + context.clip() + context.draw(_image!, in: rect, byTiling: true) + + case .layer: + + context.clip() + context.draw(_layer!, in: rect) + + case .linearGradient: + + let radians = (360.0 - _gradientAngle).DEG2RAD + let centerPoint = CGPoint(x: rect.midX, y: rect.midY) + let xAngleDelta = cos(radians) * rect.width / 2.0 + let yAngleDelta = sin(radians) * rect.height / 2.0 + let startPoint = CGPoint( + x: centerPoint.x - xAngleDelta, + y: centerPoint.y - yAngleDelta + ) + let endPoint = CGPoint( + x: centerPoint.x + xAngleDelta, + y: centerPoint.y + yAngleDelta + ) + + context.clip() + context.drawLinearGradient(_gradient!, + start: startPoint, + end: endPoint, + options: [.drawsAfterEndLocation, .drawsBeforeStartLocation] + ) + + case .radialGradient: + + let centerPoint = CGPoint(x: rect.midX, y: rect.midY) + let radius = max(rect.width, rect.height) / 2.0 + + context.clip() + context.drawRadialGradient(_gradient!, + startCenter: CGPoint( + x: centerPoint.x + rect.width * _gradientStartOffsetPercent.x, + y: centerPoint.y + rect.height * _gradientStartOffsetPercent.y + ), + startRadius: radius * _gradientStartRadiusPercent, + endCenter: CGPoint( + x: centerPoint.x + rect.width * _gradientEndOffsetPercent.x, + y: centerPoint.y + rect.height * _gradientEndOffsetPercent.y + ), + endRadius: radius * _gradientEndRadiusPercent, + options: [.drawsAfterEndLocation, .drawsBeforeStartLocation] + ) + + case .empty: + break + } + + context.restoreGState() + } + +} diff --git a/Pods/Charts/Source/Charts/Utils/Platform+Accessibility.swift b/Pods/Charts/Source/Charts/Utils/Platform+Accessibility.swift new file mode 100644 index 00000000..35f4ee31 --- /dev/null +++ b/Pods/Charts/Source/Charts/Utils/Platform+Accessibility.swift @@ -0,0 +1,197 @@ +import Foundation + +#if os(iOS) || os(tvOS) + +internal func accessibilityPostLayoutChangedNotification(withElement element: Any? = nil) +{ + UIAccessibility.post(notification: UIAccessibility.Notification.layoutChanged, argument: element) +} + +internal func accessibilityPostScreenChangedNotification(withElement element: Any? = nil) +{ + UIAccessibility.post(notification: UIAccessibility.Notification.screenChanged, argument: element) +} + +/// A simple abstraction over UIAccessibilityElement and NSAccessibilityElement. +open class NSUIAccessibilityElement: UIAccessibilityElement +{ + private weak var containerView: UIView? + + final var isHeader: Bool = false + { + didSet + { + accessibilityTraits = isHeader ? UIAccessibilityTraits.header : UIAccessibilityTraits.none + } + } + + final var isSelected: Bool = false + { + didSet + { + accessibilityTraits = isSelected ? UIAccessibilityTraits.selected : UIAccessibilityTraits.none + } + } + + override public init(accessibilityContainer container: Any) + { + // We can force unwrap since all chart views are subclasses of UIView + containerView = (container as! UIView) + super.init(accessibilityContainer: container) + } + + override open var accessibilityFrame: CGRect + { + get + { + return super.accessibilityFrame + } + + set + { + guard let containerView = containerView else { return } + super.accessibilityFrame = containerView.convert(newValue, to: UIScreen.main.coordinateSpace) + } + } +} + +extension NSUIView +{ + /// An array of accessibilityElements that is used to implement UIAccessibilityContainer internally. + /// Subclasses **MUST** override this with an array of such elements. + @objc open func accessibilityChildren() -> [Any]? + { + return nil + } + + public final override var isAccessibilityElement: Bool + { + get { return false } // Return false here, so we can make individual elements accessible + set { } + } + + open override func accessibilityElementCount() -> Int + { + return accessibilityChildren()?.count ?? 0 + } + + open override func accessibilityElement(at index: Int) -> Any? + { + return accessibilityChildren()?[index] + } + + open override func index(ofAccessibilityElement element: Any) -> Int + { + guard let axElement = element as? NSUIAccessibilityElement else { return NSNotFound } + return (accessibilityChildren() as? [NSUIAccessibilityElement])? + .firstIndex(of: axElement) ?? NSNotFound + } +} + +#endif + +#if os(OSX) + +internal func accessibilityPostLayoutChangedNotification(withElement element: Any? = nil) +{ + guard let validElement = element else { return } + NSAccessibility.post(element: validElement, notification: .layoutChanged) +} + +internal func accessibilityPostScreenChangedNotification(withElement element: Any? = nil) +{ + // Placeholder +} + +/// A simple abstraction over UIAccessibilityElement and NSAccessibilityElement. +open class NSUIAccessibilityElement: NSAccessibilityElement +{ + private weak var containerView: NSView? + + final var isHeader: Bool = false + { + didSet + { + setAccessibilityRole(isHeader ? .staticText : .none) + } + } + + final var isSelected: Bool = false + { + didSet + { + setAccessibilitySelected(isSelected) + } + } + + open var accessibilityLabel: String + { + get + { + return accessibilityLabel() ?? "" + } + + set + { + setAccessibilityLabel(newValue) + } + } + + open var accessibilityFrame: NSRect + { + get + { + return accessibilityFrame() + } + + set + { + guard let containerView = containerView else { return } + + let bounds = NSAccessibility.screenRect(fromView: containerView, rect: newValue) + + // This works, but won't auto update if the window is resized or moved. + // setAccessibilityFrame(bounds) + + // using FrameInParentSpace allows for automatic updating of frame when windows are moved and resized. + // However, there seems to be a bug right now where using it causes an offset in the frame. + // This is a slightly hacky workaround that calculates the offset and removes it from frame calculation. + setAccessibilityFrameInParentSpace(bounds) + let axFrame = accessibilityFrame() + let widthOffset = abs(axFrame.origin.x - bounds.origin.x) + let heightOffset = abs(axFrame.origin.y - bounds.origin.y) + let rect = NSRect(x: bounds.origin.x - widthOffset, + y: bounds.origin.y - heightOffset, + width: bounds.width, + height: bounds.height) + setAccessibilityFrameInParentSpace(rect) + } + } + + public init(accessibilityContainer container: Any) + { + // We can force unwrap since all chart views are subclasses of NSView + containerView = (container as! NSView) + + super.init() + + setAccessibilityParent(containerView) + setAccessibilityRole(.row) + } +} + +/// - Note: setAccessibilityRole(.list) is called at init. See Platform.swift. +extension NSUIView: NSAccessibilityGroup +{ + open override func accessibilityLabel() -> String? + { + return "Chart View" + } + + open override func accessibilityRows() -> [Any]? + { + return accessibilityChildren() + } +} + +#endif diff --git a/Pods/Charts/Source/Charts/Utils/Platform.swift b/Pods/Charts/Source/Charts/Utils/Platform.swift new file mode 100644 index 00000000..3c11b32a --- /dev/null +++ b/Pods/Charts/Source/Charts/Utils/Platform.swift @@ -0,0 +1,629 @@ +import Foundation + +/** This file provides a thin abstraction layer atop of UIKit (iOS, tvOS) and Cocoa (OS X). The two APIs are very much + alike, and for the chart library's usage of the APIs it is often sufficient to typealias one to the other. The NSUI* + types are aliased to either their UI* implementation (on iOS) or their NS* implementation (on OS X). */ +#if os(iOS) || os(tvOS) +import UIKit + +public typealias NSUIFont = UIFont +public typealias NSUIColor = UIColor +public typealias NSUIEvent = UIEvent +public typealias NSUITouch = UITouch +public typealias NSUIImage = UIImage +public typealias NSUIScrollView = UIScrollView +public typealias NSUIGestureRecognizer = UIGestureRecognizer +public typealias NSUIGestureRecognizerState = UIGestureRecognizer.State +public typealias NSUIGestureRecognizerDelegate = UIGestureRecognizerDelegate +public typealias NSUITapGestureRecognizer = UITapGestureRecognizer +public typealias NSUIPanGestureRecognizer = UIPanGestureRecognizer +#if !os(tvOS) +public typealias NSUIPinchGestureRecognizer = UIPinchGestureRecognizer +public typealias NSUIRotationGestureRecognizer = UIRotationGestureRecognizer +#endif +public typealias NSUIScreen = UIScreen + +public typealias NSUIDisplayLink = CADisplayLink + +extension NSUITapGestureRecognizer +{ + @objc final func nsuiNumberOfTouches() -> Int + { + return numberOfTouches + } + + @objc final var nsuiNumberOfTapsRequired: Int + { + get + { + return self.numberOfTapsRequired + } + set + { + self.numberOfTapsRequired = newValue + } + } +} + +extension NSUIPanGestureRecognizer +{ + @objc final func nsuiNumberOfTouches() -> Int + { + return numberOfTouches + } + + @objc final func nsuiLocationOfTouch(_ touch: Int, inView: UIView?) -> CGPoint + { + return super.location(ofTouch: touch, in: inView) + } +} + +#if !os(tvOS) +extension NSUIRotationGestureRecognizer +{ + @objc final var nsuiRotation: CGFloat + { + get { return rotation } + set { rotation = newValue } + } +} +#endif + +#if !os(tvOS) +extension NSUIPinchGestureRecognizer +{ + @objc final var nsuiScale: CGFloat + { + get + { + return scale + } + set + { + scale = newValue + } + } + + @objc final func nsuiLocationOfTouch(_ touch: Int, inView: UIView?) -> CGPoint + { + return super.location(ofTouch: touch, in: inView) + } +} +#endif + +open class NSUIView: UIView +{ + public final override func touchesBegan(_ touches: Set, with event: NSUIEvent?) + { + self.nsuiTouchesBegan(touches, withEvent: event) + } + + public final override func touchesMoved(_ touches: Set, with event: NSUIEvent?) + { + self.nsuiTouchesMoved(touches, withEvent: event) + } + + public final override func touchesEnded(_ touches: Set, with event: NSUIEvent?) + { + self.nsuiTouchesEnded(touches, withEvent: event) + } + + public final override func touchesCancelled(_ touches: Set, with event: NSUIEvent?) + { + self.nsuiTouchesCancelled(touches, withEvent: event) + } + + @objc open func nsuiTouchesBegan(_ touches: Set, withEvent event: NSUIEvent?) + { + super.touchesBegan(touches, with: event!) + } + + @objc open func nsuiTouchesMoved(_ touches: Set, withEvent event: NSUIEvent?) + { + super.touchesMoved(touches, with: event!) + } + + @objc open func nsuiTouchesEnded(_ touches: Set, withEvent event: NSUIEvent?) + { + super.touchesEnded(touches, with: event!) + } + + @objc open func nsuiTouchesCancelled(_ touches: Set?, withEvent event: NSUIEvent?) + { + super.touchesCancelled(touches!, with: event!) + } + + @objc var nsuiLayer: CALayer? + { + return self.layer + } +} + +extension UIView +{ + @objc final var nsuiGestureRecognizers: [NSUIGestureRecognizer]? + { + return self.gestureRecognizers + } +} + +extension UIScrollView +{ + @objc var nsuiIsScrollEnabled: Bool + { + get { return isScrollEnabled } + set { isScrollEnabled = newValue } + } +} + +extension UIScreen +{ + @objc final var nsuiScale: CGFloat + { + return self.scale + } +} + +func NSUIGraphicsGetCurrentContext() -> CGContext? +{ + return UIGraphicsGetCurrentContext() +} + +func NSUIGraphicsGetImageFromCurrentImageContext() -> NSUIImage! +{ + return UIGraphicsGetImageFromCurrentImageContext() +} + +func NSUIGraphicsPushContext(_ context: CGContext) +{ + UIGraphicsPushContext(context) +} + +func NSUIGraphicsPopContext() +{ + UIGraphicsPopContext() +} + +func NSUIGraphicsEndImageContext() +{ + UIGraphicsEndImageContext() +} + +func NSUIImagePNGRepresentation(_ image: NSUIImage) -> Data? +{ + return image.pngData() +} + +func NSUIImageJPEGRepresentation(_ image: NSUIImage, _ quality: CGFloat = 0.8) -> Data? +{ + return image.jpegData(compressionQuality: quality) +} + +func NSUIMainScreen() -> NSUIScreen? +{ + return NSUIScreen.main +} + +func NSUIGraphicsBeginImageContextWithOptions(_ size: CGSize, _ opaque: Bool, _ scale: CGFloat) +{ + UIGraphicsBeginImageContextWithOptions(size, opaque, scale) +} + +#endif + +#if os(OSX) +import Cocoa +import Quartz + +public typealias NSUIFont = NSFont +public typealias NSUIColor = NSColor +public typealias NSUIEvent = NSEvent +public typealias NSUITouch = NSTouch +public typealias NSUIImage = NSImage +public typealias NSUIScrollView = NSScrollView +public typealias NSUIGestureRecognizer = NSGestureRecognizer +public typealias NSUIGestureRecognizerState = NSGestureRecognizer.State +public typealias NSUIGestureRecognizerDelegate = NSGestureRecognizerDelegate +public typealias NSUITapGestureRecognizer = NSClickGestureRecognizer +public typealias NSUIPanGestureRecognizer = NSPanGestureRecognizer +public typealias NSUIPinchGestureRecognizer = NSMagnificationGestureRecognizer +public typealias NSUIRotationGestureRecognizer = NSRotationGestureRecognizer +public typealias NSUIScreen = NSScreen + +/** On OS X there is no CADisplayLink. Use a 60 fps timer to render the animations. */ +public class NSUIDisplayLink +{ + private var timer: Timer? + private var displayLink: CVDisplayLink? + private var _timestamp: CFTimeInterval = 0.0 + + private weak var _target: AnyObject? + private var _selector: Selector + + public var timestamp: CFTimeInterval + { + return _timestamp + } + + init(target: Any, selector: Selector) + { + _target = target as AnyObject + _selector = selector + + if CVDisplayLinkCreateWithActiveCGDisplays(&displayLink) == kCVReturnSuccess + { + + CVDisplayLinkSetOutputCallback(displayLink!, { (displayLink, inNow, inOutputTime, flagsIn, flagsOut, userData) -> CVReturn in + + let _self = unsafeBitCast(userData, to: NSUIDisplayLink.self) + + _self._timestamp = CFAbsoluteTimeGetCurrent() + _self._target?.performSelector(onMainThread: _self._selector, with: _self, waitUntilDone: false) + + return kCVReturnSuccess + }, Unmanaged.passUnretained(self).toOpaque()) + } + else + { + timer = Timer(timeInterval: 1.0 / 60.0, target: target, selector: selector, userInfo: nil, repeats: true) + } + } + + deinit + { + stop() + } + + open func add(to runloop: RunLoop, forMode mode: RunLoop.Mode) + { + if displayLink != nil + { + CVDisplayLinkStart(displayLink!) + } + else if timer != nil + { + runloop.add(timer!, forMode: mode) + } + } + + open func remove(from: RunLoop, forMode: RunLoop.Mode) + { + stop() + } + + private func stop() + { + if displayLink != nil + { + CVDisplayLinkStop(displayLink!) + } + if timer != nil + { + timer?.invalidate() + } + } +} + +/** The 'tap' gesture is mapped to clicks. */ +extension NSUITapGestureRecognizer +{ + final func nsuiNumberOfTouches() -> Int + { + return 1 + } + + final var nsuiNumberOfTapsRequired: Int + { + get + { + return self.numberOfClicksRequired + } + set + { + self.numberOfClicksRequired = newValue + } + } +} + +extension NSUIPanGestureRecognizer +{ + final func nsuiNumberOfTouches() -> Int + { + return 1 + } + + /// FIXME: Currently there are no more than 1 touch in OSX gestures, and not way to create custom touch gestures. + final func nsuiLocationOfTouch(_ touch: Int, inView: NSView?) -> NSPoint + { + return super.location(in: inView) + } +} + +extension NSUIRotationGestureRecognizer +{ + /// FIXME: Currently there are no velocities in OSX gestures, and not way to create custom touch gestures. + final var velocity: CGFloat + { + return 0.1 + } + + final var nsuiRotation: CGFloat + { + get { return -rotation } + set { rotation = -newValue } + } +} + +extension NSUIPinchGestureRecognizer +{ + final var nsuiScale: CGFloat + { + get + { + return magnification + 1.0 + } + set + { + magnification = newValue - 1.0 + } + } + + /// FIXME: Currently there are no more than 1 touch in OSX gestures, and not way to create custom touch gestures. + final func nsuiLocationOfTouch(_ touch: Int, inView view: NSView?) -> NSPoint + { + return super.location(in: view) + } +} + +extension NSView +{ + final var nsuiGestureRecognizers: [NSGestureRecognizer]? + { + return self.gestureRecognizers + } +} + +extension NSScrollView +{ + var nsuiIsScrollEnabled: Bool + { + get { return scrollEnabled } + set { scrollEnabled = newValue } + } +} + +open class NSUIView: NSView +{ + /// A private constant to set the accessibility role during initialization. + /// It ensures parity with the iOS element ordering as well as numbered counts of chart components. + /// (See Platform+Accessibility for details) + private let role: NSAccessibility.Role = .list + + public override init(frame frameRect: NSRect) + { + super.init(frame: frameRect) + setAccessibilityRole(role) + } + + required public init?(coder decoder: NSCoder) + { + super.init(coder: decoder) + setAccessibilityRole(role) + } + + public final override var isFlipped: Bool + { + return true + } + + func setNeedsDisplay() + { + self.setNeedsDisplay(self.bounds) + } + + public final override func touchesBegan(with event: NSEvent) + { + self.nsuiTouchesBegan(event.touches(matching: .any, in: self), withEvent: event) + } + + public final override func touchesEnded(with event: NSEvent) + { + self.nsuiTouchesEnded(event.touches(matching: .any, in: self), withEvent: event) + } + + public final override func touchesMoved(with event: NSEvent) + { + self.nsuiTouchesMoved(event.touches(matching: .any, in: self), withEvent: event) + } + + open override func touchesCancelled(with event: NSEvent) + { + self.nsuiTouchesCancelled(event.touches(matching: .any, in: self), withEvent: event) + } + + open func nsuiTouchesBegan(_ touches: Set, withEvent event: NSUIEvent?) + { + super.touchesBegan(with: event!) + } + + open func nsuiTouchesMoved(_ touches: Set, withEvent event: NSUIEvent?) + { + super.touchesMoved(with: event!) + } + + open func nsuiTouchesEnded(_ touches: Set, withEvent event: NSUIEvent?) + { + super.touchesEnded(with: event!) + } + + open func nsuiTouchesCancelled(_ touches: Set?, withEvent event: NSUIEvent?) + { + super.touchesCancelled(with: event!) + } + + open var backgroundColor: NSUIColor? + { + get + { + return self.layer?.backgroundColor == nil + ? nil + : NSColor(cgColor: self.layer!.backgroundColor!) + } + set + { + self.wantsLayer = true + self.layer?.backgroundColor = newValue == nil ? nil : newValue!.cgColor + } + } + + final var nsuiLayer: CALayer? + { + return self.layer + } +} + +extension NSFont +{ + var lineHeight: CGFloat + { + // Not sure if this is right, but it looks okay + return self.boundingRectForFont.size.height + } +} + +extension NSScreen +{ + final var nsuiScale: CGFloat + { + return self.backingScaleFactor + } +} + +extension NSImage +{ + var cgImage: CGImage? + { + return self.cgImage(forProposedRect: nil, context: nil, hints: nil) + } +} + +extension NSTouch +{ + /** Touch locations on OS X are relative to the trackpad, whereas on iOS they are actually *on* the view. */ + func locationInView(view: NSView) -> NSPoint + { + let n = self.normalizedPosition + let b = view.bounds + return NSPoint(x: b.origin.x + b.size.width * n.x, y: b.origin.y + b.size.height * n.y) + } +} + +extension NSScrollView +{ + var scrollEnabled: Bool + { + get + { + return true + } + set + { + // FIXME: We can't disable scrolling it on OSX + } + } +} + +func NSUIGraphicsGetCurrentContext() -> CGContext? +{ + return NSGraphicsContext.current?.cgContext +} + +func NSUIGraphicsPushContext(_ context: CGContext) +{ + let cx = NSGraphicsContext(cgContext: context, flipped: true) + NSGraphicsContext.saveGraphicsState() + NSGraphicsContext.current = cx +} + +func NSUIGraphicsPopContext() +{ + NSGraphicsContext.restoreGraphicsState() +} + +func NSUIImagePNGRepresentation(_ image: NSUIImage) -> Data? +{ + image.lockFocus() + let rep = NSBitmapImageRep(focusedViewRect: NSMakeRect(0, 0, image.size.width, image.size.height)) + image.unlockFocus() + return rep?.representation(using: .png, properties: [:]) +} + +func NSUIImageJPEGRepresentation(_ image: NSUIImage, _ quality: CGFloat = 0.9) -> Data? +{ + image.lockFocus() + let rep = NSBitmapImageRep(focusedViewRect: NSMakeRect(0, 0, image.size.width, image.size.height)) + image.unlockFocus() + return rep?.representation(using: .jpeg, properties: [NSBitmapImageRep.PropertyKey.compressionFactor: quality]) +} + +private var imageContextStack: [CGFloat] = [] + +func NSUIGraphicsBeginImageContextWithOptions(_ size: CGSize, _ opaque: Bool, _ scale: CGFloat) +{ + var scale = scale + if scale == 0.0 + { + scale = NSScreen.main?.backingScaleFactor ?? 1.0 + } + + let width = Int(size.width * scale) + let height = Int(size.height * scale) + + if width > 0 && height > 0 + { + imageContextStack.append(scale) + + let colorSpace = CGColorSpaceCreateDeviceRGB() + + guard let ctx = CGContext(data: nil, width: width, height: height, bitsPerComponent: 8, bytesPerRow: 4*width, space: colorSpace, bitmapInfo: (opaque ? CGImageAlphaInfo.noneSkipFirst.rawValue : CGImageAlphaInfo.premultipliedFirst.rawValue)) + else { return } + + ctx.concatenate(CGAffineTransform(a: 1, b: 0, c: 0, d: -1, tx: 0, ty: CGFloat(height))) + ctx.scaleBy(x: scale, y: scale) + NSUIGraphicsPushContext(ctx) + } +} + +func NSUIGraphicsGetImageFromCurrentImageContext() -> NSUIImage? +{ + if !imageContextStack.isEmpty + { + guard let ctx = NSUIGraphicsGetCurrentContext() + else { return nil } + + let scale = imageContextStack.last! + if let theCGImage = ctx.makeImage() + { + let size = CGSize(width: CGFloat(ctx.width) / scale, height: CGFloat(ctx.height) / scale) + let image = NSImage(cgImage: theCGImage, size: size) + return image + } + } + return nil +} + +func NSUIGraphicsEndImageContext() +{ + if imageContextStack.last != nil + { + imageContextStack.removeLast() + NSUIGraphicsPopContext() + } +} + +func NSUIMainScreen() -> NSUIScreen? +{ + return NSUIScreen.main +} + +#endif diff --git a/Pods/Charts/Source/Charts/Utils/Transformer.swift b/Pods/Charts/Source/Charts/Utils/Transformer.swift new file mode 100644 index 00000000..b50ea823 --- /dev/null +++ b/Pods/Charts/Source/Charts/Utils/Transformer.swift @@ -0,0 +1,170 @@ +// +// Transformer.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 + +/// Transformer class that contains all matrices and is responsible for transforming values into pixels on the screen and backwards. +@objc(ChartTransformer) +open class Transformer: NSObject +{ + /// matrix to map the values to the screen pixels + internal var _matrixValueToPx = CGAffineTransform.identity + + /// matrix for handling the different offsets of the chart + internal var _matrixOffset = CGAffineTransform.identity + + internal var _viewPortHandler: ViewPortHandler + + @objc public init(viewPortHandler: ViewPortHandler) + { + _viewPortHandler = viewPortHandler + } + + /// Prepares the matrix that transforms values to pixels. Calculates the scale factors from the charts size and offsets. + @objc open func prepareMatrixValuePx(chartXMin: Double, deltaX: CGFloat, deltaY: CGFloat, chartYMin: Double) + { + var scaleX = (_viewPortHandler.contentWidth / deltaX) + var scaleY = (_viewPortHandler.contentHeight / deltaY) + + if CGFloat.infinity == scaleX + { + scaleX = 0.0 + } + if CGFloat.infinity == scaleY + { + scaleY = 0.0 + } + + // setup all matrices + _matrixValueToPx = CGAffineTransform.identity + _matrixValueToPx = _matrixValueToPx.scaledBy(x: scaleX, y: -scaleY) + _matrixValueToPx = _matrixValueToPx.translatedBy(x: CGFloat(-chartXMin), y: CGFloat(-chartYMin)) + } + + /// Prepares the matrix that contains all offsets. + @objc open func prepareMatrixOffset(inverted: Bool) + { + if !inverted + { + _matrixOffset = CGAffineTransform(translationX: _viewPortHandler.offsetLeft, y: _viewPortHandler.chartHeight - _viewPortHandler.offsetBottom) + } + else + { + _matrixOffset = CGAffineTransform(scaleX: 1.0, y: -1.0) + _matrixOffset = _matrixOffset.translatedBy(x: _viewPortHandler.offsetLeft, y: -_viewPortHandler.offsetTop) + } + } + + /// Transform an array of points with all matrices. + // VERY IMPORTANT: Keep matrix order "value-touch-offset" when transforming. + open func pointValuesToPixel(_ points: inout [CGPoint]) + { + let trans = valueToPixelMatrix + points = points.map { $0.applying(trans) } + } + + open func pointValueToPixel(_ point: inout CGPoint) + { + point = point.applying(valueToPixelMatrix) + } + + @objc open func pixelForValues(x: Double, y: Double) -> CGPoint + { + return CGPoint(x: x, y: y).applying(valueToPixelMatrix) + } + + /// Transform a rectangle with all matrices. + open func rectValueToPixel(_ r: inout CGRect) + { + r = r.applying(valueToPixelMatrix) + } + + /// Transform a rectangle with all matrices with potential animation phases. + open func rectValueToPixel(_ r: inout CGRect, phaseY: Double) + { + // multiply the height of the rect with the phase + var bottom = r.origin.y + r.size.height + bottom *= CGFloat(phaseY) + let top = r.origin.y * CGFloat(phaseY) + r.size.height = bottom - top + r.origin.y = top + + r = r.applying(valueToPixelMatrix) + } + + /// Transform a rectangle with all matrices. + open func rectValueToPixelHorizontal(_ r: inout CGRect) + { + r = r.applying(valueToPixelMatrix) + } + + /// Transform a rectangle with all matrices with potential animation phases. + open func rectValueToPixelHorizontal(_ r: inout CGRect, phaseY: Double) + { + // multiply the height of the rect with the phase + let left = r.origin.x * CGFloat(phaseY) + let right = (r.origin.x + r.size.width) * CGFloat(phaseY) + r.size.width = right - left + r.origin.x = left + + r = r.applying(valueToPixelMatrix) + } + + /// transforms multiple rects with all matrices + open func rectValuesToPixel(_ rects: inout [CGRect]) + { + let trans = valueToPixelMatrix + rects = rects.map { $0.applying(trans) } + } + + /// Transforms the given array of touch points (pixels) into values on the chart. + open func pixelsToValues(_ pixels: inout [CGPoint]) + { + let trans = pixelToValueMatrix + pixels = pixels.map { $0.applying(trans) } + } + + /// Transforms the given touch point (pixels) into a value on the chart. + open func pixelToValues(_ pixel: inout CGPoint) + { + pixel = pixel.applying(pixelToValueMatrix) + } + + /// - Returns: The x and y values in the chart at the given touch point + /// (encapsulated in a CGPoint). This method transforms pixel coordinates to + /// coordinates / values in the chart. + @objc open func valueForTouchPoint(_ point: CGPoint) -> CGPoint + { + return point.applying(pixelToValueMatrix) + } + + /// - Returns: The x and y values in the chart at the given touch point + /// (x/y). This method transforms pixel coordinates to + /// coordinates / values in the chart. + @objc open func valueForTouchPoint(x: CGFloat, y: CGFloat) -> CGPoint + { + return CGPoint(x: x, y: y).applying(pixelToValueMatrix) + } + + @objc open var valueToPixelMatrix: CGAffineTransform + { + return + _matrixValueToPx.concatenating(_viewPortHandler.touchMatrix + ).concatenating(_matrixOffset + ) + } + + @objc open var pixelToValueMatrix: CGAffineTransform + { + return valueToPixelMatrix.inverted() + } +} diff --git a/Pods/Charts/Source/Charts/Utils/TransformerHorizontalBarChart.swift b/Pods/Charts/Source/Charts/Utils/TransformerHorizontalBarChart.swift new file mode 100644 index 00000000..d7e657bd --- /dev/null +++ b/Pods/Charts/Source/Charts/Utils/TransformerHorizontalBarChart.swift @@ -0,0 +1,32 @@ +// +// TransformerHorizontalBarChart.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(ChartTransformerHorizontalBarChart) +open class TransformerHorizontalBarChart: Transformer +{ + /// Prepares the matrix that contains all offsets. + open override func prepareMatrixOffset(inverted: Bool) + { + if !inverted + { + _matrixOffset = CGAffineTransform(translationX: _viewPortHandler.offsetLeft, y: _viewPortHandler.chartHeight - _viewPortHandler.offsetBottom) + } + else + { + _matrixOffset = CGAffineTransform(scaleX: -1.0, y: 1.0) + _matrixOffset = _matrixOffset.translatedBy(x: -(_viewPortHandler.chartWidth - _viewPortHandler.offsetRight), + y: _viewPortHandler.chartHeight - _viewPortHandler.offsetBottom) + } + } +} diff --git a/Pods/Charts/Source/Charts/Utils/ViewPortHandler.swift b/Pods/Charts/Source/Charts/Utils/ViewPortHandler.swift new file mode 100755 index 00000000..56e034b4 --- /dev/null +++ b/Pods/Charts/Source/Charts/Utils/ViewPortHandler.swift @@ -0,0 +1,553 @@ +// +// ViewPortHandler.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 + +/// Class that contains information about the charts current viewport settings, including offsets, scale & translation levels, ... +@objc(ChartViewPortHandler) +open class ViewPortHandler: NSObject +{ + /// matrix used for touch events + private var _touchMatrix = CGAffineTransform.identity + + /// this rectangle defines the area in which graph values can be drawn + private var _contentRect = CGRect() + + private var _chartWidth = CGFloat(0.0) + private var _chartHeight = CGFloat(0.0) + + /// minimum scale value on the y-axis + private var _minScaleY = CGFloat(1.0) + + /// maximum scale value on the y-axis + private var _maxScaleY = CGFloat.greatestFiniteMagnitude + + /// minimum scale value on the x-axis + private var _minScaleX = CGFloat(1.0) + + /// maximum scale value on the x-axis + private var _maxScaleX = CGFloat.greatestFiniteMagnitude + + /// contains the current scale factor of the x-axis + private var _scaleX = CGFloat(1.0) + + /// contains the current scale factor of the y-axis + private var _scaleY = CGFloat(1.0) + + /// current translation (drag distance) on the x-axis + private var _transX = CGFloat(0.0) + + /// current translation (drag distance) on the y-axis + private var _transY = CGFloat(0.0) + + /// offset that allows the chart to be dragged over its bounds on the x-axis + private var _transOffsetX = CGFloat(0.0) + + /// offset that allows the chart to be dragged over its bounds on the x-axis + private var _transOffsetY = CGFloat(0.0) + + /// Constructor - don't forget calling setChartDimens(...) + @objc public init(width: CGFloat, height: CGFloat) + { + super.init() + + setChartDimens(width: width, height: height) + } + + @objc open func setChartDimens(width: CGFloat, height: CGFloat) + { + let offsetLeft = self.offsetLeft + let offsetTop = self.offsetTop + let offsetRight = self.offsetRight + let offsetBottom = self.offsetBottom + + _chartHeight = height + _chartWidth = width + + restrainViewPort(offsetLeft: offsetLeft, offsetTop: offsetTop, offsetRight: offsetRight, offsetBottom: offsetBottom) + } + + @objc open var hasChartDimens: Bool + { + if _chartHeight > 0.0 && _chartWidth > 0.0 + { + return true + } + else + { + return false + } + } + + @objc open func restrainViewPort(offsetLeft: CGFloat, offsetTop: CGFloat, offsetRight: CGFloat, offsetBottom: CGFloat) + { + _contentRect.origin.x = offsetLeft + _contentRect.origin.y = offsetTop + _contentRect.size.width = _chartWidth - offsetLeft - offsetRight + _contentRect.size.height = _chartHeight - offsetBottom - offsetTop + } + + @objc open var offsetLeft: CGFloat + { + return _contentRect.origin.x + } + + @objc open var offsetRight: CGFloat + { + return _chartWidth - _contentRect.size.width - _contentRect.origin.x + } + + @objc open var offsetTop: CGFloat + { + return _contentRect.origin.y + } + + @objc open var offsetBottom: CGFloat + { + return _chartHeight - _contentRect.size.height - _contentRect.origin.y + } + + @objc open var contentTop: CGFloat + { + return _contentRect.origin.y + } + + @objc open var contentLeft: CGFloat + { + return _contentRect.origin.x + } + + @objc open var contentRight: CGFloat + { + return _contentRect.origin.x + _contentRect.size.width + } + + @objc open var contentBottom: CGFloat + { + return _contentRect.origin.y + _contentRect.size.height + } + + @objc open var contentWidth: CGFloat + { + return _contentRect.size.width + } + + @objc open var contentHeight: CGFloat + { + return _contentRect.size.height + } + + @objc open var contentRect: CGRect + { + return _contentRect + } + + @objc open var contentCenter: CGPoint + { + return CGPoint(x: _contentRect.origin.x + _contentRect.size.width / 2.0, y: _contentRect.origin.y + _contentRect.size.height / 2.0) + } + + @objc open var chartHeight: CGFloat + { + return _chartHeight + } + + @objc open var chartWidth: CGFloat + { + return _chartWidth + } + + // MARK: - Scaling/Panning etc. + + /// Zooms by the specified zoom factors. + @objc open func zoom(scaleX: CGFloat, scaleY: CGFloat) -> CGAffineTransform + { + return _touchMatrix.scaledBy(x: scaleX, y: scaleY) + } + + /// Zooms around the specified center + @objc open func zoom(scaleX: CGFloat, scaleY: CGFloat, x: CGFloat, y: CGFloat) -> CGAffineTransform + { + var matrix = _touchMatrix.translatedBy(x: x, y: y) + matrix = matrix.scaledBy(x: scaleX, y: scaleY) + matrix = matrix.translatedBy(x: -x, y: -y) + return matrix + } + + /// Zooms in by 1.4, x and y are the coordinates (in pixels) of the zoom center. + @objc open func zoomIn(x: CGFloat, y: CGFloat) -> CGAffineTransform + { + return zoom(scaleX: 1.4, scaleY: 1.4, x: x, y: y) + } + + /// Zooms out by 0.7, x and y are the coordinates (in pixels) of the zoom center. + @objc open func zoomOut(x: CGFloat, y: CGFloat) -> CGAffineTransform + { + return zoom(scaleX: 0.7, scaleY: 0.7, x: x, y: y) + } + + /// Zooms out to original size. + @objc open func resetZoom() -> CGAffineTransform + { + return zoom(scaleX: 1.0, scaleY: 1.0, x: 0.0, y: 0.0) + } + + /// Sets the scale factor to the specified values. + @objc open func setZoom(scaleX: CGFloat, scaleY: CGFloat) -> CGAffineTransform + { + var matrix = _touchMatrix + matrix.a = scaleX + matrix.d = scaleY + return matrix + } + + /// Sets the scale factor to the specified values. x and y is pivot. + @objc open func setZoom(scaleX: CGFloat, scaleY: CGFloat, x: CGFloat, y: CGFloat) -> CGAffineTransform + { + var matrix = _touchMatrix + matrix.a = 1.0 + matrix.d = 1.0 + matrix = matrix.translatedBy(x: x, y: y) + matrix = matrix.scaledBy(x: scaleX, y: scaleY) + matrix = matrix.translatedBy(x: -x, y: -y) + return matrix + } + + /// Resets all zooming and dragging and makes the chart fit exactly it's bounds. + @objc open func fitScreen() -> CGAffineTransform + { + _minScaleX = 1.0 + _minScaleY = 1.0 + + return CGAffineTransform.identity + } + + /// Translates to the specified point. + @objc open func translate(pt: CGPoint) -> CGAffineTransform + { + let translateX = pt.x - offsetLeft + let translateY = pt.y - offsetTop + + let matrix = _touchMatrix.concatenating(CGAffineTransform(translationX: -translateX, y: -translateY)) + + return matrix + } + + /// Centers the viewport around the specified position (x-index and y-value) in the chart. + /// Centering the viewport outside the bounds of the chart is not possible. + /// Makes most sense in combination with the setScaleMinima(...) method. + @objc open func centerViewPort(pt: CGPoint, chart: ChartViewBase) + { + let translateX = pt.x - offsetLeft + let translateY = pt.y - offsetTop + + let matrix = _touchMatrix.concatenating(CGAffineTransform(translationX: -translateX, y: -translateY)) + refresh(newMatrix: matrix, chart: chart, invalidate: true) + } + + /// call this method to refresh the graph with a given matrix + @objc @discardableResult open func refresh(newMatrix: CGAffineTransform, chart: ChartViewBase, invalidate: Bool) -> CGAffineTransform + { + _touchMatrix = newMatrix + + // make sure scale and translation are within their bounds + limitTransAndScale(matrix: &_touchMatrix, content: _contentRect) + + chart.setNeedsDisplay() + + return _touchMatrix + } + + /// limits the maximum scale and X translation of the given matrix + private func limitTransAndScale(matrix: inout CGAffineTransform, content: CGRect?) + { + // min scale-x is 1 + _scaleX = min(max(_minScaleX, matrix.a), _maxScaleX) + + // min scale-y is 1 + _scaleY = min(max(_minScaleY, matrix.d), _maxScaleY) + + + var width: CGFloat = 0.0 + var height: CGFloat = 0.0 + + if content != nil + { + width = content!.width + height = content!.height + } + + let maxTransX = -width * (_scaleX - 1.0) + _transX = min(max(matrix.tx, maxTransX - _transOffsetX), _transOffsetX) + + let maxTransY = height * (_scaleY - 1.0) + _transY = max(min(matrix.ty, maxTransY + _transOffsetY), -_transOffsetY) + + matrix.tx = _transX + matrix.a = _scaleX + matrix.ty = _transY + matrix.d = _scaleY + } + + /// Sets the minimum scale factor for the x-axis + @objc open func setMinimumScaleX(_ xScale: CGFloat) + { + var newValue = xScale + + if newValue < 1.0 + { + newValue = 1.0 + } + + _minScaleX = newValue + + limitTransAndScale(matrix: &_touchMatrix, content: _contentRect) + } + + /// Sets the maximum scale factor for the x-axis + @objc open func setMaximumScaleX(_ xScale: CGFloat) + { + var newValue = xScale + + if newValue == 0.0 + { + newValue = CGFloat.greatestFiniteMagnitude + } + + _maxScaleX = newValue + + limitTransAndScale(matrix: &_touchMatrix, content: _contentRect) + } + + /// Sets the minimum and maximum scale factors for the x-axis + @objc open func setMinMaxScaleX(minScaleX: CGFloat, maxScaleX: CGFloat) + { + var newMin = minScaleX + var newMax = maxScaleX + + if newMin < 1.0 + { + newMin = 1.0 + } + if newMax == 0.0 + { + newMax = CGFloat.greatestFiniteMagnitude + } + + _minScaleX = newMin + _maxScaleX = maxScaleX + + limitTransAndScale(matrix: &_touchMatrix, content: _contentRect) + } + + /// Sets the minimum scale factor for the y-axis + @objc open func setMinimumScaleY(_ yScale: CGFloat) + { + var newValue = yScale + + if newValue < 1.0 + { + newValue = 1.0 + } + + _minScaleY = newValue + + limitTransAndScale(matrix: &_touchMatrix, content: _contentRect) + } + + /// Sets the maximum scale factor for the y-axis + @objc open func setMaximumScaleY(_ yScale: CGFloat) + { + var newValue = yScale + + if newValue == 0.0 + { + newValue = CGFloat.greatestFiniteMagnitude + } + + _maxScaleY = newValue + + limitTransAndScale(matrix: &_touchMatrix, content: _contentRect) + } + + @objc open func setMinMaxScaleY(minScaleY: CGFloat, maxScaleY: CGFloat) + { + var minScaleY = minScaleY, maxScaleY = maxScaleY + + if minScaleY < 1.0 + { + minScaleY = 1.0 + } + + if maxScaleY == 0.0 + { + maxScaleY = CGFloat.greatestFiniteMagnitude + } + + _minScaleY = minScaleY + _maxScaleY = maxScaleY + + limitTransAndScale(matrix: &_touchMatrix, content: _contentRect) + } + + @objc open var touchMatrix: CGAffineTransform + { + return _touchMatrix + } + + // MARK: - Boundaries Check + + @objc open func isInBoundsX(_ x: CGFloat) -> Bool + { + return isInBoundsLeft(x) && isInBoundsRight(x) + } + + @objc open func isInBoundsY(_ y: CGFloat) -> Bool + { + return isInBoundsTop(y) && isInBoundsBottom(y) + } + + @objc open func isInBounds(x: CGFloat, y: CGFloat) -> Bool + { + return isInBoundsX(x) && isInBoundsY(y) + } + + @objc open func isInBoundsLeft(_ x: CGFloat) -> Bool + { + return _contentRect.origin.x <= x + 1.0 + } + + @objc open func isInBoundsRight(_ x: CGFloat) -> Bool + { + let x = floor(x * 100.0) / 100.0 + return (_contentRect.origin.x + _contentRect.size.width) >= x - 1.0 + } + + @objc open func isInBoundsTop(_ y: CGFloat) -> Bool + { + return _contentRect.origin.y <= y + } + + @objc open func isInBoundsBottom(_ y: CGFloat) -> Bool + { + let normalizedY = floor(y * 100.0) / 100.0 + return (_contentRect.origin.y + _contentRect.size.height) >= normalizedY + } + + /// The current x-scale factor + @objc open var scaleX: CGFloat + { + return _scaleX + } + + /// The current y-scale factor + @objc open var scaleY: CGFloat + { + return _scaleY + } + + /// The minimum x-scale factor + @objc open var minScaleX: CGFloat + { + return _minScaleX + } + + /// The minimum y-scale factor + @objc open var minScaleY: CGFloat + { + return _minScaleY + } + + /// The minimum x-scale factor + @objc open var maxScaleX: CGFloat + { + return _maxScaleX + } + + /// The minimum y-scale factor + @objc open var maxScaleY: CGFloat + { + return _maxScaleY + } + + /// The translation (drag / pan) distance on the x-axis + @objc open var transX: CGFloat + { + return _transX + } + + /// The translation (drag / pan) distance on the y-axis + @objc open var transY: CGFloat + { + return _transY + } + + /// if the chart is fully zoomed out, return true + @objc open var isFullyZoomedOut: Bool + { + return isFullyZoomedOutX && isFullyZoomedOutY + } + + /// `true` if the chart is fully zoomed out on it's y-axis (vertical). + @objc open var isFullyZoomedOutY: Bool + { + return !(_scaleY > _minScaleY || _minScaleY > 1.0) + } + + /// `true` if the chart is fully zoomed out on it's x-axis (horizontal). + @objc open var isFullyZoomedOutX: Bool + { + return !(_scaleX > _minScaleX || _minScaleX > 1.0) + } + + /// Set an offset in pixels that allows the user to drag the chart over it's bounds on the x-axis. + @objc open func setDragOffsetX(_ offset: CGFloat) + { + _transOffsetX = offset + } + + /// Set an offset in pixels that allows the user to drag the chart over it's bounds on the y-axis. + @objc open func setDragOffsetY(_ offset: CGFloat) + { + _transOffsetY = offset + } + + /// `true` if both drag offsets (x and y) are zero or smaller. + @objc open var hasNoDragOffset: Bool + { + return _transOffsetX <= 0.0 && _transOffsetY <= 0.0 + } + + /// `true` if the chart is not yet fully zoomed out on the x-axis + @objc open var canZoomOutMoreX: Bool + { + return _scaleX > _minScaleX + } + + /// `true` if the chart is not yet fully zoomed in on the x-axis + @objc open var canZoomInMoreX: Bool + { + return _scaleX < _maxScaleX + } + + /// `true` if the chart is not yet fully zoomed out on the y-axis + @objc open var canZoomOutMoreY: Bool + { + return _scaleY > _minScaleY + } + + /// `true` if the chart is not yet fully zoomed in on the y-axis + @objc open var canZoomInMoreY: Bool + { + return _scaleY < _maxScaleY + } +} diff --git a/Pods/Eddystone/LICENSE b/Pods/Eddystone/LICENSE new file mode 100644 index 00000000..87a1b18c --- /dev/null +++ b/Pods/Eddystone/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2015 Tanner Nelson + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/Pods/Eddystone/Pod/Classes/Beacon.swift b/Pods/Eddystone/Pod/Classes/Beacon.swift new file mode 100644 index 00000000..cc4d4803 --- /dev/null +++ b/Pods/Eddystone/Pod/Classes/Beacon.swift @@ -0,0 +1,206 @@ +import CoreBluetooth + +open class Beacon { + + //MARK: Enumerations + public enum SignalStrength: Int { + case excellent + case veryGood + case good + case low + case veryLow + case noSignal + case unknown + } + + //MARK: Frames + var frames: ( + url: UrlFrame?, + uid: UidFrame?, + tlm: TlmFrame? + ) = (nil,nil,nil) + + //MARK: Properties + var txPower: Int + var identifier: String + var rssi: Double { + get { + var totalRssi: Double = 0 + for rssi in self.rssiBuffer { + totalRssi += rssi + } + + let average: Double = totalRssi / Double(self.rssiBuffer.count) + return average + } + } + var signalStrength: SignalStrength = .unknown + var rssiBuffer = [Double]() + var distance: Double { + get { + return Beacon.calculateAccuracy(txPower: self.txPower, rssi: self.rssi) + } + } + + //MARK: Initializations + init(rssi: Double, txPower: Int, identifier: String) { + self.txPower = txPower + self.identifier = identifier + + self.updateRssi(rssi) + } + + //MARK: Delegate + var delegate: BeaconDelegate? + func notifyChange() { + self.delegate?.beaconDidChange() + } + + //MARK: Functions + func updateRssi(_ newRssi: Double) -> Bool { + self.rssiBuffer.insert(newRssi, at: 0) + if self.rssiBuffer.count >= 20 { + self.rssiBuffer.removeLast() + } + + let signalStrength = Beacon.calculateSignalStrength(self.distance) + if signalStrength != self.signalStrength { + self.signalStrength = signalStrength + self.notifyChange() + } + + return false + } + + //MARK: Calculations + class func calculateAccuracy(txPower: Int, rssi: Double) -> Double { + if rssi == 0 { + return 0 + } + + let ratio: Double = rssi / Double(txPower) + if ratio < 1 { + return pow(ratio, 10) + } else { + return 0.89976 * pow(ratio, 7.7095) + 0.111 + } + + } + + class func calculateSignalStrength(_ distance: Double) -> SignalStrength { + switch distance { + case 0...24999: + return .excellent + case 25000...49999: + return .veryGood + case 50000...74999: + return .good + case 75000...99999: + return .low + default: + return .veryLow + } + } + + //MARK: Advertisement Data + func parseAdvertisementData(_ advertisementData: [AnyHashable: Any], rssi: Double) { + self.updateRssi(rssi) + + if let bytes = Beacon.bytesFromAdvertisementData(advertisementData) { + if let type = Beacon.frameTypeFromBytes(bytes) { + switch type { + case .url: + if let frame = UrlFrame.frameWithBytes(bytes) { + if frame.url != self.frames.url?.url { + self.frames.url = frame + log("Parsed URL Frame with url: \(frame.url)") + self.notifyChange() + } + } + case .uid: + if let frame = UidFrame.frameWithBytes(bytes) { + if frame.uid != self.frames.uid?.uid { + self.frames.uid = frame + log("Parsed UID Frame with uid: \(frame.uid)") + self.notifyChange() + } + } + case .tlm: + if let frame = TlmFrame.frameWithBytes(bytes) { + self.frames.tlm = frame + log("Parsed TLM Frame with battery: \(frame.batteryVolts) temperature: \(frame.temperature) advertisement count: \(frame.advertisementCount) on time: \(frame.onTime)") + self.notifyChange() + } + } + } + } + } + + //MARK: Bytes + class func beaconWithAdvertisementData(_ advertisementData: [AnyHashable: Any], rssi: Double, identifier: String) -> Beacon? { + var txPower: Int? + var type: FrameType? + + if let bytes = Beacon.bytesFromAdvertisementData(advertisementData) { + type = Beacon.frameTypeFromBytes(bytes) + txPower = Beacon.txPowerFromBytes(bytes) + + if let txPower = txPower, type != nil { + let beacon = Beacon(rssi: rssi, txPower: txPower, identifier: identifier) + beacon.parseAdvertisementData(advertisementData, rssi: rssi) + return beacon + } + + } + + return nil + } + + class func bytesFromAdvertisementData(_ advertisementData: [AnyHashable: Any]) -> [Byte]? { + if let serviceData = advertisementData[CBAdvertisementDataServiceDataKey] as? [AnyHashable: Any] { + if let urlData = serviceData[Scanner.eddystoneServiceUUID] as? Data { + let count = urlData.count / MemoryLayout.size + var bytes = [UInt8](repeating: 0, count: count) + (urlData as NSData).getBytes(&bytes, length:count * MemoryLayout.size) + return bytes.map { byte in + return Byte(byte) + } + } + } + + return nil + } + + class func frameTypeFromBytes(_ bytes: [Byte]) -> FrameType? { + if bytes.count >= 1 { + switch bytes[0] { + case 0: + return .uid + case 16: + return .url + case 32: + return .tlm + default: + break + } + } + + return nil + } + + class func txPowerFromBytes(_ bytes: [Byte]) -> Int? { + if bytes.count >= 2 { + if let type = Beacon.frameTypeFromBytes(bytes) { + if type == .uid || type == .url { + return Int(Int8(bitPattern: UInt8(bytes[1]))) + } + } + } + + return nil + } +} + +protocol BeaconDelegate { + func beaconDidChange() +} diff --git a/Pods/Eddystone/Pod/Classes/CoreBluetoothExtensions.swift b/Pods/Eddystone/Pod/Classes/CoreBluetoothExtensions.swift new file mode 100755 index 00000000..f8973718 --- /dev/null +++ b/Pods/Eddystone/Pod/Classes/CoreBluetoothExtensions.swift @@ -0,0 +1,53 @@ +/** + CoreBluetoothExtensions.swift + + Easily identify which state a CBCentralManager or CBPeripheralManager is in + + +*/ + +import CoreBluetooth + +extension CBCentralManager { + var stateString: String { + get { + switch (self.state) { + case .poweredOn: + return "Powered On" + case .poweredOff: + return "Powered Off" + case .resetting: + return "Resetting" + case .unauthorized: + return "Unauthorized" + case .unknown: + return "Unknown" + case .unsupported: + return "Unsupported" + } + + } + } +} + +extension CBPeripheralManager { + var stateString: String { + get { + switch (self.state) { + case .poweredOn: + return "Powered On" + case .poweredOff: + return "Powered Off" + case .resetting: + return "Resetting" + case .unauthorized: + return "Unauthorized" + case .unknown: + return "Unknown" + case .unsupported: + return "Unsupported" + } + + } + } +} diff --git a/Pods/Eddystone/Pod/Classes/DoubleExtensions.swift b/Pods/Eddystone/Pod/Classes/DoubleExtensions.swift new file mode 100755 index 00000000..0f970a32 --- /dev/null +++ b/Pods/Eddystone/Pod/Classes/DoubleExtensions.swift @@ -0,0 +1,45 @@ +/** + Converts 16-bit 8:8 Fixed Point numbers to swift Doubles. + + Fixed Point mathematical functions: + + + Compare the results from these calls to the Examples from the "Fixed Point mathematical functions" paper. + + Double.from88FixedPoint(0, 0) + Double.from88FixedPoint(1, 0) + Double.from88FixedPoint(1, 128) + Double.from88FixedPoint(1, 192) + Double.from88FixedPoint(1, 1) + Double.from88FixedPoint(255, 0) + Double.from88FixedPoint(254, 128) + Double.from88FixedPoint(254, 0) + Double.from88FixedPoint(129, 0) + Double.from88FixedPoint(255, 128) + Double.from88FixedPoint(255, 192) + Double.from88FixedPoint(0, 128) + Double.from88FixedPoint(128, 0) + Double.from88FixedPoint(127, 0) + Double.from88FixedPoint(2, 64) + Double.from88FixedPoint(253, 192) + + +*/ + +extension Double { + static func from88FixedPoint(_ byte1: UInt8, _ byte2: UInt8) -> Double { + var double: Double = 0 + + var integer = Double(byte1) + let fraction = Double(byte2) + + if integer >= 256 / 2 { + integer -= 256 + } + + double += Double(integer) + double += (1 / 256) * Double(fraction) + + return double + } +} diff --git a/Pods/Eddystone/Pod/Classes/Frame.swift b/Pods/Eddystone/Pod/Classes/Frame.swift new file mode 100644 index 00000000..1439bd60 --- /dev/null +++ b/Pods/Eddystone/Pod/Classes/Frame.swift @@ -0,0 +1,14 @@ +// +// Frame.swift +// Pods +// +// Created by Tanner Nelson on 8/24/15. +// +// +import Foundation + +class Frame { + class func frameWithBytes(_ bytes: [Byte]) -> Frame? { + fatalError("Function should be overridden") + } +} diff --git a/Pods/Eddystone/Pod/Classes/Generic.swift b/Pods/Eddystone/Pod/Classes/Generic.swift new file mode 100644 index 00000000..ae58ffcb --- /dev/null +++ b/Pods/Eddystone/Pod/Classes/Generic.swift @@ -0,0 +1,41 @@ +open class Generic: Object { + + //MARK: Properties + fileprivate(set) open var url: URL? + fileprivate(set) open var namespace: String? + fileprivate(set) open var instance: String? + fileprivate(set) open var rssi: Double + fileprivate(set) open var txPower: Int + open var uid: String? { + get { + if let namespace = self.namespace, + let instance = self.instance { + return namespace + instance + } + return nil + } + } + + //MARK: Initializations + init(url: URL?, namespace: String?, instance: String?, signalStrength: Beacon.SignalStrength, identifier: String, rssi: Double, txPower: Int) { + self.url = url + self.namespace = namespace + self.instance = instance + self.rssi = rssi + self.txPower = txPower + + var urlString = "" + if let absoluteString = url?.absoluteString { + urlString = absoluteString + } + + var uid = "" + if let namespace = self.namespace, + let instance = self.instance { + uid = namespace + instance + } + + super.init(signalStrength: signalStrength, identifier: urlString + uid + identifier) + } + +} diff --git a/Pods/Eddystone/Pod/Classes/Global.swift b/Pods/Eddystone/Pod/Classes/Global.swift new file mode 100644 index 00000000..bea25f1d --- /dev/null +++ b/Pods/Eddystone/Pod/Classes/Global.swift @@ -0,0 +1,21 @@ +import Foundation + +public var logging = false + +func log(_ message: AnyObject) { + if logging { + print("[Eddystone] \(message)") + } +} + +func log(_ message: String) { + if logging { + print("[Eddystone] \(message)") + } +} + +enum FrameType { + case url, uid, tlm +} + +typealias Byte = Int diff --git a/Pods/Eddystone/Pod/Classes/IntExtensions.swift b/Pods/Eddystone/Pod/Classes/IntExtensions.swift new file mode 100644 index 00000000..d2abdce2 --- /dev/null +++ b/Pods/Eddystone/Pod/Classes/IntExtensions.swift @@ -0,0 +1,22 @@ +/** + IntExtensions.swift + + Convert an arbitrary length byte array into a Swift Int + + +*/ + +extension Int { + static func fromByteArray(_ bytes: [UInt8]) -> Int { + var int = 0 + + for (offset, byte) in bytes.enumerated() { + let factor: Double = Double(bytes.count) - (Double(offset) + 1); + let size: Double = 256 + + int += Int(byte) * Int(pow(size, factor)) + } + + return int + } +} diff --git a/Pods/Eddystone/Pod/Classes/NSTimeIntervalExtensions.swift b/Pods/Eddystone/Pod/Classes/NSTimeIntervalExtensions.swift new file mode 100644 index 00000000..062c515e --- /dev/null +++ b/Pods/Eddystone/Pod/Classes/NSTimeIntervalExtensions.swift @@ -0,0 +1,48 @@ +/** + NSTimeIntervalExtensions.swift + + Return human readable string for any NSTimeInterval + + +*/ + +import Foundation + +public extension TimeInterval { + var readable: String { + get { + let second = 1 + let minute = second * 60 + let hour = minute * 60 + let day = hour * 24 + + var num: Int = Int(abs(self)) + var unit = "day" + + if num >= day { + num /= day + } else if num >= hour { + num /= hour + unit = "hour" + } else if num >= minute { + num /= minute + unit = "minute" + } else if num >= second { + num /= second + unit = "second" + } else { + num = 0 + } + + if num > 1 { + unit += "s" + } + + if num == 0 { + return "now" + } else { + return "\(num) \(unit)" + } + } + } +} diff --git a/Pods/Eddystone/Pod/Classes/Object.swift b/Pods/Eddystone/Pod/Classes/Object.swift new file mode 100644 index 00000000..1c52f6d5 --- /dev/null +++ b/Pods/Eddystone/Pod/Classes/Object.swift @@ -0,0 +1,57 @@ +open class Object: Equatable { + + //MARK: Properties + /// The signal strength of the nearby entity + fileprivate(set) open var signalStrength: Beacon.SignalStrength + /// A unique identifier for the beacon + fileprivate(set) open var identifier: String + /// The percent battery left on the beacon + fileprivate(set) open var battery: Double? + /// The temperature of the beacon in degrees Celsius + fileprivate(set) open var temperature: Double? + /// The amount of packets the beacon has sent + fileprivate(set) open var advertisementCount: Int? + /// The amount of time the beacon has been on in seconds + fileprivate(set) open var onTime: TimeInterval? + + //MARK: Initilizations + init (signalStrength: Beacon.SignalStrength, identifier: String) { + self.signalStrength = signalStrength + self.identifier = identifier + } + + func parseTlmFrame(_ frame: TlmFrame) { + self.battery = Object.batteryLevelInPercent(frame.batteryVolts) + self.temperature = frame.temperature + self.advertisementCount = frame.advertisementCount + self.onTime = TimeInterval(frame.onTime / 10) + } + + //MARK: Class + class func batteryLevelInPercent(_ mvolts: Int) -> Double + { + var batteryLevel: Double + let mvoltsDouble = Double(mvolts) + + if (mvolts >= 3000) { + batteryLevel = 100 + } else if (mvolts > 2900) { + batteryLevel = 100 - ((3000 - mvoltsDouble) * 58) / 100 + } else if (mvolts > 2740) { + batteryLevel = 42 - ((2900 - mvoltsDouble) * 24) / 160 + } else if (mvolts > 2440) { + batteryLevel = 18 - ((2740 - mvoltsDouble) * 12) / 300 + } else if (mvolts > 2100) { + batteryLevel = 6 - ((2440 - mvoltsDouble) * 6) / 340 + } else { + batteryLevel = 0 + } + + return batteryLevel + } + +} + +public func ==(lhs: Object, rhs: Object) -> Bool { + return lhs.identifier == rhs.identifier +} diff --git a/Pods/Eddystone/Pod/Classes/Scanner.swift b/Pods/Eddystone/Pod/Classes/Scanner.swift new file mode 100644 index 00000000..6b47e936 --- /dev/null +++ b/Pods/Eddystone/Pod/Classes/Scanner.swift @@ -0,0 +1,173 @@ +import CoreBluetooth + +open class Scanner: NSObject { + + //MARK: Public + open class func start(_ delegate: ScannerDelegate) { + + self.shared.centralManager = CBCentralManager(delegate: self.shared, queue: nil) + self.shared.delegate = delegate + + } + + open class func stopScan() { + self.shared.centralManager.stopScan() + self.shared.delegate = nil + } + + //Returns an array of Url objects that are nearby + open class var nearbyUrls: [Url] { + get { + var urls = [Url]() + + for beacon in self.beacons { + if let urlFrame = beacon.frames.url { + let url = Url(url: urlFrame.url, signalStrength: beacon.signalStrength, identifier: beacon.identifier) + if let tlmFrame = beacon.frames.tlm { + url.parseTlmFrame(tlmFrame) + } + urls.append(url) + } + } + + return urls + } + } + + //Returns an array of Uid objects that are nearby + open class var nearbyUids: [Uid] { + get { + var uids = [Uid]() + + for beacon in self.beacons { + if let uidFrame = beacon.frames.uid { + let uid = Uid(namespace: uidFrame.namespace, instance: uidFrame.instance, signalStrength: beacon.signalStrength, identifier: beacon.identifier) + if let tlmFrame = beacon.frames.tlm { + uid.parseTlmFrame(tlmFrame) + } + uids.append(uid) + } + } + + return uids + } + } + + //Returns an array of all nearby Eddystone objects + open class var nearby: [Generic] { + get { + var generics = [Generic]() + + for beacon in self.beacons { + var url: URL? + var namespace: String? + var instance: String? + + if let uidFrame = beacon.frames.uid { + namespace = uidFrame.namespace + instance = uidFrame.instance + } + + if let urlFrame = beacon.frames.url { + url = urlFrame.url as URL + } + + let generic = Generic(url: url, namespace: namespace, instance: instance, signalStrength: beacon.signalStrength, identifier: beacon.identifier, rssi: beacon.rssiBuffer.first ?? 0, txPower: beacon.txPower) + if let tlmFrame = beacon.frames.tlm { + generic.parseTlmFrame(tlmFrame) + } + generics.append(generic) + } + + return generics + + } + } + + //MARK: Singleton + static let shared = Scanner() + + //MARK: Constants + static let eddystoneServiceUUID = CBUUID(string: "FEAA") + + //MARK: Properties + var centralManager = CBCentralManager() + var discoveredBeacons = [String: Beacon]() + var beaconTimers = [String: Timer]() + + //MARK: Delegate + var delegate: ScannerDelegate? + func notifyChange() { + self.delegate?.eddystoneNearbyDidChange() + } + + //MARK: Internal Class + class var beacons: [Beacon] { + get { + var orderedBeacons = [Beacon]() + + for beacon in self.shared.discoveredBeacons.values { + orderedBeacons.append(beacon) + } + + orderedBeacons.sort { beacon1, beacon2 in + return beacon1.distance < beacon2.distance + } + + return orderedBeacons + } + } + +} + +extension Scanner: CBCentralManagerDelegate { + + public func centralManagerDidUpdateState(_ central: CBCentralManager) { + if central.state == .poweredOn { + central.scanForPeripherals(withServices: [Scanner.eddystoneServiceUUID], options: [CBCentralManagerScanOptionAllowDuplicatesKey: true]) + } else { + log("Bluetooth not powered on. Current state: \(central.state)") + } + } + + public func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) { + let identifier = peripheral.identifier.uuidString + + if let beacon = self.discoveredBeacons[identifier] { + beacon.parseAdvertisementData(advertisementData, rssi: RSSI.doubleValue) + } else { + if let beacon = Beacon.beaconWithAdvertisementData(advertisementData, rssi: RSSI.doubleValue, identifier: identifier) { + beacon.delegate = self + self.discoveredBeacons[peripheral.identifier.uuidString] = beacon + } + } + + self.notifyChange() + self.beaconTimers[identifier]?.invalidate() + self.beaconTimers[identifier] = Timer.scheduledTimer(timeInterval: 10, target: self, selector: #selector(Scanner.beaconTimerExpire(_:)), userInfo: identifier, repeats: false) + } + + @objc func beaconTimerExpire(_ timer: Timer) { + if let identifier = timer.userInfo as? String { + log("Beacon lost") + + self.discoveredBeacons.removeValue(forKey: identifier) + self.notifyChange() + } + } +} + +extension Scanner: BeaconDelegate { + + func beaconDidChange() { + self.notifyChange() + } + +} + +//MARK: Protocol +public protocol ScannerDelegate { + + func eddystoneNearbyDidChange() + +} diff --git a/Pods/Eddystone/Pod/Classes/TlmFrame.swift b/Pods/Eddystone/Pod/Classes/TlmFrame.swift new file mode 100644 index 00000000..431f4a94 --- /dev/null +++ b/Pods/Eddystone/Pod/Classes/TlmFrame.swift @@ -0,0 +1,75 @@ +// +// TlmFrame.swift +// Pods +// +// Created by Tanner Nelson on 8/24/15. +// +// + +import UIKit + +class TlmFrame: Frame { + + var batteryVolts: Int + var temperature: Double + var advertisementCount: Int + var onTime: Int + + init(batteryVolts: Int, temperature: Double, advertisementCount: Int, onTime: Int) { + self.batteryVolts = batteryVolts + self.temperature = temperature + self.advertisementCount = advertisementCount + self.onTime = onTime + + super.init() + } + + override class func frameWithBytes(_ bytes: [Byte]) -> TlmFrame? { + var batteryVolts: Int? + var temperature: Double? + var advertisementCount: Int? + var onTime: Int? + + if bytes.count <= 2 || bytes[1] != 0 { + log("Invalid TLM version, only 0 is supported") + return nil + } + + if bytes.count >= 4 { + let vbattBytes = [bytes[2], bytes[3]] + batteryVolts = Int.fromByteArray(vbattBytes.map { byte in + return UInt8(byte) + }) + } + + if bytes.count >= 6 { + temperature = Double.from88FixedPoint(UInt8(bytes[4]), UInt8(bytes[5])) + } + + if bytes.count >= 10 { + let advCountBytes = [bytes[6], bytes[7], bytes[8], bytes[9]] + advertisementCount = Int.fromByteArray(advCountBytes.map { byte in + return UInt8(byte) + }) + } + + if bytes.count >= 14 { + let onTimeBytes = [bytes[10], bytes[11], bytes[12], bytes[13]] + onTime = Int.fromByteArray(onTimeBytes.map { byte in + return UInt8(byte) + }) + } + + if let batteryVolts = batteryVolts, + let temperature = temperature, + let advertisementCount = advertisementCount, + let onTime = onTime { + return TlmFrame(batteryVolts: batteryVolts, temperature: temperature, advertisementCount: advertisementCount, onTime: onTime) + } else { + log("Invalid TLM frame") + } + + return nil + } + +} diff --git a/Pods/Eddystone/Pod/Classes/Uid.swift b/Pods/Eddystone/Pod/Classes/Uid.swift new file mode 100644 index 00000000..45ef8a80 --- /dev/null +++ b/Pods/Eddystone/Pod/Classes/Uid.swift @@ -0,0 +1,20 @@ +open class Uid: Object { + + //MARK: Properties + fileprivate(set) open var namespace: String + fileprivate(set) open var instance: String + open var uid: String { + get { + return self.namespace + self.instance + } + } + + //MARK: Initializations + init(namespace: String, instance: String, signalStrength: Beacon.SignalStrength, identifier: String) { + self.namespace = namespace + self.instance = instance + + super.init(signalStrength: signalStrength, identifier: namespace + instance + identifier) + } + +} diff --git a/Pods/Eddystone/Pod/Classes/UidFrame.swift b/Pods/Eddystone/Pod/Classes/UidFrame.swift new file mode 100644 index 00000000..dc58e4a0 --- /dev/null +++ b/Pods/Eddystone/Pod/Classes/UidFrame.swift @@ -0,0 +1,58 @@ +// +// UidFrame.swift +// Pods +// +// Created by Tanner Nelson on 8/24/15. +// +// + +import UIKit + +class UidFrame: Frame { + + var namespace: String + var instance: String + var uid: String { + get { + return namespace + instance + } + } + + init(namespace: String, instance: String) { + self.namespace = namespace + self.instance = instance + + super.init() + } + + override class func frameWithBytes(_ bytes: [Byte]) -> UidFrame? { + var namespace = "" + var instance = "" + + for (offset, byte) in bytes.enumerated() { + var hex = String(byte, radix: 16) + if hex.characters.count == 1 { + hex = "0" + hex + } + + switch offset { + case 2...11: + namespace += hex + case 12...17: + instance += hex + default: + break + } + + } + + if namespace.characters.count == 20 && instance.characters.count == 12 { + return UidFrame(namespace: namespace, instance: instance) + } else { + log("Invalid UID frame") + } + + return nil + } + +} diff --git a/Pods/Eddystone/Pod/Classes/Url.swift b/Pods/Eddystone/Pod/Classes/Url.swift new file mode 100644 index 00000000..38fa3ed5 --- /dev/null +++ b/Pods/Eddystone/Pod/Classes/Url.swift @@ -0,0 +1,13 @@ +open class Url: Object { + + //MARK: Properties + fileprivate(set) open var url: URL + + //MARK: Initializations + init(url: URL, signalStrength: Beacon.SignalStrength, identifier: String) { + self.url = url + + super.init(signalStrength: signalStrength, identifier: url.absoluteString + identifier) + } + +} diff --git a/Pods/Eddystone/Pod/Classes/UrlFrame.swift b/Pods/Eddystone/Pod/Classes/UrlFrame.swift new file mode 100644 index 00000000..4f5656d3 --- /dev/null +++ b/Pods/Eddystone/Pod/Classes/UrlFrame.swift @@ -0,0 +1,80 @@ +// +// UrlFrame.swift +// Pods +// +// Created by Tanner Nelson on 8/24/15. +// +// +import Foundation + +class UrlFrame: Frame { + + //MARK: Constants + static let schemePrefixes = [ + "http://www.", + "https:/www.", + "http://", + "https://" + ] + + static let urlEncodings = [ + ".com/", + ".org/", + ".edu/", + ".net/", + ".info/", + ".biz/", + ".gov/", + ".com", + ".org", + ".edu", + ".net", + ".info", + ".biz", + ".gov" + ] + + //MARK: Properties + var url: URL + + //MARK: Initializations + init(url: URL) { + self.url = url + + super.init() + } + + //MARK: Class + override class func frameWithBytes(_ bytes: [Byte]) -> UrlFrame? { + var urlString = "" + + for (offset, byte) in bytes.enumerated() { + switch offset { + case 2: + if byte < UrlFrame.schemePrefixes.count { + urlString += UrlFrame.schemePrefixes[byte] + } + case 3...bytes.count-1: + if byte < UrlFrame.urlEncodings.count { + urlString += UrlFrame.urlEncodings[byte] + } else { + let unicode = UnicodeScalar(byte) + let character = Character(unicode!) + urlString.append(character) + } + default: + break + } + + } + + if let url = URL(string: urlString) { + return UrlFrame(url: url) + } else { + log("Invalid URL frame") + } + + return nil + } + +} diff --git a/Pods/Eddystone/README.md b/Pods/Eddystone/README.md new file mode 100644 index 00000000..cabf877a --- /dev/null +++ b/Pods/Eddystone/README.md @@ -0,0 +1,161 @@ +# Eddystone CocoaPod + +[![CI Status](http://img.shields.io/travis/BlueBiteLLC/Eddystone.svg?style=flat)](https://travis-ci.org/Tanner Nelson/Eddystone) +[![Version](https://img.shields.io/cocoapods/v/Eddystone.svg?style=flat)](http://cocoapods.org/pods/Eddystone) +[![License](https://img.shields.io/cocoapods/l/Eddystone.svg?style=flat)](http://cocoapods.org/pods/Eddystone) +[![Platform](https://img.shields.io/cocoapods/p/Eddystone.svg?style=flat)](http://cocoapods.org/pods/Eddystone) + +## Usage + +To run the example project, clone the repo, and run `pod install` from the Example directory first. + +### Nearby + +To fetch nearby Eddystone objects, simply start the scanner + +```swift +Eddystone.Scanner.start(self) +``` + +Then get an array of the nearby objects + +```swift +Eddystone.Scanner.nearby +``` + +To start the scanner, you will need to provide an `Eddystone.ScannerDelegate` delegate that will be notified to changes in the nearby objects + +```swift +public protocol ScannerDelegate { + func eddystoneNearbyDidChange() +} +``` + +Objects of the `Eddystone.Generic` class returned by `Eddystone.Scanner.nearby` have several properties gathered from the three Eddystone frame types and basic beacon information. + +### Beacon +```swift +public var signalStrength: Beacon.SignalStrength +public var identifier: String +``` + +### Eddystone-URL +```swift +public var url: NSURL? +``` + +### Eddystone-UID +```swift +public var namespace: String? +public var instance: String? +public var uid: String? +``` + +### Eddystone-TLM +```swift +public var battery: Double? +public var temperature: Double? +public var advertisementCount: Int? +public var onTime: NSTimeInterval? +``` + +## URL or UID Specific Applications + +Since Eddystone beacons may broadcast one or more of the frame types, most of the properties on the `Eddystone.Generic` class are optionals. If your application is dealing exlusively with Eddystone-URL or Eddystone-UID frame types, you may use the following `Eddystone.Scanner` properties instead. + +Notice the objects returned by these methods have properties that are not optionals. + +### Url +Get an array of `Eddystone.Url` objects with + +```swift +Eddystone.Scanner.nearbyUrls +``` + +`Eddystone.Url` objects have the following properties + +```swift +public var signalStrength: Beacon.SignalStrength +public var identifier: String +public var url: NSURL +``` + +### Uid +Get an array of `Eddystone.Uid` objects with + +```swift +Eddystone.Scanner.nearbyUids +``` + +`Eddystone.Uid` objects have the following properties + +```swift +public var signalStrength: Beacon.SignalStrength +public var identifier: String +public var namespace: String +public var instance: String +public var uid: String +``` + +##Debugging + +Logs from the Eddystone module may be helpful while debugging your application. To enable logs, use the following line. + +```swift +Eddystone.logging = true +``` + +## Additional Resources + +### UITableViewExtensions.swift + +As Eddystone beacons become closer or farther away from the device, they will need to be re-arranged on screen. The following gist makes re-arranging the data source for your `UITableView` much easier. + +```swift +ExampleViewController: UIViewController, Eddystone.ScannerDelegate { + var urls = Eddystone.Scanner.nearbyUrls + var previousUrls: [Eddystone.Url] = [] + + func eddystoneNearbyDidChange() { + self.previousUrls = self.urls + self.urls = Eddystone.Scanner.nearbyUrls + + self.mainTableView.switchDataSourceFrom(self.previousUrls, to: self.urls, withAnimation: .Top) + } +} +``` + + + +### SignalStrength + +Showing the relative signal strength for an Eddystone object helps the user understand how close they are to the beacon. This cocoapod provides you with an iOS 7 style Signal Strength view that you can put anywhere in your application. + + + +## Requirements + +Eddystone uses CoreBluetooth + +## Installation + +Eddystone is available through [CocoaPods](http://cocoapods.org). To install +it, simply add the following line to your Podfile: + +```ruby +pod "Eddystone" +``` + +## Examples + +The Eddystone cocoapod comes with an example iOS project that shows how the various method calls work in a real application. The example application also includes the aforementioned Additional Resources. + +## Author + +Maintained by: Sam Krantz, sam@bluebite.com (@sekrantz) + +Original by: Tanner Nelson, tanner@bluebite.com + +## License + +Eddystone is available under the MIT license. See the LICENSE file for more info. diff --git a/Pods/IP-UIKit-Wisdom/LICENSE b/Pods/IP-UIKit-Wisdom/LICENSE new file mode 100644 index 00000000..f8b5caa8 --- /dev/null +++ b/Pods/IP-UIKit-Wisdom/LICENSE @@ -0,0 +1,9 @@ +The MIT License (MIT) + +Copyright (c) 2015 Intrepid Pursuits LLC + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/Pods/IP-UIKit-Wisdom/src/CAGradientLayer/CAGradientLayer+IPGradients.h b/Pods/IP-UIKit-Wisdom/src/CAGradientLayer/CAGradientLayer+IPGradients.h new file mode 100644 index 00000000..3098659d --- /dev/null +++ b/Pods/IP-UIKit-Wisdom/src/CAGradientLayer/CAGradientLayer+IPGradients.h @@ -0,0 +1,23 @@ +// +// CAGradientLayer+IPGradients.h +// IP-UIKit-Wisdom +// +// Created by Nicholas Servidio on 10/26/15. +// Copyright © 2015 Nick Servidio. All rights reserved. +// + +#import + +@interface CAGradientLayer (IPGradients) + +/** + * Creates and returns a gradient layer by blending the specified colors + * + * @param topColor This color is 100% visible at the top of the layer and 0% at the bottom of the layer + * @param bottomColor This color is 100% visible at the bottom of the layer and 0% at the top of the layer + * + * @return The new gradient layer + */ ++ (CAGradientLayer *)gradentLayerWithTopColor:(UIColor *)topColor bottomColor:(UIColor *)bottomColor; + +@end diff --git a/Pods/IP-UIKit-Wisdom/src/CAGradientLayer/CAGradientLayer+IPGradients.m b/Pods/IP-UIKit-Wisdom/src/CAGradientLayer/CAGradientLayer+IPGradients.m new file mode 100644 index 00000000..3bd5bc23 --- /dev/null +++ b/Pods/IP-UIKit-Wisdom/src/CAGradientLayer/CAGradientLayer+IPGradients.m @@ -0,0 +1,24 @@ +// +// CAGradientLayer+IPGradients.m +// IP-UIKit-Wisdom +// +// Created by Nicholas Servidio on 10/26/15. +// Copyright © 2015 Nick Servidio. All rights reserved. +// + +#import "CAGradientLayer+IPGradients.h" + +@implementation CAGradientLayer (IPGradients) + ++ (CAGradientLayer *)gradentLayerWithTopColor:(UIColor *)topColor bottomColor:(UIColor *)bottomColor { + NSArray *gradientColors = @[(id)topColor.CGColor, (id)bottomColor.CGColor]; + NSArray *gradientLocations = @[@0.0, @1.0]; + + CAGradientLayer *gradientLayer = [CAGradientLayer layer]; + gradientLayer.colors = gradientColors; + gradientLayer.locations = gradientLocations; + + return gradientLayer; +} + +@end diff --git a/Pods/IP-UIKit-Wisdom/src/UIButton/UIButton+IPUtils.h b/Pods/IP-UIKit-Wisdom/src/UIButton/UIButton+IPUtils.h new file mode 100644 index 00000000..bebf0750 --- /dev/null +++ b/Pods/IP-UIKit-Wisdom/src/UIButton/UIButton+IPUtils.h @@ -0,0 +1,19 @@ +// +// UIButton+IPUtils.h +// Pods +// +// Created by Ying Quan Tan on 12/24/15. +// +// + +@import UIKit; + +@interface UIButton (IPUtils) + +/** + * Puts a space between the image and the text in a UIButton. Assumes that image is on the left, and text is right + * Taken from: http://stackoverflow.com/questions/4564621/aligning-text-and-image-on-uibutton-with-imageedgeinsets-and-titleedgeinsets + */ +- (void)centerButtonAndImageWithSpacing:(CGFloat)spacing; + +@end diff --git a/Pods/IP-UIKit-Wisdom/src/UIButton/UIButton+IPUtils.m b/Pods/IP-UIKit-Wisdom/src/UIButton/UIButton+IPUtils.m new file mode 100644 index 00000000..81fa90fb --- /dev/null +++ b/Pods/IP-UIKit-Wisdom/src/UIButton/UIButton+IPUtils.m @@ -0,0 +1,20 @@ +// +// UIButton+IPUtils.m +// Pods +// +// Created by Ying Quan Tan on 12/24/15. +// +// + +#import "UIButton+IPUtils.h" + +@implementation UIButton (IPUtils) + +- (void)centerButtonAndImageWithSpacing:(CGFloat)spacing { + CGFloat insetAmount = spacing / 2.0; + self.imageEdgeInsets = UIEdgeInsetsMake(0, -insetAmount, 0, insetAmount); + self.titleEdgeInsets = UIEdgeInsetsMake(0, insetAmount, 0, -insetAmount); + self.contentEdgeInsets = UIEdgeInsetsMake(0, insetAmount, 0, insetAmount); +} + +@end diff --git a/Pods/IP-UIKit-Wisdom/src/UIColor/UIColor+IPRandomColor.h b/Pods/IP-UIKit-Wisdom/src/UIColor/UIColor+IPRandomColor.h new file mode 100644 index 00000000..97ab968f --- /dev/null +++ b/Pods/IP-UIKit-Wisdom/src/UIColor/UIColor+IPRandomColor.h @@ -0,0 +1,7 @@ +#import + +@interface UIColor (IPRandomColor) + ++ (UIColor *)randomColor; + +@end diff --git a/Pods/IP-UIKit-Wisdom/src/UIColor/UIColor+IPRandomColor.m b/Pods/IP-UIKit-Wisdom/src/UIColor/UIColor+IPRandomColor.m new file mode 100644 index 00000000..0624b4ad --- /dev/null +++ b/Pods/IP-UIKit-Wisdom/src/UIColor/UIColor+IPRandomColor.m @@ -0,0 +1,12 @@ +#import "UIColor+IPRandomColor.h" + +@implementation UIColor (IPRandomColor) + ++ (UIColor *)randomColor { + return [UIColor colorWithRed:(arc4random_uniform(255) / 255.0) + green:(arc4random_uniform(255) / 255.0) + blue:(arc4random_uniform(255) / 255.0) + alpha:1]; +} + +@end diff --git a/Pods/IP-UIKit-Wisdom/src/UIImage/UIImage+ColorMaskedImage.h b/Pods/IP-UIKit-Wisdom/src/UIImage/UIImage+ColorMaskedImage.h new file mode 100644 index 00000000..2605036e --- /dev/null +++ b/Pods/IP-UIKit-Wisdom/src/UIImage/UIImage+ColorMaskedImage.h @@ -0,0 +1,14 @@ +@import UIKit; + +@interface UIImage (ColorMaskedImage) + +/*! + * Used for masking the specified image to a specific color + * + * @param color the color to mask to + * + * @return the image that has been updated to use the specified color + */ +- (UIImage *)maskToColor:(UIColor *)color; + +@end diff --git a/Pods/IP-UIKit-Wisdom/src/UIImage/UIImage+ColorMaskedImage.m b/Pods/IP-UIKit-Wisdom/src/UIImage/UIImage+ColorMaskedImage.m new file mode 100644 index 00000000..4d63e9fe --- /dev/null +++ b/Pods/IP-UIKit-Wisdom/src/UIImage/UIImage+ColorMaskedImage.m @@ -0,0 +1,16 @@ +#import "UIImage+ColorMaskedImage.h" + +@implementation UIImage (ColorMaskedImage) +- (UIImage *)maskToColor:(UIColor *)color { + CGRect rect = CGRectMake(0, 0, self.size.width, self.size.height); + UIGraphicsBeginImageContextWithOptions(rect.size, NO, self.scale); + CGContextRef c = UIGraphicsGetCurrentContext(); + [self drawInRect:rect]; + CGContextSetFillColorWithColor(c, [color CGColor]); + CGContextSetBlendMode(c, kCGBlendModeSourceAtop); + CGContextFillRect(c, rect); + UIImage *result = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + return result; +} +@end diff --git a/Pods/IP-UIKit-Wisdom/src/UITableView/UITableView+Utils.h b/Pods/IP-UIKit-Wisdom/src/UITableView/UITableView+Utils.h new file mode 100644 index 00000000..cdbe9ee4 --- /dev/null +++ b/Pods/IP-UIKit-Wisdom/src/UITableView/UITableView+Utils.h @@ -0,0 +1,32 @@ + +@import UIKit; + +@interface UITableView (Utils) + +/** + * Adjust UITableView to remove separator insets. Note that this must be called on both the + * table view and the cell's awakeFromNib. + */ +- (void)ip_setZeroSeparatorInsets; + +/** + * Adjust UITableView scroll inset to account for a bottom view, like a tab bar. + */ +- (void)ip_adjustInsetsForBottomLayoutGuideHeight:(UIViewController * _Nonnull)controller; + +@end + +@interface UITableViewCell (Utils) + +/** + * Adjust UITableViewCell to remove separator insets. Note that this must be called on both the + * table view and the cell's awakeFromNib. + */ +- (void)ip_setZeroSeparatorInsets; + +/** + * Traverses the view hierarchy to find the table view that contains this table view cell. + */ +- (UITableView * _Nullable)ip_owningTableView; + +@end diff --git a/Pods/IP-UIKit-Wisdom/src/UITableView/UITableView+Utils.m b/Pods/IP-UIKit-Wisdom/src/UITableView/UITableView+Utils.m new file mode 100644 index 00000000..dc18dd10 --- /dev/null +++ b/Pods/IP-UIKit-Wisdom/src/UITableView/UITableView+Utils.m @@ -0,0 +1,48 @@ + +#import "UITableView+Utils.h" +#import "UIView+IPAncestry.h" + +@implementation UITableView (Utils) + +- (void)ip_setZeroSeparatorInsets { + if ([self respondsToSelector:@selector(setSeparatorInset:)]) { + [self setSeparatorInset:UIEdgeInsetsZero]; + } + + if ([self respondsToSelector:@selector(setLayoutMargins:)]) { + [self setLayoutMargins:UIEdgeInsetsZero]; + } +} + +- (void)ip_adjustInsetsForBottomLayoutGuideHeight:(UIViewController *)controller { + self.contentInset = UIEdgeInsetsMake(0, 0, controller.bottomLayoutGuide.length, 0); + self.scrollIndicatorInsets = UIEdgeInsetsMake(0, 0, controller.bottomLayoutGuide.length, 0); +} + +@end + +@implementation UITableViewCell (Utils) + +- (void)ip_setZeroSeparatorInsets { + if ([self respondsToSelector:@selector(setSeparatorInset:)]) { + [self setSeparatorInset:UIEdgeInsetsZero]; + } + + if ([self respondsToSelector:@selector(setLayoutMargins:)]) { + [self setLayoutMargins:UIEdgeInsetsZero]; + } +} + +- (UITableView *)ip_owningTableView { + __block UITableView *tableView = nil; + [self enumerateSuperviewsWithBlock:^(UIView *view, NSUInteger idx, BOOL *stop) { + if ([view isKindOfClass:[UITableView class]]) { + *stop = YES; + tableView = (UITableView *)view; + } + }]; + return tableView; +} + +@end + diff --git a/Pods/IP-UIKit-Wisdom/src/UIView/UIView+Constraints.h b/Pods/IP-UIKit-Wisdom/src/UIView/UIView+Constraints.h new file mode 100644 index 00000000..33bc0214 --- /dev/null +++ b/Pods/IP-UIKit-Wisdom/src/UIView/UIView+Constraints.h @@ -0,0 +1,329 @@ +@import UIKit; + +typedef NSDictionary ConstraintDictionary; + +/** + * When a method returns a dictionary, retrieve the desired contraint by using the following keys: + */ +extern NSString *const IPConstraintKeyTop; +extern NSString *const IPConstraintKeyLeft; +extern NSString *const IPConstraintKeyBottom; +extern NSString *const IPConstraintKeyRight; + +@interface UIView (CBConstraints) + +/*! + * Constrain a view with specified insets. Use `NSNotFound` to specify edges that should not be set + * + * @param view the view to constrain + * @param insets the insets to use when positioning the view + */ +- (ConstraintDictionary *)constrainView:(UIView *)view toInsets:(UIEdgeInsets)insets; + +/*! + * Constrain view's left edge to the left edge of the caller + * + * @param view the view to constrain + */ +- (NSLayoutConstraint *)constrainViewToLeft:(UIView *)view; + +/*! + * Constrain view's left edge to the left edge of the caller with an inset + * + * @param view the view to constrain + * @param inset the inset of the view + */ +- (NSLayoutConstraint *)constrainViewToLeft:(UIView *)view withInset:(CGFloat)inset; + +/*! + * Constrain view's right edge to the right edge of the caller + * + * @param view the view to constrain + */ +- (NSLayoutConstraint *)constrainViewToRight:(UIView *)view; + +/*! + * Constrain view's right edge to the right edge of the caller with an inset + * + * @param view the view to constrain + * @param inset the inset to use when positioning the view + */ +- (NSLayoutConstraint *)constrainViewToRight:(UIView *)view withInset:(CGFloat)inset; + +/*! + * Constrain view's top edge to the top edge of the caller + * + * @param view the view to constrain + */ +- (NSLayoutConstraint *)constrainViewToTop:(UIView *)view; + +/*! + * Constrain view's top edge to the top edge of the caller with specified inset + * + * @param view the view to constrain + * @param inset the inset to use when positioning the view + */ +- (NSLayoutConstraint *)constrainViewToTop:(UIView *)view withInset:(CGFloat)inset; + +/*! + * Constrain view's bottom edge to the bottom edge of the caller + * + * @param view the view to constrain + */ +- (NSLayoutConstraint *)constrainViewToBottom:(UIView *)view; + +/*! + * Constrain view's bottom edge to the bottom edge of the caller with specified inset + * + * @param view the view to constrain + * @param inset the inset to use when positioning the view + */ +- (NSLayoutConstraint *)constrainViewToBottom:(UIView *)view withInset:(CGFloat)inset; + +/*! + * Constrain a view within the caller with specified insets from the edges. Use 'NSNotFound' to specify edges that shouldn't be set + * + * @param view the view to constrain + * @param top the top inset + * @param left left inset + * @param bottom bottom inset + * @param right right inset + */ +- (NSLayoutConstraint *)constrainView:(UIView *)view top:(CGFloat)top left:(CGFloat)left bottom:(CGFloat)bottom right:(CGFloat)right; + +/*! + * Set a view's width to be equal to the caller's width + * + * @param view the view to constrain + */ +- (NSLayoutConstraint *)constrainViewToEqualWidth:(UIView *)view; + +/*! + * Set a view's width to be equal to the caller's width with a constant and multiplier option + * + * @param view the view to constrain + * @param constant constant offset + * @param multiplier multiplier + */ +- (NSLayoutConstraint *)constrainViewToEqualWidth:(UIView *)view constant:(CGFloat)constant multiplier:(CGFloat)multiplier; + +/*! + * Set a view's height to be equal to the caller's height + * + * @param view the view to constrain + */ +- (NSLayoutConstraint *)constrainViewToEqualHeight:(UIView *)view; + +/*! + * Set a view's height to be equal to the caller's height with a constant and multiplier option + * + * @param view the view to constrain + * @param constant the constant to offset + * @param multiplier multiplier + */ +- (NSLayoutConstraint *)constrainViewToEqualHeight:(UIView *)view constant:(CGFloat)constant multiplier:(CGFloat)multiplier; + +/*! + * Constrain a view to a specified width + * + * @param view the view to constrain + * @param width the width to constrain the view + */ +- (NSLayoutConstraint *)constrainView:(UIView *)view toWidth:(CGFloat)width; + +/*! + * Constrain a view to a specified height + * + * @param view the view to constrain + * @param height the height to constrain the view + */ +- (NSLayoutConstraint *)constrainView:(UIView *)view toHeight:(CGFloat)height; + +/** + * Constrain a view to a specified aspect ration + * + * @param view the view to constrain + * @param aspectRatio the aspect ratio to constrain the view + */ +- (NSLayoutConstraint *)constrainView:(UIView *)view toAspectRatio:(CGFloat)aspectRatio; + +/*! + * Position a view above another view + * + * @param view the view to position above + * @param positioningView the view to use for positioning + */ +- (NSLayoutConstraint *)constrainView:(UIView *)view aboveView:(UIView *)positioningView; + +/** + * Position a view above another view with an offset + * + * @param view the view to position above + * @param positioningView the view to use for positioning + * @param offset the constant to offset + */ +- (NSLayoutConstraint *)constrainView:(UIView *)view aboveView:(UIView *)positioningView withOffset:(CGFloat)offset; + +/*! + * Position a view below another view + * + * @param view the view to position below + * @param positioningView the view to use for positioning + */ +- (NSLayoutConstraint *)constrainView:(UIView *)view belowView:(UIView *)positioningView; + +/** + * Position a view below another view with offset + * + * @param view the view to position below + * @param positioningView the view to use for positioning + * @param offset the constant to offset + */ +- (NSLayoutConstraint *)constrainView:(UIView *)view belowView:(UIView *)positioningView withOffset:(CGFloat)offset; + +/*! + * Position a view to the left of another view + * + * @param view the view to position + * @param positioningView the view to use for positioning + */ +- (NSLayoutConstraint *)constrainView:(UIView *)view leftOfView:(UIView *)positioningView; + +/** + * Position a view to the left of another view with offset + * + * @param view the view to position + * @param positioningView the view to use for positioning + * @param offset the constant to offset + */ +- (NSLayoutConstraint *)constrainView:(UIView *)view leftOfView:(UIView *)positioningView withOffset:(CGFloat)offset; + +/*! + * Position a view to the right of another view + * + * @param view the view to position + * @param positioningView the view to use for positioning + */ +- (NSLayoutConstraint *)constrainView:(UIView *)view rightOfView:(UIView *)positioningView; + +/** + * Position a view to the right of another view with offset + * + * @param view the view to position + * @param positioningView the view to use for positioning + * @param offset the constant to offset + */ +- (NSLayoutConstraint *)constrainView:(UIView *)view rightOfView:(UIView *)positioningView withOffset:(CGFloat)offset; + +/** + * Position two views so that their tops are aligned vertically + * + * @param view the view to position + * @param positioningView the view to use for positioning + */ +- (NSLayoutConstraint *)constrainView:(UIView *)view toTopOfView:(UIView *)positioningView; + +/** + * Position two views so that their bottoms are aligned vertically + * + * @param view the view to position + * @param positioningView the view to use for positioning + */ +- (NSLayoutConstraint *)constrainView:(UIView *)view toBottomOfView:(UIView *)positioningView; + +/** + * Constrain the width of two views to be equal + * + * @param view the view to constrain + * @param sizingView the view to use as a width reference + */ +- (NSLayoutConstraint *)constrainView:(UIView *)view toWidthOfView:(UIView *)sizingView; + +/** + * Constrain the height of two views to be equal + * + * @param view the view to constrain + * @param sizingView the view to use as a height reference + */ +- (NSLayoutConstraint *)constrainView:(UIView *)view toHeightOfView:(UIView *)sizingView; + +/*! + * More customizable control for building relationships between two views + * + * @param viewA a view to constrain + * @param attributeA the attribute to constrain + * @param viewB the second view used in constrainint + * @param attributeB the attribute to constrain + */ +- (NSLayoutConstraint *)constrainView:(UIView *)viewA attribute:(NSLayoutAttribute)attributeA toView:(UIView *)viewB attribute:(NSLayoutAttribute)attributeB; + +/*! + * More customizable control for building relationships between two views + * + * @param viewA a view to constrain + * @param attributeA the attribute to constrain + * @param viewB the second view used in constraint + * @param attributeB secondary view attribute + * @param constant constant + * @param multiplier multiplier + */ +- (NSLayoutConstraint *)constrainView:(UIView *)viewA attribute:(NSLayoutAttribute)attributeA toView:(UIView *)viewB attribute:(NSLayoutAttribute)attributeB constant:(CGFloat)constant multiplier:(CGFloat)multiplier; + +/*! + * More customizable control for building relationships between two views + * + * @param viewA primary view to constrain + * @param attributeA primary attribute + * @param viewB secondary view to constrain + * @param attributeB secondary attribute + * @param constant constant + * @param multiplier multiplier + * @param relation relation + */ +- (NSLayoutConstraint *)constrainView:(UIView *)viewA attribute:(NSLayoutAttribute)attributeA toView:(UIView *)viewB attribute:(NSLayoutAttribute)attributeB constant:(CGFloat)constant multiplier:(CGFloat)multiplier relation:(NSLayoutRelation)relation; + +/*! + * Convenience for horizontal center + * + * @param view view to constrain + */ +- (NSLayoutConstraint *)constrainViewToMiddleHorizontally:(UIView *)view; + +/*! + * Convenience for vertical center + * + * @param view view to constrain + */ +- (NSLayoutConstraint *)constrainViewToMiddleVertically:(UIView *)view; + +/*! + * Constrain top of view to the center with specified offset + * + * @param view view to constrain + * @param offset the offset from centerY to top of view + */ +- (NSLayoutConstraint *)constrainTopOfView:(UIView *)view toCenterYWithOffset:(CGFloat)offset; + +/*! + * Constrain bottom of view to the center with specified offset + * + * @param view the view to constrain + * @param offset the offset from centerY to bottom of view + */ +- (NSLayoutConstraint *)constrainBottomOfView:(UIView *)view toCenterYWithOffset:(CGFloat)offset; + +/*! + * Constrain the view to 0 on all edges of caller + * + * @param view the view to constrain + */ +- (ConstraintDictionary *)constrainViewToAllEdges:(UIView *)view; + +/*! + * Constrain the left and right edges of the view to the caller + * + * @param view the view to constrain + */ +- (ConstraintDictionary *)constrainViewToHorizontalEdges:(UIView *)view; + +@end diff --git a/Pods/IP-UIKit-Wisdom/src/UIView/UIView+Constraints.m b/Pods/IP-UIKit-Wisdom/src/UIView/UIView+Constraints.m new file mode 100644 index 00000000..b07ad33b --- /dev/null +++ b/Pods/IP-UIKit-Wisdom/src/UIView/UIView+Constraints.m @@ -0,0 +1,274 @@ +#import "UIView+Constraints.h" + +NSString *const IPConstraintKeyTop = @"IPConstraintKeyTop"; +NSString *const IPConstraintKeyLeft = @"IPConstraintKeyLeft"; +NSString *const IPConstraintKeyBottom = @"IPConstraintKeyBottom"; +NSString *const IPConstraintKeyRight = @"IPConstraintKeyRight"; + +@implementation UIView (CBConstraints) + +- (ConstraintDictionary *)constrainView:(UIView *)view top:(CGFloat)top left:(CGFloat)left bottom:(CGFloat)bottom right:(CGFloat)right { + return [self constrainView:view toInsets:UIEdgeInsetsMake(top, left, bottom, right)]; +} + +- (ConstraintDictionary *)constrainView:(UIView *)view toInsets:(UIEdgeInsets)insets { + NSMutableDictionary *constraints = [NSMutableDictionary dictionary]; + if (insets.top != NSNotFound) { + NSLayoutConstraint *top = [NSLayoutConstraint constraintWithItem:view + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:insets.top]; + constraints[IPConstraintKeyTop] = top; + } + if (insets.left != NSNotFound) { + NSLayoutConstraint *left = [NSLayoutConstraint constraintWithItem:view + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:insets.left]; + constraints[IPConstraintKeyLeft] = left; + } + if (insets.bottom != NSNotFound) { + NSLayoutConstraint *bottom = [NSLayoutConstraint constraintWithItem:view + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:-insets.bottom]; + constraints[IPConstraintKeyBottom] = bottom; + } + if (insets.right != NSNotFound) { + NSLayoutConstraint *right = [NSLayoutConstraint constraintWithItem:view + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:-insets.right]; + constraints[IPConstraintKeyRight] = right; + } + + view.translatesAutoresizingMaskIntoConstraints = NO; + [self addConstraints:constraints.allValues]; + return constraints; +} + +- (NSLayoutConstraint *)constrainViewToEqualWidth:(UIView *)view { + return [self constrainViewToEqualWidth:view constant:0.0 multiplier:1.0]; +} + +- (NSLayoutConstraint *)constrainViewToEqualWidth:(UIView *)view constant:(CGFloat)constant multiplier:(CGFloat)multiplier { + NSLayoutConstraint *width = [NSLayoutConstraint constraintWithItem:view + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeWidth + multiplier:multiplier + constant:constant]; + view.translatesAutoresizingMaskIntoConstraints = NO; + [self addConstraint:width]; + return width; +} + +- (NSLayoutConstraint *)constrainViewToEqualHeight:(UIView *)view { + return [self constrainViewToEqualHeight:view constant:0.0 multiplier:1.0]; +} + +- (NSLayoutConstraint *)constrainViewToEqualHeight:(UIView *)view constant:(CGFloat)constant multiplier:(CGFloat)multiplier { + NSLayoutConstraint *height = [NSLayoutConstraint constraintWithItem:view + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeHeight + multiplier:multiplier + constant:constant]; + view.translatesAutoresizingMaskIntoConstraints = NO; + [self addConstraint:height]; + return height; +} + +- (NSLayoutConstraint *)constrainView:(UIView *)view toWidth:(CGFloat)width { + NSLayoutConstraint *widthConstraint = [NSLayoutConstraint constraintWithItem:view + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:width]; + view.translatesAutoresizingMaskIntoConstraints = NO; + [self addConstraint:widthConstraint]; + return widthConstraint; +} + +- (NSLayoutConstraint *)constrainView:(UIView *)view toHeight:(CGFloat)height { + NSLayoutConstraint *heightConstraint = [NSLayoutConstraint constraintWithItem:view + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:height]; + view.translatesAutoresizingMaskIntoConstraints = NO; + [self addConstraint:heightConstraint]; + return heightConstraint; +} + +- (NSLayoutConstraint *)constrainView:(UIView *)view toAspectRatio:(CGFloat)aspectRatio { + return [self constrainView:view attribute:NSLayoutAttributeWidth toView:view attribute:NSLayoutAttributeHeight constant:0.0 multiplier:aspectRatio]; +} + +- (NSLayoutConstraint *)constrainView:(UIView *)view aboveView:(UIView *)positioningView { + return [self constrainView:view attribute:NSLayoutAttributeBottom toView:positioningView attribute:NSLayoutAttributeTop]; +} + +- (NSLayoutConstraint *)constrainView:(UIView *)view aboveView:(UIView *)positioningView withOffset:(CGFloat)offset { + return [self constrainView:view attribute:NSLayoutAttributeBottom toView:positioningView attribute:NSLayoutAttributeTop constant:offset multiplier:1.0]; +} + +- (NSLayoutConstraint *)constrainView:(UIView *)view belowView:(UIView *)positioningView { + return [self constrainView:view attribute:NSLayoutAttributeTop toView:positioningView attribute:NSLayoutAttributeBottom]; +} + +- (NSLayoutConstraint *)constrainView:(UIView *)view belowView:(UIView *)positioningView withOffset:(CGFloat)offset { + return [self constrainView:view attribute:NSLayoutAttributeTop toView:positioningView attribute:NSLayoutAttributeBottom constant:offset multiplier:1.0]; +} + +- (NSLayoutConstraint *)constrainView:(UIView *)view leftOfView:(UIView *)positioningView { + return [self constrainView:view attribute:NSLayoutAttributeRight toView:positioningView attribute:NSLayoutAttributeLeft]; +} + +- (NSLayoutConstraint *)constrainView:(UIView *)view leftOfView:(UIView *)positioningView withOffset:(CGFloat)offset { + return [self constrainView:view attribute:NSLayoutAttributeRight toView:positioningView attribute:NSLayoutAttributeLeft constant:offset multiplier:1.0]; +} + +- (NSLayoutConstraint *)constrainView:(UIView *)view rightOfView:(UIView *)positioningView { + return [self constrainView:view attribute:NSLayoutAttributeLeft toView:positioningView attribute:NSLayoutAttributeRight]; +} + +- (NSLayoutConstraint *)constrainView:(UIView *)view rightOfView:(UIView *)positioningView withOffset:(CGFloat)offset { + return [self constrainView:view attribute:NSLayoutAttributeLeft toView:positioningView attribute:NSLayoutAttributeRight constant:offset multiplier:1.0]; +} + +- (NSLayoutConstraint *)constrainView:(UIView *)view toTopOfView:(UIView *)positioningView { + return [self constrainView:view attribute:NSLayoutAttributeTop toView:positioningView attribute:NSLayoutAttributeTop]; +} + +- (NSLayoutConstraint *)constrainView:(UIView *)view toBottomOfView:(UIView *)positioningView { + return [self constrainView:view attribute:NSLayoutAttributeBottom toView:positioningView attribute:NSLayoutAttributeBottom]; +} + +- (NSLayoutConstraint *)constrainView:(UIView *)view toWidthOfView:(UIView *)sizingView { + return [self constrainView:view attribute:NSLayoutAttributeWidth toView:sizingView attribute:NSLayoutAttributeWidth]; +} + +- (NSLayoutConstraint *)constrainView:(UIView *)view toHeightOfView:(UIView *)sizingView { + return [self constrainView:view attribute:NSLayoutAttributeHeight toView:sizingView attribute:NSLayoutAttributeHeight]; +} + +- (NSLayoutConstraint *)constrainView:(UIView *)viewA attribute:(NSLayoutAttribute)attributeA toView:(UIView *)viewB attribute:(NSLayoutAttribute)attributeB { + return [self constrainView:viewA + attribute:attributeA + toView:viewB + attribute:attributeB + constant:0.0 + multiplier:1.0]; +} + +- (NSLayoutConstraint *)constrainView:(UIView *)viewA attribute:(NSLayoutAttribute)attributeA toView:(UIView *)viewB attribute:(NSLayoutAttribute)attributeB constant:(CGFloat)constant multiplier:(CGFloat)multiplier { + return [self constrainView:viewA + attribute:attributeA + toView:viewB + attribute:attributeB + constant:constant + multiplier:multiplier + relation:NSLayoutRelationEqual]; +} + +- (NSLayoutConstraint *)constrainView:(UIView *)viewA attribute:(NSLayoutAttribute)attributeA toView:(UIView *)viewB attribute:(NSLayoutAttribute)attributeB constant:(CGFloat)constant multiplier:(CGFloat)multiplier relation:(NSLayoutRelation)relation { + NSLayoutConstraint *bind = [NSLayoutConstraint constraintWithItem:viewA + attribute:attributeA + relatedBy:relation + toItem:viewB + attribute:attributeB + multiplier:multiplier + constant:constant]; + + viewA.translatesAutoresizingMaskIntoConstraints = NO; + viewB.translatesAutoresizingMaskIntoConstraints = NO; + [self addConstraint:bind]; + return bind; +} + +- (NSLayoutConstraint *)constrainViewToLeft:(UIView *)view { + return [self constrainViewToLeft:view withInset:0]; +} + +- (NSLayoutConstraint *)constrainViewToLeft:(UIView *)view withInset:(CGFloat)inset { + return [self constrainView:view toInsets:UIEdgeInsetsMake(NSNotFound, inset, NSNotFound, NSNotFound)][IPConstraintKeyLeft]; +} + +- (NSLayoutConstraint *)constrainViewToRight:(UIView *)view { + return [self constrainViewToRight:view withInset:0]; +} + +- (NSLayoutConstraint *)constrainViewToRight:(UIView *)view withInset:(CGFloat)inset { + return [self constrainView:view toInsets:UIEdgeInsetsMake(NSNotFound, NSNotFound, NSNotFound, -inset)][IPConstraintKeyRight]; +} + +- (NSLayoutConstraint *)constrainViewToTop:(UIView *)view { + return [self constrainViewToTop:view withInset:0]; +} + +- (NSLayoutConstraint *)constrainViewToTop:(UIView *)view withInset:(CGFloat)inset { + return [self constrainView:view toInsets:UIEdgeInsetsMake(inset, NSNotFound, NSNotFound, NSNotFound)][IPConstraintKeyTop]; +} + +- (NSLayoutConstraint *)constrainViewToBottom:(UIView *)view { + return [self constrainViewToBottom:view withInset:0]; +} + +- (NSLayoutConstraint *)constrainViewToBottom:(UIView *)view withInset:(CGFloat)inset { + return [self constrainView:view toInsets:UIEdgeInsetsMake(NSNotFound, NSNotFound, -inset, NSNotFound)][IPConstraintKeyBottom]; +} + +- (NSLayoutConstraint *)constrainViewToMiddleVertically:(UIView *)view { + return [self constrainView:view attribute:NSLayoutAttributeCenterY toView:self attribute:NSLayoutAttributeCenterY]; +} + +- (NSLayoutConstraint *)constrainViewToMiddleHorizontally:(UIView *)view { + return [self constrainView:view attribute:NSLayoutAttributeCenterX toView:self attribute:NSLayoutAttributeCenterX]; +} + +- (NSLayoutConstraint *)constrainTopOfView:(UIView *)view toCenterYWithOffset:(CGFloat)offset { + return [self constrainView:view + attribute:NSLayoutAttributeTop + toView:self + attribute:NSLayoutAttributeCenterY + constant:offset + multiplier:1]; +} + +- (NSLayoutConstraint *)constrainBottomOfView:(UIView *)view toCenterYWithOffset:(CGFloat)offset { + return [self constrainView:view + attribute:NSLayoutAttributeBottom + toView:self + attribute:NSLayoutAttributeCenterY + constant:offset + multiplier:1]; +} + +- (ConstraintDictionary *)constrainViewToAllEdges:(UIView *)view { + return [self constrainView:view toInsets:UIEdgeInsetsZero]; +} + +- (ConstraintDictionary *)constrainViewToHorizontalEdges:(UIView *)view { + return [self constrainView:view toInsets:UIEdgeInsetsMake(NSNotFound, 0, NSNotFound, 0)]; +} + +@end diff --git a/Pods/IP-UIKit-Wisdom/src/UIView/UIView+IPAncestry.h b/Pods/IP-UIKit-Wisdom/src/UIView/UIView+IPAncestry.h new file mode 100644 index 00000000..fd3fad55 --- /dev/null +++ b/Pods/IP-UIKit-Wisdom/src/UIView/UIView+IPAncestry.h @@ -0,0 +1,20 @@ +#import + +@interface UIView (IPAncestry) + +/*! + Enumerates through the receiver's superviews until no superviews are found. + */ +- (void)enumerateSuperviewsWithBlock:(void (^)(UIView *view, NSUInteger idx, BOOL *stop))block; + +/*! + Performs a depth first search and returns the first view, including the receiver, that passes the specified test. + */ +- (UIView *)descendantViewPassingTest:(BOOL (^)(UIView *viewToCheck))test; + +/*! + Returns all the descendant views that pass the given test. + */ +- (NSSet *)allDescendantViewsPassingTest:(BOOL (^)(UIView *viewToCheck))test; + +@end diff --git a/Pods/IP-UIKit-Wisdom/src/UIView/UIView+IPAncestry.m b/Pods/IP-UIKit-Wisdom/src/UIView/UIView+IPAncestry.m new file mode 100644 index 00000000..07890417 --- /dev/null +++ b/Pods/IP-UIKit-Wisdom/src/UIView/UIView+IPAncestry.m @@ -0,0 +1,42 @@ +#import "UIView+IPAncestry.h" + +@implementation UIView (IPAncestry) + +- (void)enumerateSuperviewsWithBlock:(void (^)(UIView *view, NSUInteger idx, BOOL *stop))block { + UIView *thisView = self; + NSUInteger index = 0; + __block BOOL stop = NO; + while (thisView.superview != nil && stop == NO) { + block(thisView.superview, index, &stop); + index++; + thisView = thisView.superview; + } +} + +- (UIView *)descendantViewPassingTest:(BOOL (^)(UIView *viewToCheck))test { + if (test(self)) { + return self; + } + for (UIView *subview in self.subviews) { + UIView *subviewResult = [subview descendantViewPassingTest:test]; + if (subviewResult) { + return subviewResult; + } + } + return nil; +} + +- (NSSet *)allDescendantViewsPassingTest:(BOOL (^)(UIView *viewToCheck))test { + NSMutableSet *descendantViews = [NSMutableSet set]; + if (test(self)) { + [descendantViews addObject:self]; + } + + for (UIView *subview in self.subviews) { + [descendantViews unionSet:[subview allDescendantViewsPassingTest:test]]; + } + + return [descendantViews copy]; +} + +@end diff --git a/Pods/IP-UIKit-Wisdom/src/UIView/UIView+IPFrameUtils.h b/Pods/IP-UIKit-Wisdom/src/UIView/UIView+IPFrameUtils.h new file mode 100644 index 00000000..37bac14f --- /dev/null +++ b/Pods/IP-UIKit-Wisdom/src/UIView/UIView+IPFrameUtils.h @@ -0,0 +1,63 @@ +#import + +@interface UIView (IPFrameUtils) + +/*! + Gets and sets the view's origin. This leaves the frame's size untouched. + */ +@property (nonatomic, readwrite) CGPoint frameOrigin; + +/*! + Gets and sets the view's frame sizesize. This leaves the frame's origin untouched. + */ +@property (nonatomic, readwrite) CGSize frameSize; + +/*! + Gets and sets the view frame's x origin. + */ +@property (nonatomic, readwrite) CGFloat frameX; + +/*! + Gets and sets the view frame's y origin. + */ +@property (nonatomic, readwrite) CGFloat frameY; + +/*! + Gets and sets the view frame's width + */ +@property (nonatomic, readwrite) CGFloat frameWidth; + +/*! + Gets and sets the view frame's height + */ +@property (nonatomic, readwrite) CGFloat frameHeight; + +/*! + Gets and sets the view frame's middle x position + */ +@property (nonatomic, readwrite) CGFloat frameMidX; + +/*! + Gets and sets the view frame's middle y position + */ +@property (nonatomic, readwrite) CGFloat frameMidY; + +/*! + Gets x value of the right edge of the view's frame. + Setting frameMaxX moves the origin of the view so that the right edge is at frameMaxX. The frame's width does not change. + */ +@property (nonatomic, readwrite) CGFloat frameMaxX; + +/*! + Gets y value of the bottom edge of the view's frame. + Setting frameMaxY moves the origin of the view so that the bottom edge is at frameMaxY. The frame's height does not change. + */ +@property (nonatomic, readwrite) CGFloat frameMaxY; + +/*! + When adjustHeight is NO, this moves the origin of the view so that the bottom edge is at frameMaxY. The frame's height does not change. + When adjustHeight is YES, the size of the view is changed so that the bottom edge is at frameMaxY. + */ +- (void)setFrameMaxY:(CGFloat)frameMaxY adjustHeight:(BOOL)adjustHeight; + +@end diff --git a/Pods/IP-UIKit-Wisdom/src/UIView/UIView+IPFrameUtils.m b/Pods/IP-UIKit-Wisdom/src/UIView/UIView+IPFrameUtils.m new file mode 100644 index 00000000..b131f027 --- /dev/null +++ b/Pods/IP-UIKit-Wisdom/src/UIView/UIView+IPFrameUtils.m @@ -0,0 +1,115 @@ +#import "UIView+IPFrameUtils.h" + +@implementation UIView (IPFrameUtils) + +- (CGPoint)frameOrigin { + return self.frame.origin; +} + +- (void)setFrameOrigin:(CGPoint)origin { + CGRect frame = self.frame; + frame.origin = origin; + self.frame = frame; +} + +- (CGSize)frameSize { + return self.frame.size; +} + +- (void)setFrameSize:(CGSize)size { + CGRect frame = self.frame; + frame.size = size; + self.frame = frame; +} + +- (CGFloat)frameX { + return CGRectGetMinX(self.frame); +} + +- (void)setFrameX:(CGFloat)x { + CGRect frame = self.frame; + frame.origin.x = x; + self.frame = frame; +} + +- (CGFloat)frameY { + return CGRectGetMinY(self.frame); +} + +- (void)setFrameY:(CGFloat)y { + CGRect frame = self.frame; + frame.origin.y = y; + self.frame = frame; +} + +- (CGFloat)frameWidth { + return CGRectGetWidth(self.frame); +} + +- (void)setFrameWidth:(CGFloat)width { + CGRect frame = self.frame; + frame.size.width = width; + self.frame = frame; +} + +- (CGFloat)frameHeight { + return CGRectGetHeight(self.frame); +} + +- (void)setFrameHeight:(CGFloat)height { + CGRect frame = self.frame; + frame.size.height = height; + self.frame = frame; +} + +- (CGFloat)frameMaxX { + return CGRectGetMaxX(self.frame); +} + +- (void)setFrameMaxX:(CGFloat)maxX { + CGRect frame = self.frame; + frame.origin.x = maxX - self.frameWidth; + self.frame = frame; +} + +- (CGFloat)frameMaxY { + return CGRectGetMaxY(self.frame); +} + +- (void)setFrameMaxY:(CGFloat)maxY { + [self setFrameMaxY:maxY adjustHeight:NO]; +} + +- (CGFloat)frameMidX { + return CGRectGetMidX(self.frame); +} + +- (void)setFrameMidX:(CGFloat)midX { + [self setFrameX:midX - floor(self.frameWidth/2)]; +} + +- (CGFloat)frameMidY { + return CGRectGetMidY(self.frame); +} + +- (void)setFrameMidY:(CGFloat)midY { + [self setFrameY:midY - floor(self.frameHeight/2)]; +} + +- (void)setFrameMaxY:(CGFloat)frameMaxY adjustHeight:(BOOL)adjustHeight { + CGRect frame = self.frame; + BOOL maxYGreaterThanOriginY = frameMaxY > self.frameY; + if (adjustHeight && maxYGreaterThanOriginY) + { + frame.size.height = frameMaxY - self.frameY; + } + else + { + frame.origin.y = frameMaxY - self.frameHeight; + } + self.frame = frame; + +} + +@end + diff --git a/Pods/IP-UIKit-Wisdom/src/UIView/UIView+NibInitable.h b/Pods/IP-UIKit-Wisdom/src/UIView/UIView+NibInitable.h new file mode 100644 index 00000000..c899fddb --- /dev/null +++ b/Pods/IP-UIKit-Wisdom/src/UIView/UIView+NibInitable.h @@ -0,0 +1,14 @@ +@import UIKit; + +@interface UIView (NibInitable) + +/*! + * Initialize a view with a specified nib in the main bundle + * + * @param nibNameOrNil the name of the nib or nil. If `nil`, will use class name. In Swift, do not use `nil` or name spacing will conflict w/ nib name. + * + * @return an initialized view with the specified nib name, or nil if the nib can't be found or nib class conflicts. + */ +- (instancetype)initWithNibNamed:(NSString *)nibNameOrNil; + +@end diff --git a/Pods/IP-UIKit-Wisdom/src/UIView/UIView+NibInitable.m b/Pods/IP-UIKit-Wisdom/src/UIView/UIView+NibInitable.m new file mode 100644 index 00000000..423913e4 --- /dev/null +++ b/Pods/IP-UIKit-Wisdom/src/UIView/UIView+NibInitable.m @@ -0,0 +1,28 @@ +#import "UIView+NibInitable.h" + +#pragma clang diagnostic push +// Ignoring this warning because a call will be made to `initWithCoder:` when the nib is loaded, otherwise the function fails. +#pragma clang diagnostic ignored "-Wobjc-designated-initializers" + +@implementation UIView (NibInitable) +- (instancetype)initWithNibNamed:(NSString *)nibNameOrNil { + if (!nibNameOrNil) { + nibNameOrNil = NSStringFromClass([self class]); + } + NSArray *viewsInNib = [[NSBundle mainBundle] loadNibNamed:nibNameOrNil + owner:nil + options:nil]; + for (id view in viewsInNib) { + if ([view isKindOfClass:[self class]]) { + self = view; + break; + } + } + + NSAssert(self != nil, + @"Unable to initialize view of class: %@ from nib named: %@", [self class], nibNameOrNil); + return self; +} +@end + +#pragma clang diagnostic pop diff --git a/Pods/IP-UIKit-Wisdom/src/UIViewController/UIViewController+Containment.h b/Pods/IP-UIKit-Wisdom/src/UIViewController/UIViewController+Containment.h new file mode 100644 index 00000000..275fd313 --- /dev/null +++ b/Pods/IP-UIKit-Wisdom/src/UIViewController/UIViewController+Containment.h @@ -0,0 +1,33 @@ +// +// UIViewController+Containment.h +// Chronability +// +// Created by Ying Quan Tan on 5/7/15. +// Copyright (c) 2015 IntrepidPursuits. All rights reserved. +// + +@import UIKit; + +@interface UIViewController(Containment) + +/*! + * Add a child view controller's view to the caller's view + * + * @param controller the controller to add as a subview + */ +- (void)ip_addChildViewController:(UIViewController *)controller; + +/*! + * Add a child view controller to the caller, but add the view to the specified subview + * + * @param controller the controller to add as a subview + * @param view the view with which to add the controller's view + */ +- (void)ip_addChildViewController:(UIViewController *)controller toView:(UIView *)view; + +/*! + * Remove from parent + */ +- (void)ip_removeFromParentViewController; + +@end diff --git a/Pods/IP-UIKit-Wisdom/src/UIViewController/UIViewController+Containment.m b/Pods/IP-UIKit-Wisdom/src/UIViewController/UIViewController+Containment.m new file mode 100644 index 00000000..99068e1c --- /dev/null +++ b/Pods/IP-UIKit-Wisdom/src/UIViewController/UIViewController+Containment.m @@ -0,0 +1,30 @@ +// +// UIViewController+Containment.m +// Chronability +// +// Created by Ying Quan Tan on 5/7/15. +// Copyright (c) 2015 IntrepidPursuits. All rights reserved. +// + +#import "UIViewController+Containment.h" + +@implementation UIViewController(Containment) + +- (void)ip_addChildViewController:(UIViewController *)controller { + [self ip_addChildViewController:controller toView:self.view]; +} + +- (void)ip_addChildViewController:(UIViewController *)controller toView:(UIView *)view { + [self addChildViewController:controller]; + [view addSubview:controller.view]; + [controller didMoveToParentViewController:self]; +} + +- (void)ip_removeFromParentViewController { + [self willMoveToParentViewController:nil]; + [self removeFromParentViewController]; + [self.view removeFromSuperview]; + [self didMoveToParentViewController:nil]; +} + +@end diff --git a/Pods/KVOController/FBKVOController/FBKVOController.h b/Pods/KVOController/FBKVOController/FBKVOController.h new file mode 100644 index 00000000..285c1090 --- /dev/null +++ b/Pods/KVOController/FBKVOController/FBKVOController.h @@ -0,0 +1,200 @@ +/** + Copyright (c) 2014-present, Facebook, Inc. + All rights reserved. + + This source code is licensed under the BSD-style license found in the + LICENSE file in the root directory of this source tree. An additional grant + of patent rights can be found in the PATENTS file in the same directory. + */ + +#import + +/** + This macro ensures that key path exists at compile time. + Given a real receiver with a key path as you would call it, it verifies at compile time that the key path exists, without calling it. + + For example: + + FBKVOKeyPath(string.length) => @"length" + + Or even the complex case: + + FBKVOKeyPath(string.lowercaseString.length) => @"lowercaseString.length". + */ +#define FBKVOKeyPath(KEYPATH) \ +@(((void)(NO && ((void)KEYPATH, NO)), \ +({ const char *fbkvokeypath = strchr(#KEYPATH, '.'); NSCAssert(fbkvokeypath, @"Provided key path is invalid."); fbkvokeypath + 1; }))) + +/** + This macro ensures that key path exists at compile time. + Given a receiver type and a key path, it verifies at compile time that the key path exists, without calling it. + + For example: + + FBKVOClassKeyPath(NSString, length) => @"length" + FBKVOClassKeyPath(NSString, lowercaseString.length) => @"lowercaseString.length" + */ +#define FBKVOClassKeyPath(CLASS, KEYPATH) \ +@(((void)(NO && ((void)((CLASS *)(nil)).KEYPATH, NO)), #KEYPATH)) + +NS_ASSUME_NONNULL_BEGIN + +/** + Key provided in the @c change dictionary of @c FBKVONotificationBlock that's value represents the key-path being observed + */ +extern NSString *const FBKVONotificationKeyPathKey; + +/** + @abstract Block called on key-value change notification. + @param observer The observer of the change. + @param object The object changed. + @param change The change dictionary which also includes @c FBKVONotificationKeyPathKey + */ +typedef void (^FBKVONotificationBlock)(id _Nullable observer, id object, NSDictionary *change); + +/** + @abstract FBKVOController makes Key-Value Observing simpler and safer. + @discussion FBKVOController adds support for handling key-value changes with blocks and custom actions, as well as the NSKeyValueObserving callback. Notification will never message a deallocated observer. Observer removal never throws exceptions, and observers are removed implicitly on controller deallocation. FBKVOController is also thread safe. When used in a concurrent environment, it protects observers from possible resurrection and avoids ensuing crash. By default, the controller maintains a strong reference to objects observed. + */ +@interface FBKVOController : NSObject + +///-------------------------------------- +#pragma mark - Initialize +///-------------------------------------- + +/** + @abstract Creates and returns an initialized KVO controller instance. + @param observer The object notified on key-value change. + @return The initialized KVO controller instance. + */ ++ (instancetype)controllerWithObserver:(nullable id)observer; + +/** + @abstract The designated initializer. + @param observer The object notified on key-value change. The specified observer must support weak references. + @param retainObserved Flag indicating whether observed objects should be retained. + @return The initialized KVO controller instance. + @discussion Use retainObserved = NO when a strong reference between controller and observee would create a retain loop. When not retaining observees, special care must be taken to remove observation info prior to observee dealloc. + */ +- (instancetype)initWithObserver:(nullable id)observer retainObserved:(BOOL)retainObserved NS_DESIGNATED_INITIALIZER; + +/** + @abstract Convenience initializer. + @param observer The object notified on key-value change. The specified observer must support weak references. + @return The initialized KVO controller instance. + @discussion By default, KVO controller retains objects observed. + */ +- (instancetype)initWithObserver:(nullable id)observer; + +/** + @abstract Initializes a new instance. + + @warning This method is unavaialble. Please use `initWithObserver:` instead. + */ +- (instancetype)init NS_UNAVAILABLE; + +/** + @abstract Allocates memory and initializes a new instance into it. + + @warning This method is unavaialble. Please use `controllerWithObserver:` instead. + */ ++ (instancetype)new NS_UNAVAILABLE; + +///-------------------------------------- +#pragma mark - Observe +///-------------------------------------- + +/** + The observer notified on key-value change. Specified on initialization. + */ +@property (nullable, nonatomic, weak, readonly) id observer; + +/** + @abstract Registers observer for key-value change notification. + @param object The object to observe. + @param keyPath The key path to observe. + @param options The NSKeyValueObservingOptions to use for observation. + @param block The block to execute on notification. + @discussion On key-value change, the specified block is called. In order to avoid retain loops, the block must avoid referencing the KVO controller or an owner thereof. Observing an already observed object key path or nil results in no operation. + */ +- (void)observe:(nullable id)object keyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options block:(FBKVONotificationBlock)block; + +/** + @abstract Registers observer for key-value change notification. + @param object The object to observe. + @param keyPath The key path to observe. + @param options The NSKeyValueObservingOptions to use for observation. + @param action The observer selector called on key-value change. + @discussion On key-value change, the observer's action selector is called. The selector provided should take the form of -propertyDidChange, -propertyDidChange: or -propertyDidChange:object:, where optional parameters delivered will be KVO change dictionary and object observed. Observing nil or observing an already observed object's key path results in no operation. + */ +- (void)observe:(nullable id)object keyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options action:(SEL)action; + +/** + @abstract Registers observer for key-value change notification. + @param object The object to observe. + @param keyPath The key path to observe. + @param options The NSKeyValueObservingOptions to use for observation. + @param context The context specified. + @discussion On key-value change, the observer's -observeValueForKeyPath:ofObject:change:context: method is called. Observing an already observed object key path or nil results in no operation. + */ +- (void)observe:(nullable id)object keyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(nullable void *)context; + + +/** + @abstract Registers observer for key-value change notification. + @param object The object to observe. + @param keyPaths The key paths to observe. + @param options The NSKeyValueObservingOptions to use for observation. + @param block The block to execute on notification. + @discussion On key-value change, the specified block is called. Inorder to avoid retain loops, the block must avoid referencing the KVO controller or an owner thereof. Observing an already observed object key path or nil results in no operation. + */ +- (void)observe:(nullable id)object keyPaths:(NSArray *)keyPaths options:(NSKeyValueObservingOptions)options block:(FBKVONotificationBlock)block; + +/** + @abstract Registers observer for key-value change notification. + @param object The object to observe. + @param keyPaths The key paths to observe. + @param options The NSKeyValueObservingOptions to use for observation. + @param action The observer selector called on key-value change. + @discussion On key-value change, the observer's action selector is called. The selector provided should take the form of -propertyDidChange, -propertyDidChange: or -propertyDidChange:object:, where optional parameters delivered will be KVO change dictionary and object observed. Observing nil or observing an already observed object's key path results in no operation. + */ +- (void)observe:(nullable id)object keyPaths:(NSArray *)keyPaths options:(NSKeyValueObservingOptions)options action:(SEL)action; + +/** + @abstract Registers observer for key-value change notification. + @param object The object to observe. + @param keyPaths The key paths to observe. + @param options The NSKeyValueObservingOptions to use for observation. + @param context The context specified. + @discussion On key-value change, the observer's -observeValueForKeyPath:ofObject:change:context: method is called. Observing an already observed object key path or nil results in no operation. + */ +- (void)observe:(nullable id)object keyPaths:(NSArray *)keyPaths options:(NSKeyValueObservingOptions)options context:(nullable void *)context; + +///-------------------------------------- +#pragma mark - Unobserve +///-------------------------------------- + +/** + @abstract Unobserve object key path. + @param object The object to unobserve. + @param keyPath The key path to observe. + @discussion If not observing object key path, or unobserving nil, this method results in no operation. + */ +- (void)unobserve:(nullable id)object keyPath:(NSString *)keyPath; + +/** + @abstract Unobserve all object key paths. + @param object The object to unobserve. + @discussion If not observing object, or unobserving nil, this method results in no operation. + */ +- (void)unobserve:(nullable id)object; + +/** + @abstract Unobserve all objects. + @discussion If not observing any objects, this method results in no operation. + */ +- (void)unobserveAll; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Pods/KVOController/FBKVOController/FBKVOController.m b/Pods/KVOController/FBKVOController/FBKVOController.m new file mode 100644 index 00000000..8b48a08a --- /dev/null +++ b/Pods/KVOController/FBKVOController/FBKVOController.m @@ -0,0 +1,676 @@ +/** + Copyright (c) 2014-present, Facebook, Inc. + All rights reserved. + + This source code is licensed under the BSD-style license found in the + LICENSE file in the root directory of this source tree. An additional grant + of patent rights can be found in the PATENTS file in the same directory. + */ + +#import "FBKVOController.h" + +#import +#import + +#if !__has_feature(objc_arc) +#error This file must be compiled with ARC. Convert your project to ARC or specify the -fobjc-arc flag. +#endif + +NS_ASSUME_NONNULL_BEGIN + +#pragma mark Utilities - + +static NSString *describe_option(NSKeyValueObservingOptions option) +{ + switch (option) { + case NSKeyValueObservingOptionNew: + return @"NSKeyValueObservingOptionNew"; + break; + case NSKeyValueObservingOptionOld: + return @"NSKeyValueObservingOptionOld"; + break; + case NSKeyValueObservingOptionInitial: + return @"NSKeyValueObservingOptionInitial"; + break; + case NSKeyValueObservingOptionPrior: + return @"NSKeyValueObservingOptionPrior"; + break; + default: + NSCAssert(NO, @"unexpected option %tu", option); + break; + } + return nil; +} + +static void append_option_description(NSMutableString *s, NSUInteger option) +{ + if (0 == s.length) { + [s appendString:describe_option(option)]; + } else { + [s appendString:@"|"]; + [s appendString:describe_option(option)]; + } +} + +static NSUInteger enumerate_flags(NSUInteger *ptrFlags) +{ + NSCAssert(ptrFlags, @"expected ptrFlags"); + if (!ptrFlags) { + return 0; + } + + NSUInteger flags = *ptrFlags; + if (!flags) { + return 0; + } + + NSUInteger flag = 1 << __builtin_ctzl(flags); + flags &= ~flag; + *ptrFlags = flags; + return flag; +} + +static NSString *describe_options(NSKeyValueObservingOptions options) +{ + NSMutableString *s = [NSMutableString string]; + NSUInteger option; + while (0 != (option = enumerate_flags(&options))) { + append_option_description(s, option); + } + return s; +} + +#pragma mark _FBKVOInfo - + +typedef NS_ENUM(uint8_t, _FBKVOInfoState) { + _FBKVOInfoStateInitial = 0, + + // whether the observer registration in Foundation has completed + _FBKVOInfoStateObserving, + + // whether `unobserve` was called before observer registration in Foundation has completed + // this could happen when `NSKeyValueObservingOptionInitial` is one of the NSKeyValueObservingOptions + _FBKVOInfoStateNotObserving, +}; + +NSString *const FBKVONotificationKeyPathKey = @"FBKVONotificationKeyPathKey"; + +/** + @abstract The key-value observation info. + @discussion Object equality is only used within the scope of a controller instance. Safely omit controller from equality definition. + */ +@interface _FBKVOInfo : NSObject +@end + +@implementation _FBKVOInfo +{ +@public + __weak FBKVOController *_controller; + NSString *_keyPath; + NSKeyValueObservingOptions _options; + SEL _action; + void *_context; + FBKVONotificationBlock _block; + _FBKVOInfoState _state; +} + +- (instancetype)initWithController:(FBKVOController *)controller + keyPath:(NSString *)keyPath + options:(NSKeyValueObservingOptions)options + block:(nullable FBKVONotificationBlock)block + action:(nullable SEL)action + context:(nullable void *)context +{ + self = [super init]; + if (nil != self) { + _controller = controller; + _block = [block copy]; + _keyPath = [keyPath copy]; + _options = options; + _action = action; + _context = context; + } + return self; +} + +- (instancetype)initWithController:(FBKVOController *)controller keyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options block:(FBKVONotificationBlock)block +{ + return [self initWithController:controller keyPath:keyPath options:options block:block action:NULL context:NULL]; +} + +- (instancetype)initWithController:(FBKVOController *)controller keyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options action:(SEL)action +{ + return [self initWithController:controller keyPath:keyPath options:options block:NULL action:action context:NULL]; +} + +- (instancetype)initWithController:(FBKVOController *)controller keyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context +{ + return [self initWithController:controller keyPath:keyPath options:options block:NULL action:NULL context:context]; +} + +- (instancetype)initWithController:(FBKVOController *)controller keyPath:(NSString *)keyPath +{ + return [self initWithController:controller keyPath:keyPath options:0 block:NULL action:NULL context:NULL]; +} + +- (NSUInteger)hash +{ + return [_keyPath hash]; +} + +- (BOOL)isEqual:(id)object +{ + if (nil == object) { + return NO; + } + if (self == object) { + return YES; + } + if (![object isKindOfClass:[self class]]) { + return NO; + } + return [_keyPath isEqualToString:((_FBKVOInfo *)object)->_keyPath]; +} + +- (NSString *)debugDescription +{ + NSMutableString *s = [NSMutableString stringWithFormat:@"<%@:%p keyPath:%@", NSStringFromClass([self class]), self, _keyPath]; + if (0 != _options) { + [s appendFormat:@" options:%@", describe_options(_options)]; + } + if (NULL != _action) { + [s appendFormat:@" action:%@", NSStringFromSelector(_action)]; + } + if (NULL != _context) { + [s appendFormat:@" context:%p", _context]; + } + if (NULL != _block) { + [s appendFormat:@" block:%p", _block]; + } + [s appendString:@">"]; + return s; +} + +@end + +#pragma mark _FBKVOSharedController - + +/** + @abstract The shared KVO controller instance. + @discussion Acts as a receptionist, receiving and forwarding KVO notifications. + */ +@interface _FBKVOSharedController : NSObject + +/** A shared instance that never deallocates. */ ++ (instancetype)sharedController; + +/** observe an object, info pair */ +- (void)observe:(id)object info:(nullable _FBKVOInfo *)info; + +/** unobserve an object, info pair */ +- (void)unobserve:(id)object info:(nullable _FBKVOInfo *)info; + +/** unobserve an object with a set of infos */ +- (void)unobserve:(id)object infos:(nullable NSSet *)infos; + +@end + +@implementation _FBKVOSharedController +{ + NSHashTable<_FBKVOInfo *> *_infos; + pthread_mutex_t _mutex; +} + ++ (instancetype)sharedController +{ + static _FBKVOSharedController *_controller = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + _controller = [[_FBKVOSharedController alloc] init]; + }); + return _controller; +} + +- (instancetype)init +{ + self = [super init]; + if (nil != self) { + NSHashTable *infos = [NSHashTable alloc]; +#ifdef __IPHONE_OS_VERSION_MIN_REQUIRED + _infos = [infos initWithOptions:NSPointerFunctionsWeakMemory|NSPointerFunctionsObjectPointerPersonality capacity:0]; +#elif defined(__MAC_OS_X_VERSION_MIN_REQUIRED) + if ([NSHashTable respondsToSelector:@selector(weakObjectsHashTable)]) { + _infos = [infos initWithOptions:NSPointerFunctionsWeakMemory|NSPointerFunctionsObjectPointerPersonality capacity:0]; + } else { + // silence deprecated warnings +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + _infos = [infos initWithOptions:NSPointerFunctionsZeroingWeakMemory|NSPointerFunctionsObjectPointerPersonality capacity:0]; +#pragma clang diagnostic pop + } + +#endif + pthread_mutex_init(&_mutex, NULL); + } + return self; +} + +- (void)dealloc +{ + pthread_mutex_destroy(&_mutex); +} + +- (NSString *)debugDescription +{ + NSMutableString *s = [NSMutableString stringWithFormat:@"<%@:%p", NSStringFromClass([self class]), self]; + + // lock + pthread_mutex_lock(&_mutex); + + NSMutableArray *infoDescriptions = [NSMutableArray arrayWithCapacity:_infos.count]; + for (_FBKVOInfo *info in _infos) { + [infoDescriptions addObject:info.debugDescription]; + } + + [s appendFormat:@" contexts:%@", infoDescriptions]; + + // unlock + pthread_mutex_unlock(&_mutex); + + [s appendString:@">"]; + return s; +} + +- (void)observe:(id)object info:(nullable _FBKVOInfo *)info +{ + if (nil == info) { + return; + } + + // register info + pthread_mutex_lock(&_mutex); + [_infos addObject:info]; + pthread_mutex_unlock(&_mutex); + + // add observer + [object addObserver:self forKeyPath:info->_keyPath options:info->_options context:(void *)info]; + + if (info->_state == _FBKVOInfoStateInitial) { + info->_state = _FBKVOInfoStateObserving; + } else if (info->_state == _FBKVOInfoStateNotObserving) { + // this could happen when `NSKeyValueObservingOptionInitial` is one of the NSKeyValueObservingOptions, + // and the observer is unregistered within the callback block. + // at this time the object has been registered as an observer (in Foundation KVO), + // so we can safely unobserve it. + [object removeObserver:self forKeyPath:info->_keyPath context:(void *)info]; + } +} + +- (void)unobserve:(id)object info:(nullable _FBKVOInfo *)info +{ + if (nil == info) { + return; + } + + // unregister info + pthread_mutex_lock(&_mutex); + [_infos removeObject:info]; + pthread_mutex_unlock(&_mutex); + + // remove observer + if (info->_state == _FBKVOInfoStateObserving) { + [object removeObserver:self forKeyPath:info->_keyPath context:(void *)info]; + } + info->_state = _FBKVOInfoStateNotObserving; +} + +- (void)unobserve:(id)object infos:(nullable NSSet<_FBKVOInfo *> *)infos +{ + if (0 == infos.count) { + return; + } + + // unregister info + pthread_mutex_lock(&_mutex); + for (_FBKVOInfo *info in infos) { + [_infos removeObject:info]; + } + pthread_mutex_unlock(&_mutex); + + // remove observer + for (_FBKVOInfo *info in infos) { + if (info->_state == _FBKVOInfoStateObserving) { + [object removeObserver:self forKeyPath:info->_keyPath context:(void *)info]; + } + info->_state = _FBKVOInfoStateNotObserving; + } +} + +- (void)observeValueForKeyPath:(nullable NSString *)keyPath + ofObject:(nullable id)object + change:(nullable NSDictionary *)change + context:(nullable void *)context +{ + NSAssert(context, @"missing context keyPath:%@ object:%@ change:%@", keyPath, object, change); + + _FBKVOInfo *info; + + { + // lookup context in registered infos, taking out a strong reference only if it exists + pthread_mutex_lock(&_mutex); + info = [_infos member:(__bridge id)context]; + pthread_mutex_unlock(&_mutex); + } + + if (nil != info) { + + // take strong reference to controller + FBKVOController *controller = info->_controller; + if (nil != controller) { + + // take strong reference to observer + id observer = controller.observer; + if (nil != observer) { + + // dispatch custom block or action, fall back to default action + if (info->_block) { + NSDictionary *changeWithKeyPath = change; + // add the keyPath to the change dictionary for clarity when mulitple keyPaths are being observed + if (keyPath) { + NSMutableDictionary *mChange = [NSMutableDictionary dictionaryWithObject:keyPath forKey:FBKVONotificationKeyPathKey]; + [mChange addEntriesFromDictionary:change]; + changeWithKeyPath = [mChange copy]; + } + info->_block(observer, object, changeWithKeyPath); + } else if (info->_action) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + [observer performSelector:info->_action withObject:change withObject:object]; +#pragma clang diagnostic pop + } else { + [observer observeValueForKeyPath:keyPath ofObject:object change:change context:info->_context]; + } + } + } + } +} + +@end + +#pragma mark FBKVOController - + +@implementation FBKVOController +{ + NSMapTable *> *_objectInfosMap; + pthread_mutex_t _lock; +} + +#pragma mark Lifecycle - + ++ (instancetype)controllerWithObserver:(nullable id)observer +{ + return [[self alloc] initWithObserver:observer]; +} + +- (instancetype)initWithObserver:(nullable id)observer retainObserved:(BOOL)retainObserved +{ + self = [super init]; + if (nil != self) { + _observer = observer; + NSPointerFunctionsOptions keyOptions = retainObserved ? NSPointerFunctionsStrongMemory|NSPointerFunctionsObjectPointerPersonality : NSPointerFunctionsWeakMemory|NSPointerFunctionsObjectPointerPersonality; + _objectInfosMap = [[NSMapTable alloc] initWithKeyOptions:keyOptions valueOptions:NSPointerFunctionsStrongMemory|NSPointerFunctionsObjectPersonality capacity:0]; + pthread_mutex_init(&_lock, NULL); + } + return self; +} + +- (instancetype)initWithObserver:(nullable id)observer +{ + return [self initWithObserver:observer retainObserved:YES]; +} + +- (void)dealloc +{ + [self unobserveAll]; + pthread_mutex_destroy(&_lock); +} + +#pragma mark Properties - + +- (NSString *)debugDescription +{ + NSMutableString *s = [NSMutableString stringWithFormat:@"<%@:%p", NSStringFromClass([self class]), self]; + [s appendFormat:@" observer:<%@:%p>", NSStringFromClass([_observer class]), _observer]; + + // lock + pthread_mutex_lock(&_lock); + + if (0 != _objectInfosMap.count) { + [s appendString:@"\n "]; + } + + for (id object in _objectInfosMap) { + NSMutableSet *infos = [_objectInfosMap objectForKey:object]; + NSMutableArray *infoDescriptions = [NSMutableArray arrayWithCapacity:infos.count]; + [infos enumerateObjectsUsingBlock:^(_FBKVOInfo *info, BOOL *stop) { + [infoDescriptions addObject:info.debugDescription]; + }]; + [s appendFormat:@"%@ -> %@", object, infoDescriptions]; + } + + // unlock + pthread_mutex_unlock(&_lock); + + [s appendString:@">"]; + return s; +} + +#pragma mark Utilities - + +- (void)_observe:(id)object info:(_FBKVOInfo *)info +{ + // lock + pthread_mutex_lock(&_lock); + + NSMutableSet *infos = [_objectInfosMap objectForKey:object]; + + // check for info existence + _FBKVOInfo *existingInfo = [infos member:info]; + if (nil != existingInfo) { + // observation info already exists; do not observe it again + + // unlock and return + pthread_mutex_unlock(&_lock); + return; + } + + // lazilly create set of infos + if (nil == infos) { + infos = [NSMutableSet set]; + [_objectInfosMap setObject:infos forKey:object]; + } + + // add info and oberve + [infos addObject:info]; + + // unlock prior to callout + pthread_mutex_unlock(&_lock); + + [[_FBKVOSharedController sharedController] observe:object info:info]; +} + +- (void)_unobserve:(id)object info:(_FBKVOInfo *)info +{ + // lock + pthread_mutex_lock(&_lock); + + // get observation infos + NSMutableSet *infos = [_objectInfosMap objectForKey:object]; + + // lookup registered info instance + _FBKVOInfo *registeredInfo = [infos member:info]; + + if (nil != registeredInfo) { + [infos removeObject:registeredInfo]; + + // remove no longer used infos + if (0 == infos.count) { + [_objectInfosMap removeObjectForKey:object]; + } + } + + // unlock + pthread_mutex_unlock(&_lock); + + // unobserve + [[_FBKVOSharedController sharedController] unobserve:object info:registeredInfo]; +} + +- (void)_unobserve:(id)object +{ + // lock + pthread_mutex_lock(&_lock); + + NSMutableSet *infos = [_objectInfosMap objectForKey:object]; + + // remove infos + [_objectInfosMap removeObjectForKey:object]; + + // unlock + pthread_mutex_unlock(&_lock); + + // unobserve + [[_FBKVOSharedController sharedController] unobserve:object infos:infos]; +} + +- (void)_unobserveAll +{ + // lock + pthread_mutex_lock(&_lock); + + NSMapTable *objectInfoMaps = [_objectInfosMap copy]; + + // clear table and map + [_objectInfosMap removeAllObjects]; + + // unlock + pthread_mutex_unlock(&_lock); + + _FBKVOSharedController *shareController = [_FBKVOSharedController sharedController]; + + for (id object in objectInfoMaps) { + // unobserve each registered object and infos + NSSet *infos = [objectInfoMaps objectForKey:object]; + [shareController unobserve:object infos:infos]; + } +} + +#pragma mark API - + +- (void)observe:(nullable id)object keyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options block:(FBKVONotificationBlock)block +{ + NSAssert(0 != keyPath.length && NULL != block, @"missing required parameters observe:%@ keyPath:%@ block:%p", object, keyPath, block); + if (nil == object || 0 == keyPath.length || NULL == block) { + return; + } + + // create info + _FBKVOInfo *info = [[_FBKVOInfo alloc] initWithController:self keyPath:keyPath options:options block:block]; + + // observe object with info + [self _observe:object info:info]; +} + + +- (void)observe:(nullable id)object keyPaths:(NSArray *)keyPaths options:(NSKeyValueObservingOptions)options block:(FBKVONotificationBlock)block +{ + NSAssert(0 != keyPaths.count && NULL != block, @"missing required parameters observe:%@ keyPath:%@ block:%p", object, keyPaths, block); + if (nil == object || 0 == keyPaths.count || NULL == block) { + return; + } + + for (NSString *keyPath in keyPaths) { + [self observe:object keyPath:keyPath options:options block:block]; + } +} + +- (void)observe:(nullable id)object keyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options action:(SEL)action +{ + NSAssert(0 != keyPath.length && NULL != action, @"missing required parameters observe:%@ keyPath:%@ action:%@", object, keyPath, NSStringFromSelector(action)); + NSAssert([_observer respondsToSelector:action], @"%@ does not respond to %@", _observer, NSStringFromSelector(action)); + if (nil == object || 0 == keyPath.length || NULL == action) { + return; + } + + // create info + _FBKVOInfo *info = [[_FBKVOInfo alloc] initWithController:self keyPath:keyPath options:options action:action]; + + // observe object with info + [self _observe:object info:info]; +} + +- (void)observe:(nullable id)object keyPaths:(NSArray *)keyPaths options:(NSKeyValueObservingOptions)options action:(SEL)action +{ + NSAssert(0 != keyPaths.count && NULL != action, @"missing required parameters observe:%@ keyPath:%@ action:%@", object, keyPaths, NSStringFromSelector(action)); + NSAssert([_observer respondsToSelector:action], @"%@ does not respond to %@", _observer, NSStringFromSelector(action)); + if (nil == object || 0 == keyPaths.count || NULL == action) { + return; + } + + for (NSString *keyPath in keyPaths) { + [self observe:object keyPath:keyPath options:options action:action]; + } +} + +- (void)observe:(nullable id)object keyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(nullable void *)context +{ + NSAssert(0 != keyPath.length, @"missing required parameters observe:%@ keyPath:%@", object, keyPath); + if (nil == object || 0 == keyPath.length) { + return; + } + + // create info + _FBKVOInfo *info = [[_FBKVOInfo alloc] initWithController:self keyPath:keyPath options:options context:context]; + + // observe object with info + [self _observe:object info:info]; +} + +- (void)observe:(nullable id)object keyPaths:(NSArray *)keyPaths options:(NSKeyValueObservingOptions)options context:(nullable void *)context +{ + NSAssert(0 != keyPaths.count, @"missing required parameters observe:%@ keyPath:%@", object, keyPaths); + if (nil == object || 0 == keyPaths.count) { + return; + } + + for (NSString *keyPath in keyPaths) { + [self observe:object keyPath:keyPath options:options context:context]; + } +} + +- (void)unobserve:(nullable id)object keyPath:(NSString *)keyPath +{ + // create representative info + _FBKVOInfo *info = [[_FBKVOInfo alloc] initWithController:self keyPath:keyPath]; + + // unobserve object property + [self _unobserve:object info:info]; +} + +- (void)unobserve:(nullable id)object +{ + if (nil == object) { + return; + } + + [self _unobserve:object]; +} + +- (void)unobserveAll +{ + [self _unobserveAll]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/Pods/KVOController/FBKVOController/KVOController.h b/Pods/KVOController/FBKVOController/KVOController.h new file mode 100644 index 00000000..910da2cd --- /dev/null +++ b/Pods/KVOController/FBKVOController/KVOController.h @@ -0,0 +1,11 @@ +/** + Copyright (c) 2014-present, Facebook, Inc. + All rights reserved. + + This source code is licensed under the BSD-style license found in the + LICENSE file in the root directory of this source tree. An additional grant + of patent rights can be found in the PATENTS file in the same directory. + */ + +#import +#import diff --git a/Pods/KVOController/FBKVOController/NSObject+FBKVOController.h b/Pods/KVOController/FBKVOController/NSObject+FBKVOController.h new file mode 100644 index 00000000..db38f922 --- /dev/null +++ b/Pods/KVOController/FBKVOController/NSObject+FBKVOController.h @@ -0,0 +1,42 @@ +/** + Copyright (c) 2014-present, Facebook, Inc. + All rights reserved. + + This source code is licensed under the BSD-style license found in the + LICENSE file in the root directory of this source tree. An additional grant + of patent rights can be found in the PATENTS file in the same directory. + */ + +#import + +#import "FBKVOController.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + Category that adds built-in `KVOController` and `KVOControllerNonRetaining` on any instance of `NSObject`. + + This makes it convenient to simply create and forget a `FBKVOController`, + and when this object gets dealloc'd, so will the associated controller and the observation info. + */ +@interface NSObject (FBKVOController) + +/** + @abstract Lazy-loaded FBKVOController for use with any object + @return FBKVOController associated with this object, creating one if necessary + @discussion This makes it convenient to simply create and forget a FBKVOController, and when this object gets dealloc'd, so will the associated controller and the observation info. + */ +@property (nonatomic, strong) FBKVOController *KVOController; + +/** + @abstract Lazy-loaded FBKVOController for use with any object + @return FBKVOController associated with this object, creating one if necessary + @discussion This makes it convenient to simply create and forget a FBKVOController. + Use this version when a strong reference between controller and observed object would create a retain cycle. + When not retaining observed objects, special care must be taken to remove observation info prior to deallocation of the observed object. + */ +@property (nonatomic, strong) FBKVOController *KVOControllerNonRetaining; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Pods/KVOController/FBKVOController/NSObject+FBKVOController.m b/Pods/KVOController/FBKVOController/NSObject+FBKVOController.m new file mode 100644 index 00000000..af601023 --- /dev/null +++ b/Pods/KVOController/FBKVOController/NSObject+FBKVOController.m @@ -0,0 +1,65 @@ +/** + Copyright (c) 2014-present, Facebook, Inc. + All rights reserved. + + This source code is licensed under the BSD-style license found in the + LICENSE file in the root directory of this source tree. An additional grant + of patent rights can be found in the PATENTS file in the same directory. + */ + +#import "NSObject+FBKVOController.h" + +#import + +#if !__has_feature(objc_arc) +#error This file must be compiled with ARC. Convert your project to ARC or specify the -fobjc-arc flag. +#endif + +#pragma mark NSObject Category - + +NS_ASSUME_NONNULL_BEGIN + +static void *NSObjectKVOControllerKey = &NSObjectKVOControllerKey; +static void *NSObjectKVOControllerNonRetainingKey = &NSObjectKVOControllerNonRetainingKey; + +@implementation NSObject (FBKVOController) + +- (FBKVOController *)KVOController +{ + id controller = objc_getAssociatedObject(self, NSObjectKVOControllerKey); + + // lazily create the KVOController + if (nil == controller) { + controller = [FBKVOController controllerWithObserver:self]; + self.KVOController = controller; + } + + return controller; +} + +- (void)setKVOController:(FBKVOController *)KVOController +{ + objc_setAssociatedObject(self, NSObjectKVOControllerKey, KVOController, OBJC_ASSOCIATION_RETAIN_NONATOMIC); +} + +- (FBKVOController *)KVOControllerNonRetaining +{ + id controller = objc_getAssociatedObject(self, NSObjectKVOControllerNonRetainingKey); + + if (nil == controller) { + controller = [[FBKVOController alloc] initWithObserver:self retainObserved:NO]; + self.KVOControllerNonRetaining = controller; + } + + return controller; +} + +- (void)setKVOControllerNonRetaining:(FBKVOController *)KVOControllerNonRetaining +{ + objc_setAssociatedObject(self, NSObjectKVOControllerNonRetainingKey, KVOControllerNonRetaining, OBJC_ASSOCIATION_RETAIN_NONATOMIC); +} + +@end + + +NS_ASSUME_NONNULL_END diff --git a/Pods/KVOController/LICENSE b/Pods/KVOController/LICENSE new file mode 100644 index 00000000..615de35c --- /dev/null +++ b/Pods/KVOController/LICENSE @@ -0,0 +1,30 @@ +BSD License + +For KVOController software + +Copyright (c) 2014, Facebook, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name Facebook nor the names of its contributors may be used to + endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Pods/KVOController/README.md b/Pods/KVOController/README.md new file mode 100644 index 00000000..f17574fc --- /dev/null +++ b/Pods/KVOController/README.md @@ -0,0 +1,84 @@ +# [KVOController](https://github.com/facebook/KVOController) +[![Build Status](https://img.shields.io/travis/facebook/KVOController/master.svg?style=flat)](https://travis-ci.org/facebook/KVOController) +[![Coverage Status](https://img.shields.io/codecov/c/github/facebook/KVOController/master.svg)](https://codecov.io/github/facebook/KVOController) +[![Version](https://img.shields.io/cocoapods/v/KVOController.svg?style=flat)](http://cocoadocs.org/docsets/KVOController) +[![Platform](https://img.shields.io/cocoapods/p/KVOController.svg?style=flat)](http://cocoadocs.org/docsets/KVOController) + +Key-value observing is a particularly useful technique for communicating between layers in a Model-View-Controller application. KVOController builds on Cocoa's time-tested key-value observing implementation. It offers a simple, modern API, that is also thread safe. Benefits include: + +- Notification using blocks, custom actions, or NSKeyValueObserving callback. +- No exceptions on observer removal. +- Implicit observer removal on controller dealloc. +- Thread-safety with special guards against observer resurrection – [rdar://15985376](http://openradar.appspot.com/radar?id=5305010728468480). + +For more information on KVO, see Apple's [Introduction to Key-Value Observing](https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/KeyValueObserving/KeyValueObserving.html). + +## Usage + +Example apps for iOS and OS X are included with the project. Here is one simple usage pattern: + +```objective-c +// create KVO controller with observer +FBKVOController *KVOController = [FBKVOController controllerWithObserver:self]; +self.KVOController = KVOController; + +// observe clock date property +[self.KVOController observe:clock keyPath:@"date" options:NSKeyValueObservingOptionInitial|NSKeyValueObservingOptionNew block:^(ClockView *clockView, Clock *clock, NSDictionary *change) { + + // update clock view with new value + clockView.date = change[NSKeyValueChangeNewKey]; +}]; +``` + +While simple, the above example is complete. A clock view creates a KVO controller to observe the clock date property. A block callback is used to handle initial and change notification. Unobservation happens implicitly on controller deallocation, since a strong reference to the `KVOController` is kept. + +Note: the observer specified must support weak references. The zeroing weak reference guards against notification of a deallocated observer instance. + +#### NSObject Category +For an even easier usage, just `#import ` for an automatic `KVOController` property on all objects. + +```objc +[self.KVOController observe:clock keyPath:@"date" options:NSKeyValueObservingOptionInitial|NSKeyValueObservingOptionNew action:@selector(updateClockWithDateChange:)]; +``` + +## Prerequisites + +KVOController takes advantage of recent Objective-C runtime advances, including ARC and weak collections. It requires: + +- iOS 6 or later. +- OS X 10.7 or later. + +## Installation + +To install using [CocoaPods](https://github.com/cocoapods/cocoapods), add the following to your project Podfile: + +```ruby +pod 'KVOController' +``` + +To install using [Carthage](https://github.com/carthage/carthage), add the following to your project Cartfile: + +``` +github "facebook/KVOController" +``` + +Alternatively, drag and drop FBKVOController.h and FBKVOController.m into your Xcode project, agreeing to copy files if needed. For iOS applications, you can choose to link against the static library target of the KVOController project. + +Having installed using CocoaPods or Carthage, add the following to import in Objective-C: +```objective-c +#import +``` + +## Testing + +The unit tests included use CocoaPods for managing dependencies. Install CocoaPods if you haven't already done so. Then, at the command line, navigate to the root KVOController directory and type: + +```sh +pod install +``` + +This will install and add test dependencies on OCHamcrest and OCMockito. Re-open the Xcode KVOController workspace and Test, ⌘U. + +## License + +KVOController is released under a BSD License. See LICENSE file for details. diff --git a/Pods/Local Podspecs/Eddystone.podspec.json b/Pods/Local Podspecs/Eddystone.podspec.json new file mode 100644 index 00000000..e292ef71 --- /dev/null +++ b/Pods/Local Podspecs/Eddystone.podspec.json @@ -0,0 +1,27 @@ +{ + "name": "Eddystone", + "version": "1.1.3", + "summary": "Explore Eddystone and the Physical Web", + "description": "Add Eddystone support to your app and start letting your users interact with Eddystone beacons and the Physical Web. This cocoapod will allow you to scan for Beacons broadcasting the Eddystone-URL, Eddystone-UID, and Eddystone-TLM protocol.", + "homepage": "https://github.com/BlueBiteLLC/Eddystone", + "license": "MIT", + "authors": { + "Tanner Nelson": "tanner@bluebite.com" + }, + "source": { + "git": "https://github.com/BlueBiteLLC/Eddystone.git", + "tag": "1.1.3" + }, + "social_media_url": "https://twitter.com/BlueBite", + "platforms": { + "ios": "8.0" + }, + "requires_arc": true, + "source_files": "Pod/Classes/**/*", + "resource_bundles": { + "Eddystone": [ + "Pod/Assets/*.png" + ] + }, + "frameworks": "CoreBluetooth" +} diff --git a/Pods/MZTimerLabel/LICENSE b/Pods/MZTimerLabel/LICENSE new file mode 100644 index 00000000..cd59cb57 --- /dev/null +++ b/Pods/MZTimerLabel/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2013 mineschan + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/Pods/MZTimerLabel/MZTimerLabel/MZTimerLabel.h b/Pods/MZTimerLabel/MZTimerLabel/MZTimerLabel.h new file mode 100644 index 00000000..5895aece --- /dev/null +++ b/Pods/MZTimerLabel/MZTimerLabel/MZTimerLabel.h @@ -0,0 +1,132 @@ +// +// MZTimerLabel.h +// Version 0.5.1 +// Created by MineS Chan on 2013-10-16 +// Updated 2014-12-15 + +// This code is distributed under the terms and conditions of the MIT license. + +// Copyright (c) 2014 MineS Chan +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#import + + +/********************************************** + MZTimerLabel TimerType Enum + **********************************************/ +typedef enum{ + MZTimerLabelTypeStopWatch, + MZTimerLabelTypeTimer +}MZTimerLabelType; + +/********************************************** + Delegate Methods + @optional + + - timerLabel:finshedCountDownTimerWithTimeWithTime: + ** MZTimerLabel Delegate method for finish of countdown timer + + - timerLabel:countingTo:timertype: + ** MZTimerLabel Delegate method for monitering the current counting progress + + - timerlabel:customTextToDisplayAtTime: + ** MZTimerLabel Delegate method for overriding the text displaying at the time, implement this for your very custom display formmat +**********************************************/ + +@class MZTimerLabel; +@protocol MZTimerLabelDelegate +@optional +-(void)timerLabel:(MZTimerLabel*)timerLabel finshedCountDownTimerWithTime:(NSTimeInterval)countTime; +-(void)timerLabel:(MZTimerLabel*)timerLabel countingTo:(NSTimeInterval)time timertype:(MZTimerLabelType)timerType; +-(NSString*)timerLabel:(MZTimerLabel*)timerLabel customTextToDisplayAtTime:(NSTimeInterval)time; +@end + +/********************************************** + MZTimerLabel Class Defination + **********************************************/ + +@interface MZTimerLabel : UILabel; + +/*Delegate for finish of countdown timer */ +@property (nonatomic,weak) id delegate; + +/*Time format wish to display in label*/ +@property (nonatomic,copy) NSString *timeFormat; + +/*Target label obejct, default self if you do not initWithLabel nor set*/ +@property (nonatomic,strong) UILabel *timeLabel; + +/*Used for replace text in range */ +@property (nonatomic, assign) NSRange textRange; + +@property (nonatomic, strong) NSDictionary *attributedDictionaryForTextInRange; + +/*Type to choose from stopwatch or timer*/ +@property (assign) MZTimerLabelType timerType; + +/*Is The Timer Running?*/ +@property (assign,readonly) BOOL counting; + +/*Do you want to reset the Timer after countdown?*/ +@property (assign) BOOL resetTimerAfterFinish; + +/*Do you want the timer to count beyond the HH limit from 0-23 e.g. 25:23:12 (HH:mm:ss) */ +@property (assign,nonatomic) BOOL shouldCountBeyondHHLimit; + +#if NS_BLOCKS_AVAILABLE +@property (copy) void (^endedBlock)(NSTimeInterval); +#endif + + +/*--------Init methods to choose*/ +-(id)initWithTimerType:(MZTimerLabelType)theType; +-(id)initWithLabel:(UILabel*)theLabel andTimerType:(MZTimerLabelType)theType; +-(id)initWithLabel:(UILabel*)theLabel; +/*--------designated Initializer*/ +-(id)initWithFrame:(CGRect)frame label:(UILabel*)theLabel andTimerType:(MZTimerLabelType)theType; + +/*--------Timer control methods to use*/ +-(void)start; +#if NS_BLOCKS_AVAILABLE +-(void)startWithEndingBlock:(void(^)(NSTimeInterval countTime))end; //use it if you are not going to use delegate +#endif +-(void)pause; +-(void)reset; + +/*--------Setter methods*/ +-(void)setCountDownTime:(NSTimeInterval)time; +-(void)setStopWatchTime:(NSTimeInterval)time; +-(void)setCountDownToDate:(NSDate*)date; + +-(void)addTimeCountedByTime:(NSTimeInterval)timeToAdd; + +/*--------Getter methods*/ +- (NSTimeInterval)getTimeCounted; +- (NSTimeInterval)getTimeRemaining; +- (NSTimeInterval)getCountDownTime; + + + + + +@end + + diff --git a/Pods/MZTimerLabel/MZTimerLabel/MZTimerLabel.m b/Pods/MZTimerLabel/MZTimerLabel/MZTimerLabel.m new file mode 100644 index 00000000..dbceafad --- /dev/null +++ b/Pods/MZTimerLabel/MZTimerLabel/MZTimerLabel.m @@ -0,0 +1,406 @@ +// +// MZTimerLabel.h +// Version 0.5.1 +// Created by MineS Chan on 2013-10-16 +// Updated 2014-12-15 + +// This code is distributed under the terms and conditions of the MIT license. + +// Copyright (c) 2014 MineS Chan +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#import "MZTimerLabel.h" + + +#define kDefaultTimeFormat @"HH:mm:ss" +#define kHourFormatReplace @"!!!*" +#define kDefaultFireIntervalNormal 0.1 +#define kDefaultFireIntervalHighUse 0.01 +#define kDefaultTimerType MZTimerLabelTypeStopWatch + +@interface MZTimerLabel(){ + + NSTimeInterval timeUserValue; + NSDate *startCountDate; + NSDate *pausedTime; + NSDate *date1970; + NSDate *timeToCountOff; +} + +@property (strong) NSTimer *timer; +@property (nonatomic,strong) NSDateFormatter *dateFormatter; + +- (void)setup; +- (void)updateLabel; + +@end + +#pragma mark - Initialize method + +@implementation MZTimerLabel + +@synthesize timeFormat = _timeFormat; + +- (id)initWithTimerType:(MZTimerLabelType)theType { + return [self initWithFrame:CGRectZero label:nil andTimerType:theType]; +} + +- (id)initWithLabel:(UILabel *)theLabel andTimerType:(MZTimerLabelType)theType { + return [self initWithFrame:CGRectZero label:theLabel andTimerType:theType]; +} + +- (id)initWithLabel:(UILabel*)theLabel { + return [self initWithFrame:CGRectZero label:theLabel andTimerType:kDefaultTimerType]; +} + +- (id)initWithFrame:(CGRect)frame { + return [self initWithFrame:frame label:nil andTimerType:kDefaultTimerType]; +} + +-(id)initWithFrame:(CGRect)frame label:(UILabel*)theLabel andTimerType:(MZTimerLabelType)theType { + self = [super initWithFrame:frame]; + if (self) { + self.timeLabel = theLabel; + self.timerType = theType; + [self setup]; + } + return self; +} + +- (id)initWithCoder:(NSCoder *)aDecoder +{ + self = [super initWithCoder:aDecoder]; + if (self) { + [self setup]; + } + return self; +} + +#pragma mark - Cleanup + +- (void) removeFromSuperview { + if (_timer) { + [_timer invalidate]; + _timer = nil; + } + + [super removeFromSuperview]; +} + +#pragma mark - Getter and Setter Method + +- (void)setStopWatchTime:(NSTimeInterval)time{ + + timeUserValue = (time < 0) ? 0 : time; + if(timeUserValue > 0){ + startCountDate = [[NSDate date] dateByAddingTimeInterval:-timeUserValue]; + pausedTime = [NSDate date]; + [self updateLabel]; + } +} + +- (void)setCountDownTime:(NSTimeInterval)time{ + + timeUserValue = (time < 0)? 0 : time; + timeToCountOff = [date1970 dateByAddingTimeInterval:timeUserValue]; + [self updateLabel]; +} + +-(void)setCountDownToDate:(NSDate*)date{ + NSTimeInterval timeLeft = (int)[date timeIntervalSinceDate:[NSDate date]]; + + if (timeLeft > 0) { + timeUserValue = timeLeft; + timeToCountOff = [date1970 dateByAddingTimeInterval:timeLeft]; + }else{ + timeUserValue = 0; + timeToCountOff = [date1970 dateByAddingTimeInterval:0]; + } + [self updateLabel]; + +} + +- (void)setTimeFormat:(NSString *)timeFormat{ + + if ([timeFormat length] != 0) { + _timeFormat = timeFormat; + self.dateFormatter.dateFormat = timeFormat; + } + [self updateLabel]; +} + +- (NSString*)timeFormat +{ + if ([_timeFormat length] == 0 || _timeFormat == nil) { + _timeFormat = kDefaultTimeFormat; + } + + return _timeFormat; +} + +- (NSDateFormatter*)dateFormatter{ + + if (_dateFormatter == nil) { + _dateFormatter = [[NSDateFormatter alloc] init]; + _dateFormatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_GB"]; + [_dateFormatter setTimeZone:[NSTimeZone timeZoneWithName:@"GMT"]]; + _dateFormatter.dateFormat = self.timeFormat; + } + return _dateFormatter; +} + +- (UILabel*)timeLabel +{ + if (_timeLabel == nil) { + _timeLabel = self; + } + return _timeLabel; +} + + +-(void)addTimeCountedByTime:(NSTimeInterval)timeToAdd +{ + if (_timerType == MZTimerLabelTypeTimer) { + [self setCountDownTime:timeToAdd + timeUserValue]; + }else if (_timerType == MZTimerLabelTypeStopWatch) { + NSDate *newStartDate = [startCountDate dateByAddingTimeInterval:-timeToAdd]; + if([[NSDate date] timeIntervalSinceDate:newStartDate] <= 0) { + //prevent less than 0 + startCountDate = [NSDate date]; + }else{ + startCountDate = newStartDate; + } + } + [self updateLabel]; +} + + +- (NSTimeInterval)getTimeCounted +{ + if(!startCountDate) return 0; + NSTimeInterval countedTime = [[NSDate date] timeIntervalSinceDate:startCountDate]; + + if(pausedTime != nil){ + NSTimeInterval pauseCountedTime = [[NSDate date] timeIntervalSinceDate:pausedTime]; + countedTime -= pauseCountedTime; + } + return countedTime; +} + +- (NSTimeInterval)getTimeRemaining { + + if (_timerType == MZTimerLabelTypeTimer) { + return timeUserValue - [self getTimeCounted]; + } + + return 0; +} + +- (NSTimeInterval)getCountDownTime { + + if (_timerType == MZTimerLabelTypeTimer) { + return timeUserValue; + } + + return 0; +} + +- (void)setShouldCountBeyondHHLimit:(BOOL)shouldCountBeyondHHLimit { + _shouldCountBeyondHHLimit = shouldCountBeyondHHLimit; + [self updateLabel]; +} + +#pragma mark - Timer Control Method + + +-(void)start{ + + if (_timer) { + [_timer invalidate]; + _timer = nil; + } + + if ([self.timeFormat rangeOfString:@"SS"].location != NSNotFound) { + _timer = [NSTimer scheduledTimerWithTimeInterval:kDefaultFireIntervalHighUse target:self selector:@selector(updateLabel) userInfo:nil repeats:YES]; + }else{ + _timer = [NSTimer scheduledTimerWithTimeInterval:kDefaultFireIntervalNormal target:self selector:@selector(updateLabel) userInfo:nil repeats:YES]; + } + [[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSRunLoopCommonModes]; + + if(startCountDate == nil){ + startCountDate = [NSDate date]; + + if (self.timerType == MZTimerLabelTypeStopWatch && timeUserValue > 0) { + startCountDate = [startCountDate dateByAddingTimeInterval:-timeUserValue]; + } + } + if(pausedTime != nil){ + NSTimeInterval countedTime = [pausedTime timeIntervalSinceDate:startCountDate]; + startCountDate = [[NSDate date] dateByAddingTimeInterval:-countedTime]; + pausedTime = nil; + } + + _counting = YES; + [_timer fire]; +} + +#if NS_BLOCKS_AVAILABLE +-(void)startWithEndingBlock:(void(^)(NSTimeInterval))end{ + self.endedBlock = end; + [self start]; +} +#endif + +-(void)pause{ + if(_counting){ + [_timer invalidate]; + _timer = nil; + _counting = NO; + pausedTime = [NSDate date]; + } +} + +-(void)reset{ + pausedTime = nil; + timeUserValue = (self.timerType == MZTimerLabelTypeStopWatch)? 0 : timeUserValue; + startCountDate = (self.counting)? [NSDate date] : nil; + [self updateLabel]; +} + + +#pragma mark - Private method + +-(void)setup{ + date1970 = [NSDate dateWithTimeIntervalSince1970:0]; + [self updateLabel]; +} + + +-(void)updateLabel{ + + NSTimeInterval timeDiff = [[NSDate date] timeIntervalSinceDate:startCountDate]; + NSDate *timeToShow = [NSDate date]; + BOOL timerEnded = false; + + /***MZTimerLabelTypeStopWatch Logic***/ + + if(_timerType == MZTimerLabelTypeStopWatch){ + + if (_counting) { + timeToShow = [date1970 dateByAddingTimeInterval:timeDiff]; + }else{ + timeToShow = [date1970 dateByAddingTimeInterval:(!startCountDate)?0:timeDiff]; + } + + if([_delegate respondsToSelector:@selector(timerLabel:countingTo:timertype:)]){ + [_delegate timerLabel:self countingTo:timeDiff timertype:_timerType]; + } + + }else{ + + /***MZTimerLabelTypeTimer Logic***/ + + if (_counting) { + + if([_delegate respondsToSelector:@selector(timerLabel:countingTo:timertype:)]){ + NSTimeInterval timeLeft = timeUserValue - timeDiff; + [_delegate timerLabel:self countingTo:timeLeft timertype:_timerType]; + } + + if(timeDiff >= timeUserValue){ + [self pause]; + timeToShow = [date1970 dateByAddingTimeInterval:0]; + startCountDate = nil; + timerEnded = true; + }else{ + timeToShow = [timeToCountOff dateByAddingTimeInterval:(timeDiff*-1)]; //added 0.999 to make it actually counting the whole first second + } + + }else{ + timeToShow = timeToCountOff; + } + } + + //setting text value + if ([_delegate respondsToSelector:@selector(timerLabel:customTextToDisplayAtTime:)]) { + NSTimeInterval atTime = (_timerType == MZTimerLabelTypeStopWatch) ? timeDiff : ((timeUserValue - timeDiff) < 0 ? 0 : (timeUserValue - timeDiff)); + NSString *customtext = [_delegate timerLabel:self customTextToDisplayAtTime:atTime]; + if ([customtext length]) { + self.timeLabel.text = customtext; + }else{ + self.timeLabel.text = [self.dateFormatter stringFromDate:timeToShow]; + } + }else{ + + if(_shouldCountBeyondHHLimit) { + //0.4.7 added---start// + NSString *originalTimeFormat = _timeFormat; + NSString *beyondFormat = [_timeFormat stringByReplacingOccurrencesOfString:@"HH" withString:kHourFormatReplace]; + beyondFormat = [beyondFormat stringByReplacingOccurrencesOfString:@"H" withString:kHourFormatReplace]; + self.dateFormatter.dateFormat = beyondFormat; + + int hours = (_timerType == MZTimerLabelTypeStopWatch)? ([self getTimeCounted] / 3600) : ([self getTimeRemaining] / 3600); + NSString *formmattedDate = [self.dateFormatter stringFromDate:timeToShow]; + NSString *beyondedDate = [formmattedDate stringByReplacingOccurrencesOfString:kHourFormatReplace withString:[NSString stringWithFormat:@"%02d",hours]]; + + self.timeLabel.text = beyondedDate; + self.dateFormatter.dateFormat = originalTimeFormat; + //0.4.7 added---endb// + }else{ + if(self.textRange.length > 0){ + if(self.attributedDictionaryForTextInRange){ + + NSAttributedString *attrTextInRange = [[NSAttributedString alloc] initWithString:[self.dateFormatter stringFromDate:timeToShow] attributes:self.attributedDictionaryForTextInRange]; + + NSMutableAttributedString *attributedString; + attributedString = [[NSMutableAttributedString alloc]initWithString:self.text]; + [attributedString replaceCharactersInRange:self.textRange withAttributedString:attrTextInRange]; + self.timeLabel.attributedText = attributedString; + + } else { + NSString *labelText = [self.text stringByReplacingCharactersInRange:self.textRange withString:[self.dateFormatter stringFromDate:timeToShow]]; + self.timeLabel.text = labelText; + } + } else { + self.timeLabel.text = [self.dateFormatter stringFromDate:timeToShow]; + } + } + } + + //0.5.1 moved below to the bottom + if(timerEnded) { + if([_delegate respondsToSelector:@selector(timerLabel:finshedCountDownTimerWithTime:)]){ + [_delegate timerLabel:self finshedCountDownTimerWithTime:timeUserValue]; + } + +#if NS_BLOCKS_AVAILABLE + if(_endedBlock != nil){ + _endedBlock(timeUserValue); + } +#endif + if(_resetTimerAfterFinish){ + [self reset]; + } + + } + +} + +@end diff --git a/Pods/MZTimerLabel/README.md b/Pods/MZTimerLabel/README.md new file mode 100644 index 00000000..3c732d6c --- /dev/null +++ b/Pods/MZTimerLabel/README.md @@ -0,0 +1,172 @@ +MZTimerLabel +============ + + +![License](https://cocoapod-badges.herokuapp.com/l/MZTimerLabel/badge.(png|svg)) +![Platforms](https://cocoapod-badges.herokuapp.com/p/MZTimerLabel/badge.png) +[![Cocoapod Latest Version](http://img.shields.io/cocoapods/v/MZTimerLabel.svg?style=flat)](https://cocoapods.org/?q=MZTimerLabel) +[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) + +ScreenShot +ScreenShot2 + +###Purpose + +MZTimerLabel is a UILabel subclass, which is a handy way to use UILabel as a countdown timer or stopwatch just like that in Apple Clock App with just __2 lines of code__. MZTimerLabel also provides delegate method for you to define the action when the timer finished. + +Author: [MineS Chan](https://github.com/mineschan/) and awesome [contributors](https://github.com/mineschan/MZTimerLabel/graphs/contributors). + +_Remark: This is my first iOS plugin project on github, please accept my apologize if any bad coding._ + +###Requirements +* ARC +* iOS 5.0+ + +###Installations + +####Manual + +1. Download or clone MZTimerLabel, add `MZTimerLabel.h` and `MZTimerLabel.m` source files into your project. +2. `#import "MZTimerLabel.h"` whereever you need it. + +####CocoaPods + +(Unfamiliar with [CocoaPods](http://cocoapods.org/) yet? It's a dependency management tool for iOS and Mac, check it out!) + +1. Add `pod 'MZTimerLabel'` to your podfiles + +####Carthage +Another dependency manager is [Carthage](http://github.com/Carthage/Carthage), which does not have a centralized repository. + +1. Add `github "mineschan/MZTimerLabel"` to your `Cartfile` + +###Easy Example + +To use MZTimerLabel as a stopwatch and counter, you need only __2 lines__. + ```objective-c + MZTimerLabel *stopwatch = [[MZTimerLabel alloc] initWithLabel:aUILabel]; + [stopwatch start]; + ``` + +Easy? If you are looking for a timer, things is just similar. + ```objective-c + MZTimerLabel *timer = [[MZTimerLabel alloc] initWithLabel:aUILabel andTimerType:MZTimerLabelTypeTimer]; + [timer setCountDownTime:60]; + [timer start]; + ``` + +Now the timer will start counting from 60 to 0 ;) + +###Custom Appearance + +As MZTimerLabel is a UILabel subclass, you can directly allocate it as a normal UILabel and customize `timeLabel` property just like usual. + + ```objective-c + MZTimerLabel *redStopwatch = [[MZTimerLabel alloc] init]; + redStopwatch.frame = CGRectMake(100,50,100,20); + redStopwatch.timeLabel.font = [UIFont systemFontOfSize:20.0f]; + redStopwatch.timeLabel.textColor = [UIColor redColor]; + [self.view addSubview:redStopwatch]; + [redStopwatch start]; + ``` + +MZTimerLabel uses `00:00:00 (HH:mm:ss)` as time format, if you prefer using another format such as including milliseconds.Your can set your time format like below. + +`timerExample4.timeFormat = @"HH:mm:ss SS";` + + + +###Control the timer + +You can start,pause,reset your timer with your custom control, set your control up and call these methods: + +``` +-(void)start; +-(void)pause; +-(void)reset; +``` + +#### Getter and Setters + +You may control the time value and behaviours at the begining or during runtime with these properties and methods + +``` +@property (assign) BOOL shouldCountBeyondHHLimit; //see example #12 +@property (assign) BOOL resetTimerAfterFinish; //see example #7 + +-(void)setCountDownTime:(NSTimeInterval)time; +-(void)setStopWatchTime:(NSTimeInterval)time; +-(void)setCountDownToDate:(NSDate*)date; +-(void)addTimeCountedByTime:(NSTimeInterval)timeToAdd; //see example #10, #11 +``` + +And if you want to have information of the timer, here is how. + +``` +@property (assign,readonly) BOOL counting; //see example #4-7 + +- (NSTimeInterval)getTimeCounted; //see example #3 +- (NSTimeInterval)getTimeRemaining; //see example #3 +- (NSTimeInterval)getCountDownTime; +``` + +###Timer Finish Handling + +Usually when you need a timer, you need to deal with it after it finished. Following are 2 examples showing how to do it using `delegate` and `block` methods. + +####Delegate + +First, set the delegate of the timer label. + +`timer.delegate = self;` + +And then implement `MZTimerLabelDelegate` protocol in your dedicated class + +`@interface ViewController : UIViewController` + +Finally, implement the delegate method `timerLabel:finshedCountDownTimerWithTimeWithTime:` + + ```objective-c + -(void)timerLabel:(MZTimerLabel*)timerLabel finshedCountDownTimerWithTime:(NSTimeInterval)countTime{ + //time is up, what should I do master? + } + ``` + +####Blocks + + Block is a very convenient way to handle the callbacks, MZTimerLabel makes your life even easier. + + ```objective-c + + MZTimerLabel *timer = [[MZTimerLabel alloc] initWithLabel:aUILabel andTimerType:MZTimerLabelTypeTimer]; + [timer3 setCountDownTime:60]; + [timer startWithEndingBlock:^(NSTimeInterval countTime) { + //oh my gosh, it's awesome!! + }]; + + ``` + + Or set it seperately + + ``` + [timer3 setCountDownTime:60]; + timer.endedBlock = ^(NSTimeInterval countTime) { + //oh my gosh, it's awesome!! + }; + [timer start]; +``` + + +###More Examples + +Please check the demo project I provided, with well explained example code inside. + +###License +This code is distributed under the terms and conditions of the [MIT license](LICENSE). + + +### What's coming up next? + +1. ~~Submit to CocaPods~~ +2. ~~Better performance.~~ +3. __Your suggestions!:D__ diff --git a/Pods/Manifest.lock b/Pods/Manifest.lock new file mode 100644 index 00000000..24dbd3f7 --- /dev/null +++ b/Pods/Manifest.lock @@ -0,0 +1,73 @@ +PODS: + - ActionSheetPicker-3.0 (2.3.0) + - ChameleonFramework (2.1.0): + - ChameleonFramework/Default (= 2.1.0) + - ChameleonFramework/Default (2.1.0) + - Charts (3.3.0): + - Charts/Core (= 3.3.0) + - Charts/Core (3.3.0) + - Eddystone (1.1.3) + - IP-UIKit-Wisdom (0.0.10) + - KVOController (1.2.0) + - MZTimerLabel (0.5.4) + - PureLayout (3.1.4) + - SVProgressHUD (2.2.5) + - UICircularProgressRing (4.1.0) + - WYPopoverController (0.2.2) + - XMLDictionary (1.4.1) + +DEPENDENCIES: + - ActionSheetPicker-3.0 (~> 2.3.0) + - ChameleonFramework (~> 2.1.0) + - Charts (~> 3.3.0) + - Eddystone (from `https://github.com/IntrepidPursuits/eddystone-ios.git`, branch `nservidio/add-properties-to-Generic`) + - IP-UIKit-Wisdom (~> 0.0.10) + - KVOController (~> 1.2.0) + - MZTimerLabel (~> 0.5.4) + - PureLayout (~> 3.1.4) + - SVProgressHUD (~> 2.2.5) + - UICircularProgressRing (~> 4.1.0) + - WYPopoverController (~> 0.2.2) + - XMLDictionary (~> 1.4.1) + +SPEC REPOS: + https://github.com/cocoapods/specs.git: + - ActionSheetPicker-3.0 + - ChameleonFramework + - Charts + - IP-UIKit-Wisdom + - KVOController + - MZTimerLabel + - PureLayout + - SVProgressHUD + - UICircularProgressRing + - WYPopoverController + - XMLDictionary + +EXTERNAL SOURCES: + Eddystone: + :branch: nservidio/add-properties-to-Generic + :git: https://github.com/IntrepidPursuits/eddystone-ios.git + +CHECKOUT OPTIONS: + Eddystone: + :commit: ecbaed68ff82aecc82a52671fae17552658c2b8d + :git: https://github.com/IntrepidPursuits/eddystone-ios.git + +SPEC CHECKSUMS: + ActionSheetPicker-3.0: eef157d75e151f255c5333d26656c7fbfe905a51 + ChameleonFramework: d21a3cc247abfe5e37609a283a8238b03575cf64 + Charts: ec1f57f9340054155691e84d4544a1d239d382c5 + Eddystone: a56b4cb97540f43617d6fc488a9ff75eab1d66a4 + IP-UIKit-Wisdom: b395a065344071b33659e5f6b918043a97c48a44 + KVOController: d72ace34afea42468329623b3379ab3cd1d286b6 + MZTimerLabel: cd9bfb9304540ef2a9e163384fca9c978f0dbf83 + PureLayout: f08c01b8dec00bb14a1fefa3de4c7d9c265df85e + SVProgressHUD: 1428aafac632c1f86f62aa4243ec12008d7a51d6 + UICircularProgressRing: 5a32c01f54474571b1e66e8fa050c0f83d6d981b + WYPopoverController: 00d879c25bddd1fd873dcc21aa98c8308d7f1555 + XMLDictionary: fa07b6ff422b3a91d47a5de9bc82e3fc04fbd167 + +PODFILE CHECKSUM: 7d5b07fdc804b56a2f03fb911c3d79b3485319a5 + +COCOAPODS: 1.5.3 diff --git a/Pods/Pods.xcodeproj/project.pbxproj b/Pods/Pods.xcodeproj/project.pbxproj new file mode 100644 index 00000000..ab2e9eeb --- /dev/null +++ b/Pods/Pods.xcodeproj/project.pbxproj @@ -0,0 +1,4296 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 005B70F9BE90730CC4DD68BF32E6C20A /* MZTimerLabel-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 2CB215F35A867E9CF61FC553B61D4F6D /* MZTimerLabel-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 010278E0BBEA52A0CB768888480E3E04 /* UICircularProgressRing.h in Headers */ = {isa = PBXBuildFile; fileRef = B14F5C11BC82C3487CE61453DCC8D7D3 /* UICircularProgressRing.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0278661ACDCCBB9A7D56C0FFB3E431FB /* UICircularProgressRingStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36958433D03531713561115D14A4B289 /* UICircularProgressRingStyle.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 03C332CE48CE563BE34889A93661197B /* Legend.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C94721C4A0B4B47781D9AA1C5DF1ACF /* Legend.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 04DC3AB008D664C94B53378D92A8357C /* ActionSheetDatePicker.h in Headers */ = {isa = PBXBuildFile; fileRef = AB4339FE933969A2E75A32AA820C00E0 /* ActionSheetDatePicker.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0523419917399AD061A8590C49C94419 /* BubbleChartData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A1A4ADB688FA25351F308695E3392F7 /* BubbleChartData.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 084CAE071F5CA81328307F56DBEEFA85 /* Pods-BlueGecko-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 445B3D0F1F70C467F508C347E6ECC326 /* Pods-BlueGecko-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 092011BD13C259D986642B5A842CF997 /* CombinedChartData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C7BEF7AED5E42ED9B4819573519C515 /* CombinedChartData.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 0A614755B0258F2C584D57BAF43245E0 /* ScatterChartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FCEC7ED703FE901FF913298159DEA0C /* ScatterChartView.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 0B58249E18BC6B5059BA58BF1F41ACB8 /* ActionSheetLocalePicker.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD65FD699B7A177648422A2B1CA70EE /* ActionSheetLocalePicker.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0BCB4BFFCBDAC83FF711E9AE95E74615 /* TlmFrame.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A6266FA2DC2B84E6EB17221047CB303 /* TlmFrame.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 0C10CFAB9497E8E5D011C8AFFE4008C4 /* IP-UIKit-Wisdom-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = FCF3202267AD590E1B2762F7D9B6C11F /* IP-UIKit-Wisdom-dummy.m */; }; + 0C153F4A8B82DC9EA5E04215CD3415B2 /* NSTimeIntervalExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3B3DB6838440E7C8960A0A9210CE16C /* NSTimeIntervalExtensions.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 0C2D47415AE6B9354BAE3B627A92142E /* ChartDataProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = E95C06D092FED1A9E0156EC26035A130 /* ChartDataProvider.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 0DEE8FE78BFA6837741490D5AE7E70D3 /* ActionSheetCustomPickerDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 67949A93DA0CE3246D1073C194798C1D /* ActionSheetCustomPickerDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0ED96EFE059D12B6AC01346B2F85ECDC /* MarkerImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97E5B70FBD11A68B3A9CD66E057AB5BC /* MarkerImage.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 10422A83E5E7CE748FEC304F9910EE7F /* DefaultAxisValueFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = FECB9375AFB533BCE9A3B5294FE6EBC9 /* DefaultAxisValueFormatter.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 10D4EFE38FFFE3C7F222D35B62E728ED /* ActionSheetDatePicker.m in Sources */ = {isa = PBXBuildFile; fileRef = 800785DCA911E2E3AE42AD4A0A4F1EC6 /* ActionSheetDatePicker.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0 -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 11955C722AC0851FA9B22BECF682E504 /* Eddystone.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 570A1B1BC5E57682C35D8D67DA876885 /* Eddystone.bundle */; }; + 11C0446A534BD7B800C6E756CFE527A7 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4E872B141543C04195F4AA6253DCB46A /* Foundation.framework */; }; + 120700249562CDA7600D877DC70FAA25 /* ChevronUpShapeRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF397E288BBA899C89859AE01F8425AE /* ChevronUpShapeRenderer.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 1374ABF417D13A2D8EFEAFFC359F4E08 /* ChartData.swift in Sources */ = {isa = PBXBuildFile; fileRef = BEF29C0A3B8D72102653C7E6B6C8ABC9 /* ChartData.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 13BCBF3CEA918A8C633835213BA3029D /* BarChartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80ACA67493C63D6EE695846006AA65D9 /* BarChartView.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 1418477303438487238188481990757F /* ScatterChartData.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBFA07FF80A69AF7BC4D8F64CB3CD59E /* ScatterChartData.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 15E5AD179F758E805959ED9B862CB5BC /* Frame.swift in Sources */ = {isa = PBXBuildFile; fileRef = 86776919F26940B88993D5676026EB2B /* Frame.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 1686B7ED74B5905B476E93FE2E1BC5EE /* Pods-WirelessGecko-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = B1695C077A2B000F61B2346A16513BBD /* Pods-WirelessGecko-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 16D3DB873C209F7BF08A69B9B4433518 /* IValueFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = C45F3EF251E12C20F8057B0A78C04B8D /* IValueFormatter.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 18664D7207318ABD018F139B52543492 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4B50C7A6F17A840A6331420D07FD52E /* CoreGraphics.framework */; }; + 1DC710267366A3FD3BE4FA152EFD6EE9 /* PureLayout-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 176C4897F7F7A432B12A37BB4CC52EC6 /* PureLayout-dummy.m */; }; + 1F05F6D0C5B42853B61057FF1D2EEBF4 /* IMarker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 902543F7869A31661B0AC19E3C9AE9C6 /* IMarker.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 201D14A4C9331751467DB4BF157315B4 /* PieChartDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7C4D7A7A0FCF2F95A58B32C9FF20AEC /* PieChartDataSet.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 206F95434CF9EB75353E74C4BB9C571B /* UIView+NibInitable.m in Sources */ = {isa = PBXBuildFile; fileRef = D8996CEC882A79A5A5BE3418FB9E0EF2 /* UIView+NibInitable.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0 -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 20DF05B97A06AE53FAC46AEF64C38C9B /* CircleShapeRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C1D93D382918BCF3CA502D4F94AAAA5 /* CircleShapeRenderer.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 242EF6A41F451AE94E70F6D3865B2115 /* PureLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = AFE0F36C767EFA0FC72A2FAF6F6A69AC /* PureLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 24A15054FA9AD80E158C00F36CD10E9B /* UIViewController+Chameleon.m in Sources */ = {isa = PBXBuildFile; fileRef = 96DC2C89C66682D28AC10AB157F59C00 /* UIViewController+Chameleon.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 24EA7AADDF4DEB2C5803988A52AA3034 /* KVOController.h in Headers */ = {isa = PBXBuildFile; fileRef = 86A10CA50571306393F36FAD321FD71B /* KVOController.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 259E5C8AE4AD8BC8C9FB88460A605B81 /* Highlight.swift in Sources */ = {isa = PBXBuildFile; fileRef = F277DCA16CD08392ACBAA96448BBC7D4 /* Highlight.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 262CBA8BDB05D437E3228708E7C31451 /* Pods-BlueGeckoWithHomeKit-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = E24F2FE0868E027D230A6740354DF31B /* Pods-BlueGeckoWithHomeKit-dummy.m */; }; + 2662F6DE516DD05C48FFAC5B6CF7DAF7 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4E872B141543C04195F4AA6253DCB46A /* Foundation.framework */; }; + 2711C9950721F9F90A0F4D521C730669 /* LineChartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5261E962563940D18C492010A79DDBE /* LineChartView.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 2716A86BD9C6CFE03AC4E43024380CCD /* ChartDataEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC175F823BE751179FE17865635FD1A4 /* ChartDataEntry.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 27744A9BE9F4E1D629F27C9C0B2CA0EB /* Uid.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CA40134452942E2A6CCCC7C47BCDE6E /* Uid.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 279E4BCBF03C84B851A63B48DBFE6884 /* UIImage+ColorMaskedImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 56F8646F89CBE3CC0FF913D2B1B52E8A /* UIImage+ColorMaskedImage.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0 -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 28E5726B8CB0E98A529EA111FA82B672 /* SVProgressHUD-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 6BB8DF922263956771255F26D1DF0ABD /* SVProgressHUD-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 2A5B8D6DE57B4AA3CEF0B365282AE019 /* HorizontalBarChartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11E6DB3330CBDD52707CDF6E1C33A283 /* HorizontalBarChartView.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 2C2C310BA513CB6FCC892407531A515F /* IndexAxisValueFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAE4D25A498A6C786D1C24C7371CB396 /* IndexAxisValueFormatter.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 2D178BC8412501794934B2C13AD6FE0B /* BarChartData.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1CBDF8C87B269DA8720E3DCBF935D85 /* BarChartData.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 2DA0045270F2FE8718E7366D1CFC01B2 /* AbstractActionSheetPicker.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2F8F42E69A19C4EA3F859F7A0F512A /* AbstractActionSheetPicker.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0 -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 2E2100236D2D416E636F93BD7C42EAAD /* ZoomViewJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = C974CC9984A7E1EEC9FC46D0F06A7A38 /* ZoomViewJob.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 2E718BB83D6D450CB4A00C3C8E80221E /* NSArray+Chameleon.h in Headers */ = {isa = PBXBuildFile; fileRef = 1CD1F5A0BC106C02AC57A8F494FA748F /* NSArray+Chameleon.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 31306D0B409E67CD2CA7D20932999D05 /* ILineScatterCandleRadarChartDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15D70592F205341C68F9571682E433E7 /* ILineScatterCandleRadarChartDataSet.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 3177D9AAD46AADF1B22E17E8C764B47D /* NSObject+FBKVOController.h in Headers */ = {isa = PBXBuildFile; fileRef = B92F13E1729CF4C443C0733ACC1626CB /* NSObject+FBKVOController.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 31AD1217C2BD4F460EE4F7C577A9BEE7 /* Platform.swift in Sources */ = {isa = PBXBuildFile; fileRef = D543986FAD2C7E8031D36DBA0AD3D1C3 /* Platform.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 32DFD092F9BE0BDE0D4DEEA84E713D4F /* UIColor+Chameleon.h in Headers */ = {isa = PBXBuildFile; fileRef = 05AAE3AC4D5202C769F162FEF75D2E8B /* UIColor+Chameleon.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 337D6A47FE93CE6CF2012C62824DE835 /* Url.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E43803662EE53000A57538DAA5A6B70 /* Url.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 33FF9B2BEC508A588DCB31462B7306A0 /* ActionSheetMultipleStringPicker.m in Sources */ = {isa = PBXBuildFile; fileRef = D6CAA76B33E404D17DCA3072BE4BE355 /* ActionSheetMultipleStringPicker.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0 -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 377F167BDAB0482CE83004E98F086F82 /* ScatterChartRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = B170548C418591605F95F0166769ECEF /* ScatterChartRenderer.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 3813534CDF6D03A333E4624D011DD887 /* BarLineScatterCandleBubbleRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A9984E2583E990609E9322A2CAB42C6 /* BarLineScatterCandleBubbleRenderer.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 386D90589762A4FD681E22DE927F86F5 /* MoveViewJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = 432C3FC422E42C5D6C5E28256E4968B7 /* MoveViewJob.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 3873106BA37978286AD9F211E1179A84 /* UITableView+Utils.h in Headers */ = {isa = PBXBuildFile; fileRef = E890C33AFCECA497B8CB5ABEF758FECD /* UITableView+Utils.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3AC69C422C561D15607B45558F50EE05 /* Charts-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = DD48BB50FD2F678163C6BF95A2E107EA /* Charts-dummy.m */; }; + 3ACBEC5B851B694C829A666899BA0490 /* IRadarChartDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 16CDC0EC422748B94114F308A908E51E /* IRadarChartDataSet.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 3AFFB565BBE38E813794E136B9F07832 /* UILabel+Chameleon.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C12CA761777232CB084C77ECD8F64D2 /* UILabel+Chameleon.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3D9C7B78E9C34E2B37D15A0C1724638E /* FBKVOController.h in Headers */ = {isa = PBXBuildFile; fileRef = BD285263C7058B6A5238144A6D51AF21 /* FBKVOController.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3DFEDD8DA551D14D5C1EDA8E8CD95EF9 /* UINavigationController+Chameleon.h in Headers */ = {isa = PBXBuildFile; fileRef = 336BA1494AA67B6F791FF4FB3AF34FB2 /* UINavigationController+Chameleon.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 400D2652B78FA1A8C4060EB5E7A855EB /* LineChartDataProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96919220F12F29935EABD3E47DEC7444 /* LineChartDataProvider.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 403C5D9AAD792C6FAFFE3961911E5162 /* ActionSheetStringPicker.m in Sources */ = {isa = PBXBuildFile; fileRef = 78CFE7161B732D7100419480AF27DF04 /* ActionSheetStringPicker.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0 -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 4163B8B1DA697452C9B9263EB3881F4F /* ILineRadarChartDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7477A476ADD5E869E1A4B11E8186721E /* ILineRadarChartDataSet.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 420356FB05B461AD4BA9959E5371ACF4 /* IShapeRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1EAAAF5D5A1A5776B31EB0FA5C0E0F4E /* IShapeRenderer.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 420C6EBE96BE76B50666F337BF251E61 /* UIImage+ColorMaskedImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 4D7285B8C5720CD543F416409A3B443E /* UIImage+ColorMaskedImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 424B6359A6CAD01698B3BCBB378ADEC4 /* PureLayout+Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = CE826E34150BE5022DF9B502C9A90972 /* PureLayout+Internal.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 428403E1C426C8A0034067E3720CFC9C /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4E872B141543C04195F4AA6253DCB46A /* Foundation.framework */; }; + 42C6EAB75A829100C4E9D59D5F7C23A1 /* IP-UIKit-Wisdom-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = E5C99345C40FE98B4270E8A2E48AE48D /* IP-UIKit-Wisdom-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 42C9F91772B66FD0D9960D4BC331E9BD /* UIView+IPAncestry.h in Headers */ = {isa = PBXBuildFile; fileRef = 406BF982BD3C5E9EEE3123C9441A7E73 /* UIView+IPAncestry.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 431DFD0E3CD1671726DC33F6650FE4C7 /* Transformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2DA037E74E22ECED19872F41B8DFB61 /* Transformer.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 442177EFE00C04905F9911A2ECE5526F /* RadarChartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BEC0C0F6DDF9F7DD405020FCAB4AA5FA /* RadarChartView.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 465287E08F63302BA3C1784CC76A68BF /* SVProgressHUD.bundle in Resources */ = {isa = PBXBuildFile; fileRef = CD74EF71D2FD41F0B37F068EFDCB49FC /* SVProgressHUD.bundle */; }; + 47DD648261705696CD717E721480E312 /* PureLayout-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 944AE29058BAC80AB15D436CE874AFFF /* PureLayout-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 488FDC230E98EA6720F64014FD063FB3 /* NSLayoutConstraint+PureLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = F6250A58A1D3A73FCFDB3397BB0BD028 /* NSLayoutConstraint+PureLayout.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 48C2284F5ACCBC817C5A01C6D02D2F65 /* Charts-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = A6818EA23B9838465296147045EB0FE9 /* Charts-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4933A386D37EC2D1D2BE8B99724F0962 /* UIColor+Chameleon.m in Sources */ = {isa = PBXBuildFile; fileRef = E60CC74084D7EA7D9F5DFABA2EC2427A /* UIColor+Chameleon.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 4972D596D54D5CCEC57DFA1EAECEC630 /* ICandleChartDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93151302C6ACEE98EA43A21A83585A38 /* ICandleChartDataSet.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 4B4EDA65A6E6FAE8B37BA47B53A3C7E3 /* DataApproximator+N.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4CA7F046A7C0B76968EE081A003297E /* DataApproximator+N.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 4C4A18F2AA41A8E7654F4A51F6C10C62 /* CAGradientLayer+IPGradients.h in Headers */ = {isa = PBXBuildFile; fileRef = 5EC623EFD593FF4960B3618BE14F5630 /* CAGradientLayer+IPGradients.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4D033F63E586719C6DD61DC0D16DAD5E /* XAxisRendererHorizontalBarChart.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FE53421F581B66DF6A0AF5505042A96 /* XAxisRendererHorizontalBarChart.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 4D24FC0EF43B398C4F35E15A255C9DD4 /* PieHighlighter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77AA3DA113378A3CD340D07AF9878B77 /* PieHighlighter.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 4F2ADB5162BDB173B960EC455FFC76D1 /* WYPopoverController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D48BFF0B5781A3D1EAEDF2A6C3D6B81 /* WYPopoverController.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 4FAC92B47BCF4935FB5BE481B54A439D /* NSArray+PureLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 54663D619A0D3881CE170F7EE40A8CF9 /* NSArray+PureLayout.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 508547AFDF31532896F7859DA75FB625 /* XMLDictionary-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 18C3F75647C4C195F26341298A87A180 /* XMLDictionary-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 523BE7D997AF9E44B95AF4A696B37815 /* CAGradientLayer+IPGradients.m in Sources */ = {isa = PBXBuildFile; fileRef = 0229BF4F30B91B908D0DDBB40F9D9D31 /* CAGradientLayer+IPGradients.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0 -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 5327D9E9061239D9A5218F343DB785DA /* DoubleExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF1663184D583927C6FB7569D549A840 /* DoubleExtensions.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 5531E1784474442E9ADB17A7539521AC /* Eddystone-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 683F26A72165D255BCDA83A03B0E4BCD /* Eddystone-dummy.m */; }; + 558EED8054BE6E4B77C24D3640A82867 /* MZTimerLabel-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = AEA060E5659F19B47BEFBE9D4D7E9CD8 /* MZTimerLabel-dummy.m */; }; + 567E47EE5AA042E2475AA8AC19F35060 /* ChartDataEntryBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE8657AEC36257F2FA3F10753A556B2F /* ChartDataEntryBase.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 58130F131C4B889050714D0D5F8A5BED /* UIView+IPFrameUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 39D00D1E22849A388D7AB8362D50C1DD /* UIView+IPFrameUtils.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0 -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 582C17C37CCCCC12A71016020B1E6F9A /* CombinedChartDataProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 927881679707E7BB35FBF5CCF8A0183A /* CombinedChartDataProvider.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 5830202DA5E8E5FA0734046FD00CA9AB /* IChartDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A3B168913F0573313A17DDB4317B3B2 /* IChartDataSet.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 588226751006A9F4DE29BA5C13F2363A /* WYPopoverController-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = DFF1F7E3F419F2BB2B0A022589059283 /* WYPopoverController-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5B3EAA6F7334F52A500509EA891D0B34 /* UINavigationController+Chameleon.m in Sources */ = {isa = PBXBuildFile; fileRef = 530DA5F79FC49F4F24129ACF69B64177 /* UINavigationController+Chameleon.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 5B92725F46360893493FA626926F80F2 /* CombinedHighlighter.swift in Sources */ = {isa = PBXBuildFile; fileRef = D747B0E5D7EB2EC6EF683B23CA4DD4D4 /* CombinedHighlighter.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 5E32EFEC310E2F472D9DA085FBCC5667 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4E872B141543C04195F4AA6253DCB46A /* Foundation.framework */; }; + 5E7F7D5A2B60547DEDB75E322B85C1E3 /* BarChartDataEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E063F0C244C3ED32C67EC74FCD5E4AF /* BarChartDataEntry.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 602A282381899FCDDEEDC76845F4C415 /* MZTimerLabel.m in Sources */ = {isa = PBXBuildFile; fileRef = 2608767335B92B9DA52F41E87B58A9F1 /* MZTimerLabel.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 607EB1E5DDEEE39A34B6FF76481E5240 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4E872B141543C04195F4AA6253DCB46A /* Foundation.framework */; }; + 60A61A5EA6BDBD5601299DDB5A52C14A /* LineScatterCandleRadarChartDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57634E7A180647CF43FBC74A5BD446F3 /* LineScatterCandleRadarChartDataSet.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 610605379D549B8246F4689CAE528114 /* Platform+Accessibility.swift in Sources */ = {isa = PBXBuildFile; fileRef = F343DF467FE87DE5EA940B4A5871B71E /* Platform+Accessibility.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 6160CC839154784B974F4120EC1B82C2 /* UIColor+ChameleonPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 7181A7AF7266173B7C8FB3AE317A77BF /* UIColor+ChameleonPrivate.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 618F0C277CFA69A5433DAA11EB68538A /* ViewPortHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = D86F2E52155C22E5F25E972563F6C26D /* ViewPortHandler.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 61C446A2F28E4F813CB130B6C772F857 /* CombinedChartRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42B2EEC771BA840AE50CB797B0F162F8 /* CombinedChartRenderer.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 62735AD816C256656776BB47B36E4002 /* UIColor+ChameleonPrivate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1C94D25E7BF4C82F3F0FC450078C7D2B /* UIColor+ChameleonPrivate.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 640DFE29FC42AAB9B97720C6C4143432 /* UrlFrame.swift in Sources */ = {isa = PBXBuildFile; fileRef = 303726B29FCA0EAB7FA43803BB2FFC46 /* UrlFrame.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 644E05CE5F65D923C4FE3BE9BDC78B7D /* IFillFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDF39A530290D04E3EE6CE2217C92AAD /* IFillFormatter.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 658632A1D06C3D6E228DA9920792531F /* WYPopoverController.h in Headers */ = {isa = PBXBuildFile; fileRef = 04190BCB6CCD576431A82519AEE11E5A /* WYPopoverController.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 65D5D6D89B0395AEA80F0E320D8EB487 /* UIColor+IPRandomColor.h in Headers */ = {isa = PBXBuildFile; fileRef = C87A2240B5E8AA65D71063700E91E228 /* UIColor+IPRandomColor.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 662C582EC89CF306976E72064982C6D9 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4E872B141543C04195F4AA6253DCB46A /* Foundation.framework */; }; + 669421AC5F4FA4EC7D13F08575D53B6F /* ScatterChartDataProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8642C5BE3AB754F356C8DB11D0836BD2 /* ScatterChartDataProvider.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 66F8FFDDA535894825A2E9D3490A85F6 /* DefaultFillFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 643484DF9098D57753F164AB155E2D8B /* DefaultFillFormatter.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 6B080B5ED674FE19F2889ED71D8F6813 /* UIButton+IPUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 74DB70308405A78C5D9B053473907B31 /* UIButton+IPUtils.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0 -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 6B2D8E86FC5988707F276D63E6D09843 /* AxisBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91E94BCA50C419D7C1B1B5E4FDBE3D2E /* AxisBase.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 6B8FC7C9E95AB1715333AAAB260C8185 /* BubbleChartDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = CABE3C668778FA66499CAD161C9BF3FB /* BubbleChartDataSet.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 6BC552C40935F9164B0565799E276A70 /* ActionSheetDistancePicker.h in Headers */ = {isa = PBXBuildFile; fileRef = 9EE8B89B13BC78BB5EF06D06E96AE057 /* ActionSheetDistancePicker.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6C5AA261DE2D6CA33DA0BC60C50BFF85 /* ScatterChartDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFE82A85642B53FF28CB6B150276BF47 /* ScatterChartDataSet.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 6CE49BF2883BEAD623FE702ECDA5C508 /* UIView+ChameleonPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = F0B92ED39CF0DAB364E406CBD53F3E6E /* UIView+ChameleonPrivate.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6DE8C977E77B7A9F692376E009B82254 /* DistancePickerView.m in Sources */ = {isa = PBXBuildFile; fileRef = E0DC9F0E418367CC13C7CF9B881FA05A /* DistancePickerView.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0 -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 6E8F39BF4A1C5F1E982D92DCA17F3F81 /* ALView+PureLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 934072CF1F79CE797EB562EE16407C5B /* ALView+PureLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 70052EBBCE4D6B524FD4558E1C2E1696 /* SWActionSheet.m in Sources */ = {isa = PBXBuildFile; fileRef = E03F34DE3C542EDD599D7589F75DF745 /* SWActionSheet.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0 -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 70E59FA2437A59807C900A9E381172E6 /* TriangleShapeRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60636B604BABF9DE0CC5107B72A0BCF9 /* TriangleShapeRenderer.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 718F9CBBB203EDEC7BD84E7686D9B297 /* ChameleonFramework-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 2F73756828B80DDCA6EF49CA5F26F168 /* ChameleonFramework-dummy.m */; }; + 7306E7AA1468FE0833BEAEB0D50A99DD /* ChartColorTemplates.swift in Sources */ = {isa = PBXBuildFile; fileRef = D23BFA6030DCBB4D45C339D070837F9D /* ChartColorTemplates.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 73BD034A9B00F30A1A4014EC98C5A2FC /* Eddystone-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 12D031A69C52A7AC31D772114B2770F3 /* Eddystone-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 73D6C6CCC90335B32B86829F7A492B90 /* XMLDictionary-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 9CD0288571DA72DC1251D12E561A6271 /* XMLDictionary-dummy.m */; }; + 741FDA313164BF386A7BADA9DE6A272C /* UIAppearance+Swift.h in Headers */ = {isa = PBXBuildFile; fileRef = DF301E949BBC69BBD8C5B5E4A6A9D2A0 /* UIAppearance+Swift.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 74EC7DA37555A322E231D48B8E11F774 /* CrossShapeRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8E1F569037FF8B010639F61B2735AD5 /* CrossShapeRenderer.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 755CC0A38757AE7AEACBF589C5CD0D31 /* UIView+IPAncestry.m in Sources */ = {isa = PBXBuildFile; fileRef = AB45DB51C553CD1C857F74D4F812C2DD /* UIView+IPAncestry.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0 -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 771FB69AC8E6605083E63FB27AC951A4 /* LegendEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDCDBDA222AD05425F42DFDF81FA9C4A /* LegendEntry.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 778CFAB2FF431A7CA34821B18DCD332B /* PieRadarHighlighter.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF36090CBEC6C05735606412FDE437E8 /* PieRadarHighlighter.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 77AAE9E936660E1EFB1BAD250D10C5C8 /* AnimatedViewPortJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33D149F302D5CF9FA1F7308DAF0ABD5B /* AnimatedViewPortJob.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 7B177AE0EF7941102ABF676ED4187EE9 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4E872B141543C04195F4AA6253DCB46A /* Foundation.framework */; }; + 7BC8CA21A04DAC9ECB08D905BF13608C /* ChameleonEnums.h in Headers */ = {isa = PBXBuildFile; fileRef = 6A353EA5D77D5A677BB2A7CC8C0200C1 /* ChameleonEnums.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 7E9DED37321416EB9F4EBE87FA4E0869 /* UIView+Constraints.h in Headers */ = {isa = PBXBuildFile; fileRef = 8FC40DD75DDD0B5E07D3A92A26F87C95 /* UIView+Constraints.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 7F89B8FC19832264C0567C9BABC3654B /* ViewPortJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58F964009ECA3B64814787A3435B10BD /* ViewPortJob.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 7FD267EC050B1AF18FF090EA036FEAA9 /* LineScatterCandleRadarRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = C733D2BFA082C72EAAB468D9E9678FB4 /* LineScatterCandleRadarRenderer.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 80BD732089E1B3A6E5E9E453D08AADCC /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CD4CAAF550DE1A78EEC5ED881A5AAF84 /* UIKit.framework */; }; + 80EBFB2111125DA63FA6F204357D515F /* UICircularProgressRing-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 5F2B4631847D37507D49C3BDF1244ACB /* UICircularProgressRing-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 81E72938A6165A7F476DF08F511A1B66 /* BarLineScatterCandleBubbleChartDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = F239D34F40279DC33EBF3CB789FDCFC0 /* BarLineScatterCandleBubbleChartDataSet.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 81F48B45BB3364F85399A085D2C6EB5D /* SWActionSheet.h in Headers */ = {isa = PBXBuildFile; fileRef = D5D4833825615D141834B3888572FB4D /* SWActionSheet.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 832C622C9F35C48C02DEC2220EF91FB6 /* UICircularProgressRingDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E15B2865C9220510128DD12E8BCA588 /* UICircularProgressRingDelegate.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 83A1D722DD1D5887B34219BF898DF1F1 /* PureLayoutDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = 569BA96B108F04FD9CC4CD686513297E /* PureLayoutDefines.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 83C015F328C7606792488E0421FF7083 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CD4CAAF550DE1A78EEC5ED881A5AAF84 /* UIKit.framework */; }; + 84925CC6CD24D46DBC0800942AD1C306 /* LegendRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D926BF98B90DCDD6524156075D62DB00 /* LegendRenderer.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 8502610E39EA4DA1C645D85AC1BD9F49 /* ChartDataRendererBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C48E807343CABA2262D85BFE1A1D8BA /* ChartDataRendererBase.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 856FA8FD6609AC750670E2FA996BADF8 /* LineChartRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CF24195C175E960490AB9D5477BFD87 /* LineChartRenderer.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 85F46AC0868623936E84FBD678B986EF /* XAxisRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7481CF72D407C3ABE3C21CE4EA0663DF /* XAxisRenderer.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 86308120B2AA61C15A8EB3569D5E38FF /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 504690566E595BB0A03D20B7BA480ABC /* QuartzCore.framework */; }; + 86672ED0548E81E771A5A6C11239D9C2 /* PieRadarChartViewBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = A4FE66660693AED28587ACC5B8E64B1A /* PieRadarChartViewBase.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 867B5476B4D0056DE696287063748449 /* Global.swift in Sources */ = {isa = PBXBuildFile; fileRef = F2F466AB97BC42F81997A351E1C02ABB /* Global.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 8718A99B43F4456F1CFFD90F990727D1 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4B50C7A6F17A840A6331420D07FD52E /* CoreGraphics.framework */; }; + 87CACFF8D1DEB6F794AC8DDCE8D52721 /* LineRadarChartDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3471AE3783802E123428196BF7F2C48B /* LineRadarChartDataSet.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 8817670F999F88091A8E1A7AC59B5DD0 /* BarLineScatterCandleBubbleChartData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 741CF545C29BBBD5B91CB19812F6F1AB /* BarLineScatterCandleBubbleChartData.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 89BDE1A2792C976E5CD1A94BA57B4652 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CD4CAAF550DE1A78EEC5ED881A5AAF84 /* UIKit.framework */; }; + 8C46ADC14759E79D0D4CBC63E3E14B80 /* CandleChartDataProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2A3FDF0E87B088C76C1B6F500538CAB /* CandleChartDataProvider.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 8CD86FA725C57D6F6FE9DA4132AC16E9 /* CandleChartDataEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E6227BF90B1AAD393A68FB8234816CD /* CandleChartDataEntry.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 8DDA1DD5D3323898521157C9E0AF8435 /* UILabel+Chameleon.m in Sources */ = {isa = PBXBuildFile; fileRef = C7A73385CBB863151DAE52BC522CCF88 /* UILabel+Chameleon.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 8EEBBB90A27B8CCF754B7BEAC5E460C8 /* ChartAnimationEasing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 99FC4D414E8D92A3687B983B5DD082E7 /* ChartAnimationEasing.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 8F87677FB3ACD2195081D31024A91893 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4E872B141543C04195F4AA6253DCB46A /* Foundation.framework */; }; + 8FB3D4F962538219133464CD34058547 /* XMLDictionary.m in Sources */ = {isa = PBXBuildFile; fileRef = E14AC5EF05604CFDA41013CF1E515DE8 /* XMLDictionary.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0 -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 934543CDC3E37251DE163ADB4B6820FD /* CandleStickChartRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8EBA1DD0ED252939E1BCA5C1B8578A45 /* CandleStickChartRenderer.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 9410C7E4CBDFF736F5C45DFF733BA0B3 /* UIAppearance+Swift.m in Sources */ = {isa = PBXBuildFile; fileRef = 80106BF869F5D236D9896410F1E83729 /* UIAppearance+Swift.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 944245D934F12AB6FA8057041BF7E646 /* UIButton+Chameleon.m in Sources */ = {isa = PBXBuildFile; fileRef = 7C9254F379DC1DB830541F92590F4488 /* UIButton+Chameleon.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 9512CDA083EA61F299A467BF4678A2FB /* BubbleChartRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65D9CBA1C9C448F48A1B55B1E0D465D2 /* BubbleChartRenderer.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 9523929E8668F0E72243B5D8E7379CF2 /* BarHighlighter.swift in Sources */ = {isa = PBXBuildFile; fileRef = E35C53F4C58D4FA912F93BE606F90F3A /* BarHighlighter.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 96C0FF8A72036FF83A4752A02B811B5B /* LineRadarRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE027CB2591F19C7568E2F416B905C09 /* LineRadarRenderer.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 96C8BE77C6E26E4B9312D62F5C211269 /* Description.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3376FA5C8A5D1B2D506D0C0F53E8604 /* Description.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 980F19CAA48A2AB6A2E72B0BB752FD7E /* UIView+ChameleonPrivate.m in Sources */ = {isa = PBXBuildFile; fileRef = DDCF4967B8D3E3851C5D5CEC725E65CE /* UIView+ChameleonPrivate.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 98371A8C65AF1373CA3887E187B16ABC /* XAxisRendererRadarChart.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37F49D184948DB3945E37E66E7854D7E /* XAxisRendererRadarChart.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 986BBFA10788030132379E305A0C9E15 /* WYStoryboardPopoverSegue.h in Headers */ = {isa = PBXBuildFile; fileRef = C69372D9713A79E1FA52EADFC027C46D /* WYStoryboardPopoverSegue.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 987C7F5C034715EB4A264175B8FA3AEB /* Range.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F2C6B76362F95DA7C7D59F803049517 /* Range.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 989CB1FF8E0FD8DF5B1A0C9EC57CD91D /* IPieChartDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 031C1A1D4169F31403D9CBE6EF4B294B /* IPieChartDataSet.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 9AD317C36A6DDF98D1CD5A247F9DE367 /* UICircularProgressRingGradientPosition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FC3412280E72BE4AF1388DCDDA2D308 /* UICircularProgressRingGradientPosition.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 9B98E2F6281B5CE2B56FAAF47782CD73 /* UICircularProgressRing.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8A0DFAF5F40F9B206C01736F0E25323 /* UICircularProgressRing.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 9C9E8501F44A72B46ECF922859CFED03 /* IntExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1982ED7CE88E71925D5F535C6C7A062 /* IntExtensions.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 9CB529305884D774BDCB2FDD5F7B27A0 /* UIViewController+Chameleon.h in Headers */ = {isa = PBXBuildFile; fileRef = 5A0D91B6CCA43C65C5E5AFF3DB9B1F50 /* UIViewController+Chameleon.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9CCF6EF2287763656A9E86F7552998E7 /* BubbleChartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B34262047C80B45B8586528E63030076 /* BubbleChartView.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 9D7A80B2B72F4FBC01765B25B7B0033D /* LineChartDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = B925D33DE5068460A5AC15AE02620971 /* LineChartDataSet.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 9E1EA37140FB4DB5589924D069E0F040 /* ActionSheetLocalePicker.m in Sources */ = {isa = PBXBuildFile; fileRef = A8BB3CC60E25C2EDC28E0BE7B33B9771 /* ActionSheetLocalePicker.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0 -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 9E52A2333D730EDA05C5E745540674E4 /* UICircularProgressRing-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 6174E65A0E21BA21D32E3C972B070371 /* UICircularProgressRing-dummy.m */; }; + 9EAE6A25D87CACB3469A5FE41922F582 /* Pods-BlueGecko-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = BC606CB7ADB7FF23C1EAD29C9963B8FC /* Pods-BlueGecko-dummy.m */; }; + A00B3B20DB010F2F289E90A965E0ACA9 /* CombinedChartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 903DC957219810A92394E22C6B19629D /* CombinedChartView.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + A0501B7D192BE61470F409C7DEAB2731 /* Pods-BlueGeckoWithHomeKit-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = C559D1D35A8475FE2A8DE5DB4270AFED /* Pods-BlueGeckoWithHomeKit-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A0D713856DDD52B95F7C4365F059CD1E /* UICircularProgressRingLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A8E67432D41F0ED22EF1767FE3FD7BC /* UICircularProgressRingLayer.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + A11AA27F116FF1637A8FE254AF6F044C /* ChartDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 389A3FE642BFDC7F2B5D76FAAE2EC913 /* ChartDataSet.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + A1805B3522AD2C8941E19640D7AA616B /* DistancePickerView.h in Headers */ = {isa = PBXBuildFile; fileRef = B7C3AE64DC7C46FA86DF3DC695DCB1E0 /* DistancePickerView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A191E3933EEFD02A9ACEC22B12A436A5 /* IAxisValueFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = B92124638605120A20179A134DC7D453 /* IAxisValueFormatter.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + A23C15CFFE2F0E3EFBC92FE4E799A255 /* PieChartData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 25C0783D77DD9E95A5DDFD863D8A39E8 /* PieChartData.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + A35899B69536C89FD209D72189189429 /* Renderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E1663FBB43F97FD1F8C5074DB77FEC7 /* Renderer.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + A35F9A4C8C7E3EE526F99863BF2D3EEA /* ChameleonFramework-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = A2FF71834CDD54D9F20FF33B199FCF2F /* ChameleonFramework-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A36943D28C83AAB32E4D4AFD91F3237F /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4E872B141543C04195F4AA6253DCB46A /* Foundation.framework */; }; + A497C4B9650355975228FC86A9F88026 /* BarLineScatterCandleBubbleChartDataProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 273C7DC661C73862256E8F1E24C36458 /* BarLineScatterCandleBubbleChartDataProvider.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + A4DF0869E33A835721E12663EB81D37B /* LineChartData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2612F4C6AD646E9719C2BBD4022C2ADE /* LineChartData.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + A5AB8E85B4EAB2E0958191FA978948E6 /* Animator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E79878BB77CBFDEACC606421F3D85809 /* Animator.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + A63B3C9A2AAB3A8D5BF63A882225FFFA /* IScatterChartDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD82D404096AD6B24F60109F298A3FDD /* IScatterChartDataSet.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + A6570502D82990F2A31D021D685B69F7 /* Generic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 620F97B263A04521A767E9838781254F /* Generic.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + A6721015E658A04A721FE760643D6157 /* Object.swift in Sources */ = {isa = PBXBuildFile; fileRef = F21204C8D0DC1E497B87C2D0664168CF /* Object.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + A7F8937FA0B184FB4A9CBF94AFD5C9CA /* IBarLineScatterCandleBubbleChartDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E9625AEF2DDDF05E981EC1CC74352E6 /* IBarLineScatterCandleBubbleChartDataSet.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + A8483FA08C7504C84AAFA435EC431387 /* UIImage+ChameleonPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 3E3C794FD85107420F8B9D1D8EAE5451 /* UIImage+ChameleonPrivate.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A9E8BF7B194CF266508F39D3123BFCB9 /* Chameleon.h in Headers */ = {isa = PBXBuildFile; fileRef = C3432CEDF6D175E95F2450A31A2F89D9 /* Chameleon.h */; settings = {ATTRIBUTES = (Public, ); }; }; + ABF95CBA02E302E08009102775B703F2 /* Pods-WirelessGecko-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 3CBD6C421C3B20CA83FEF5F4894B4D4B /* Pods-WirelessGecko-dummy.m */; }; + ACC0988FA6FD531E5EF82ECD0B0F8F72 /* DataApproximator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E397227EFC2CDC9D2D030F6828E29438 /* DataApproximator.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + AD1F14554F6D1F1313568CCF7346FF6F /* SVProgressHUD.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B324A581DDD6EA8E88C978D063B53DA /* SVProgressHUD.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + AD8BDD5A9231068B37619FBDAEC06DE4 /* BarChartRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F897B9413247295364D38AE83A36795 /* BarChartRenderer.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + AE90811F6C330C0483BE86C370611882 /* ChameleonConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = F1882C013DBA9375628D90C7C984182A /* ChameleonConstants.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B031532D7673C9889B31F453BAEEB88D /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CD4CAAF550DE1A78EEC5ED881A5AAF84 /* UIKit.framework */; }; + B05E520812AA92A479EB9EAA29C88B97 /* ChevronDownShapeRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1AF3F2BF2A6C179D6B9807122543F6F /* ChevronDownShapeRenderer.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + B15FC25978BE630AAE96635D17907A71 /* ChartUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8072DE6C57BC4BF3AA233DB26AAA9EB0 /* ChartUtils.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + B1D52A9C38BE10BE4229506B91103133 /* XShapeRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 200DC0152261F9AA7276C30BE32A9C8C /* XShapeRenderer.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + B3AC852255B3BB778847B171C675296B /* AxisRendererBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = C04C69B2D8638A19159459318390E183 /* AxisRendererBase.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + B4F1A6377FC8113770335D930C079C70 /* SVRadialGradientLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = AC02D409F9D0CDB1548871DE4058600E /* SVRadialGradientLayer.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + B4F8DF6260122D8C12A3A1D59026BC3B /* Scanner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 025F3ABB22FDA99968B420F91E511D2A /* Scanner.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + B4FFBAAAB2020487F48B39A18F09BABC /* ActionSheetMultipleStringPicker.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F1C3175156D68F09309C6D90C0DA3B9 /* ActionSheetMultipleStringPicker.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B6B21BB894F5A086977EE4F2A6AD77AE /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4E872B141543C04195F4AA6253DCB46A /* Foundation.framework */; }; + B9FA3D63FE523FF1E97CA50AEDDF1833 /* RadarChartDataEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38AF2B25FCF8F38D923B2A8B9B5872FE /* RadarChartDataEntry.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + BACFCF38BA6890B3C70BC7C1753C8045 /* SVProgressAnimatedView.h in Headers */ = {isa = PBXBuildFile; fileRef = A2254E1A588165AF3B57FA75E6701BA1 /* SVProgressAnimatedView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + BD8C15CEC12E2C97775FCCF763C45DBF /* ActionSheetPicker-3.0-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = BF5FEF3243553F8AA6BD62CBF22CCBD3 /* ActionSheetPicker-3.0-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + BD919F30AE8401BD08F15505B8AE8ABE /* PieChartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EE21DBBF5702F3F31F823B4AFF90A30 /* PieChartView.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + BD9D1FFE56D8A8760686B46136980400 /* KVOController-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 4D5A9E2EC3DD2F51BA182A00E5DEC6E3 /* KVOController-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + BE18FA232ADFD92A0E9299B254555FB9 /* XAxis.swift in Sources */ = {isa = PBXBuildFile; fileRef = C18C76D402F2741A0AA1D8C0017FA5CF /* XAxis.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + BE9064297027980C803A495B0BD36364 /* RadarChartRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A3A22D5D7DFFBCC072A618962C29187 /* RadarChartRenderer.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + BE96007160D646D5D68896BDE0B00D9E /* NSArray+PureLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = CFF6C104AA6D1D496B19D102FF515BD4 /* NSArray+PureLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; + BEE3F41C1AE3F63252F05C59C7E14088 /* ActionSheetStringPicker.h in Headers */ = {isa = PBXBuildFile; fileRef = 024874D192E414F673383336E47E8011 /* ActionSheetStringPicker.h */; settings = {ATTRIBUTES = (Public, ); }; }; + BF0DDF8775FDCD678AB1CA55847BEDD5 /* UITableView+Utils.m in Sources */ = {isa = PBXBuildFile; fileRef = 0461CFEB46E08F25B56551C6A3C90472 /* UITableView+Utils.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0 -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + C22161A14023C0E8B7C9CED95FEDB6EC /* UIView+NibInitable.h in Headers */ = {isa = PBXBuildFile; fileRef = 47E053279BCB14FD7D9DCF76AA6B4CBE /* UIView+NibInitable.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C2B43086EC0847B7958DE4F5FBA75A22 /* UIColor+IPRandomColor.m in Sources */ = {isa = PBXBuildFile; fileRef = 61C4F376C04A8E77F23D0F3AD6A9E95D /* UIColor+IPRandomColor.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0 -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + C2CB66F328C91D46BD14669B85BA90B3 /* SVIndefiniteAnimatedView.h in Headers */ = {isa = PBXBuildFile; fileRef = DFDE5E86B3473EBCB408792B8AF230C1 /* SVIndefiniteAnimatedView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C3CC572A93496D96D1514C110C05D4A9 /* AnimatedZoomViewJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B20E8445BA0DDD43FB3071C1C0E4BD6 /* AnimatedZoomViewJob.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + C55224B2297E86CBC8C2CCFEE4D5EA18 /* Chameleon_.m in Sources */ = {isa = PBXBuildFile; fileRef = 516B0ED428665BD90D818DEE11C340B9 /* Chameleon_.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + C63C0F6AE7087D02F2DD1AF741B84EFC /* UIView+Constraints.m in Sources */ = {isa = PBXBuildFile; fileRef = ADA5FED26D4E88D6BF457EEC69A96F00 /* UIView+Constraints.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0 -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + C662028048556D063A9AC1B784988B8D /* RadarChartData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0490899449C723E7EC451A97FC77E5B9 /* RadarChartData.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + C6FAFCCF65C6889EC5E3DBE85B9A77C1 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 504690566E595BB0A03D20B7BA480ABC /* QuartzCore.framework */; }; + C7948DD19484AD97B80E7622B9A9BCAC /* BubbleChartDataEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 513761915E3ED039E2120E0FF8B65600 /* BubbleChartDataEntry.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + C7A221A39BAF88495510D99C56DC6C04 /* ChameleonConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CD0A3FA3E70958D084098CAC95338F3 /* ChameleonConstants.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + C80AEEF00532797FF769CF482E568473 /* YAxisRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82926FBBD1B0798B1F00AAA4397F2372 /* YAxisRenderer.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + C81103311755CCE17B7373294BB2E1BF /* YAxisRendererHorizontalBarChart.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D46FFE9FA8DD84EAA516AE74508BD1A /* YAxisRendererHorizontalBarChart.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + C8BC2FEF74A2D51E779E4BAB60B1F1CE /* UIView+IPFrameUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = D49789494660D719206D7DA7E901452F /* UIView+IPFrameUtils.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C9A262A3B22241C5F9C5EE2064636869 /* Beacon.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF374CE19902BD37E880A0504B5A7D54 /* Beacon.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + CC2E2E413D6125F7636C4A0B3F6DFFCC /* ChartBaseDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81787386F805E581DA154CB7C1A23CFA /* ChartBaseDataSet.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + CCF010AF65241F580D3E461A790679D2 /* UIViewController+Containment.h in Headers */ = {isa = PBXBuildFile; fileRef = E6A05BEEAFC77CB25A3B7CF32C1B5AFD /* UIViewController+Containment.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CEAF967ACE976FF757ECDC3524E0F03D /* CandleChartData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00DE8F8453D74BA2667E3E8086ABDD4A /* CandleChartData.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + CEE5894FE73DB9EEAE919DCA0B138625 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4E872B141543C04195F4AA6253DCB46A /* Foundation.framework */; }; + D12FB77C9C64D1E7A691407206DA2348 /* AnimatedMoveViewJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = C754AAB7BBBFAE48AE426D462403CE3D /* AnimatedMoveViewJob.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + D2A6CCF8726A7F31EF4332EA84241192 /* UIViewController+Containment.m in Sources */ = {isa = PBXBuildFile; fileRef = 63F658BBCC7371AB5CA6BC9BBF022159 /* UIViewController+Containment.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0 -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + D2F1D3744CDB46E673C8CA26FAA92B8C /* UIButton+Chameleon.h in Headers */ = {isa = PBXBuildFile; fileRef = BC4A51780BC2A1E6DD2EA6CC18289A01 /* UIButton+Chameleon.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D423F046852D73CC7407370136F924CE /* PieChartDataEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6A33E9927E27B3E713B019BC3F7D90 /* PieChartDataEntry.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + D65C1FF368529A12B2E8B7F157B1DCD6 /* CoreBluetoothExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52DB73DAFFAEE1E6D19D9EF203AF2D4 /* CoreBluetoothExtensions.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + D6D007B23FA5DF1701D61350DFC40500 /* AbstractActionSheetPicker.h in Headers */ = {isa = PBXBuildFile; fileRef = 39142212EFDD9BDF3F5DDC66D222760A /* AbstractActionSheetPicker.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D6FB3C2B3E18583390ECA4FDA97A1EEA /* Fill.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45059F949099ABAAD358FB1A3586CD3A /* Fill.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + D72525552EA381EFC7AC1F2617B30F12 /* ActionSheetPicker.h in Headers */ = {isa = PBXBuildFile; fileRef = D518D2422D85805564148DE4B68EEF51 /* ActionSheetPicker.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D78AEE61D4F95442EB9266D432E69C14 /* SVProgressHUD.h in Headers */ = {isa = PBXBuildFile; fileRef = 5A22154EBF2F0DE92536644E78FA6A5D /* SVProgressHUD.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D80520F915604ECE5AFC7C198210BD4F /* ActionSheetCustomPicker.h in Headers */ = {isa = PBXBuildFile; fileRef = 15BB98E46064549F9D687CB2734C6011 /* ActionSheetCustomPicker.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D86CEE6DDC971DF965723FDD1682648F /* XMLDictionary.h in Headers */ = {isa = PBXBuildFile; fileRef = 558F2F7A2DC6222F1FF0FA94D5957844 /* XMLDictionary.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D8D4BFE7C0666D68D6649E9A95D3A03D /* CoreBluetooth.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D8D46001FF3B13E1D0356D03F0DFA3F8 /* CoreBluetooth.framework */; }; + D979651A01A2CCB1600FC373C39B4C3A /* KVOController-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = A51C44019E3A894C8895D6D8BC036A7A /* KVOController-dummy.m */; }; + DA35E172CFC080BBAB284AF2790DB7F2 /* ActionSheetPicker-3.0-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 12183893149307FB085B68D57B1DEF66 /* ActionSheetPicker-3.0-dummy.m */; }; + DB4D064C6F10F24273D7DC4A127DE99A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4E872B141543C04195F4AA6253DCB46A /* Foundation.framework */; }; + DB4F08C219191CDB5225FCE00473BA33 /* UidFrame.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE4EF2CE77C0378F2F9A8CFD5AB9B210 /* UidFrame.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + DBD7F1B4E5FCD19ED2AF4587ECB135FE /* SVIndefiniteAnimatedView.m in Sources */ = {isa = PBXBuildFile; fileRef = 45709024E87F53D94EA3E6CB7463C190 /* SVIndefiniteAnimatedView.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + DC4BBBCECB152203D4901B930197C668 /* BarChartDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 544145B0B14DBBD37A7AD8E40B5F0456 /* BarChartDataSet.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + DCD507135C42B7651AD685A2D3811BB2 /* FBKVOController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0A55D7A54C24B18ABB272F3F03760549 /* FBKVOController.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + DE454B28B9AC9F7C42839AA55D7574D2 /* YAxisRendererRadarChart.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D20CD4B0F1917F76DBF804904257E7F /* YAxisRendererRadarChart.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + E16CF9C974AFA7CB156AA72E71A1365B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4E872B141543C04195F4AA6253DCB46A /* Foundation.framework */; }; + E1AD4B4DE359DF79DDCDCC0D877797A2 /* NSObject+FBKVOController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7A59D71277F8A7EBB7698E856B46D253 /* NSObject+FBKVOController.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + E60188A7E4C69337B6840D7875A539C2 /* IBarChartDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF8905ECF8F6A06CA05E91AB2B999D85 /* IBarChartDataSet.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + E83DD47D94C577B3D5F672C7A5C55467 /* RadarHighlighter.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB28E4CC9EFD878DD9E1A3BC492EB783 /* RadarHighlighter.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + E86B6328D8296809B25F536C5F10CD4B /* ChartLimitLine.swift in Sources */ = {isa = PBXBuildFile; fileRef = D132CE6A14A414E7F42ABB051E16BBED /* ChartLimitLine.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + E922EAB5357E2B0C01D49E9A3D6F3272 /* IHighlighter.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA2D0995041FD3A752B936A161DC59DA /* IHighlighter.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + E9D7FAEC94CBACA0A7FFDE5B44965725 /* UIImage+ChameleonPrivate.m in Sources */ = {isa = PBXBuildFile; fileRef = 9CEC245B78279AF03A87DC3867F4325D /* UIImage+ChameleonPrivate.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + EA10E82D4BBDBE2575862FBE7A0C4C04 /* SVProgressHUD-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = B9103643A78ABD199104FDA2F498075F /* SVProgressHUD-dummy.m */; }; + EAE2466CD147DFEA36C889EA6081785E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4E872B141543C04195F4AA6253DCB46A /* Foundation.framework */; }; + EBC9299FE403A45B246F74297CD8A05A /* PieChartRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4A721ED9B3C069A0640FAC201570CD4 /* PieChartRenderer.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + ED42CE0BF78638A8AC06534F1ADDCB24 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4E872B141543C04195F4AA6253DCB46A /* Foundation.framework */; }; + EE30E67B79136BE20215583604092326 /* ChartViewBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D6EF8626404CE5AA97A83FA08910E76 /* ChartViewBase.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + EF0752D7045F333EB6B017BABDC63984 /* SquareShapeRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDC68D229D7ACA3ECCD9A12B1D27D6E7 /* SquareShapeRenderer.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + EF17EA942480F7242CFDBC3A7BBD5705 /* SVProgressAnimatedView.m in Sources */ = {isa = PBXBuildFile; fileRef = 3F36FA7BD17CF42413AB49F4B85512BB /* SVProgressAnimatedView.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + EF203789B9D827C23D6C5B894C239CAE /* BarLineChartViewBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = E293A98447A787C3FAC6AFB7FC85C952 /* BarLineChartViewBase.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + EFE5F0E288D5582F37B69E838FE907BC /* DefaultValueFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C33F8227CCE6399F69AFDC719E0DEB9 /* DefaultValueFormatter.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + F08904E8835E4279192C40CA6474A13C /* YAxis.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD13961E49F3C85E0868C6E54F2206F0 /* YAxis.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + F12837AAC469A75054A691FB555227B8 /* NSArray+Chameleon.m in Sources */ = {isa = PBXBuildFile; fileRef = 14CD451ABCB610CFD12F47CAFF7BE531 /* NSArray+Chameleon.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + F131FE90B8E873F55FF192FF10A19076 /* ActionSheetCustomPicker.m in Sources */ = {isa = PBXBuildFile; fileRef = A9E2418BD84AE19AF343489786757C64 /* ActionSheetCustomPicker.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0 -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + F16A032A811867FF6323143582E47951 /* HorizontalBarChartRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 679DA6BE5AD33B38F3A7E14AA89CB2C9 /* HorizontalBarChartRenderer.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + F1A0BACF2A146A439122863794F734EE /* RadarChartDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35D2F421107B1B0AAAF1A00095F56D53 /* RadarChartDataSet.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + F1D096BE7FD7AD4CE1135805B170BBB4 /* HorizontalBarHighlighter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 219F6CF3CCC811E9083AA2F13750F9E9 /* HorizontalBarHighlighter.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + F25A402EF79272E1802569409E7B3345 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 504690566E595BB0A03D20B7BA480ABC /* QuartzCore.framework */; }; + F3AA3D91880B982B7C9BDED7E4DF2A67 /* UIButton+IPUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 5E7F96C3694731B746BDA5FE375B7FFC /* UIButton+IPUtils.h */; settings = {ATTRIBUTES = (Public, ); }; }; + F3F4F80C0BAE1855B294ADAFC6BEC67E /* TransformerHorizontalBarChart.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90A3B781B047A3280FE14967BCC59A4D /* TransformerHorizontalBarChart.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + F442C35711C3B60C74D66F237619C391 /* ChameleonMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = 9027945388741C2D88415E3D7201D9EC /* ChameleonMacros.h */; settings = {ATTRIBUTES = (Public, ); }; }; + F48A2073BF27DD81DA781B5AEC15E10A /* IBubbleChartDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 478CF550BE7D801EB6E55E5D4CFE151A /* IBubbleChartDataSet.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + F4B03991D0708E3C8909CE66F291ECA8 /* Chameleon_.h in Headers */ = {isa = PBXBuildFile; fileRef = BBA4AA1162CC5B98CDC08F04FF60062F /* Chameleon_.h */; settings = {ATTRIBUTES = (Public, ); }; }; + F5A5996E49FB0CC06D9A964B7431192C /* MZTimerLabel.h in Headers */ = {isa = PBXBuildFile; fileRef = 94C3444270D503940943E477B3105B39 /* MZTimerLabel.h */; settings = {ATTRIBUTES = (Public, ); }; }; + F5E44281520A56C266B186F502B7B23B /* WYPopoverController-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = FB04D371FBAD3969A38BE86D78D0186A /* WYPopoverController-dummy.m */; }; + F61761312E0D741D61DC09E02BCA6DE9 /* ActionSheetDistancePicker.m in Sources */ = {isa = PBXBuildFile; fileRef = 1B336EDE579D4A86FD139ECB8D22B45E /* ActionSheetDistancePicker.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0 -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + F622D7EA5FD98CFBD9EA62FFADD13396 /* SVRadialGradientLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = AE80CF5B6B184DD01438693A2D92C91A /* SVRadialGradientLayer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + F7494F8E4C6D5539E6C0F508835D855E /* NSLayoutConstraint+PureLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 660FDCC8D1D1C260A6C9AFC394C62175 /* NSLayoutConstraint+PureLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; + F7A9B63B2EE7B49C97809FF5F8F2E413 /* ComponentBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A2CEAB98F32984CFE1E2BAD7687FCB6 /* ComponentBase.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + F84691EFFFCE729C9642D3110EF4385D /* ALView+PureLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = BC7375A662C818F404C6A619DB9F7CEF /* ALView+PureLayout.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + F869D5CDB92AFEAFB507B3BC097E87D6 /* BarChartDataProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 86122BE76B25FF9C7AF6EA44A5B7F04C /* BarChartDataProvider.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + F87B87AB390DE5D24C4CAE8C30108A16 /* BubbleChartDataProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1341768F552F0BBF2C86A715DA0A0FFA /* BubbleChartDataProvider.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + F8BB86EAA51DCC2F1121B7907EC5D21B /* WYStoryboardPopoverSegue.m in Sources */ = {isa = PBXBuildFile; fileRef = 002FD561FEA3D1497BD28C97A563E968 /* WYStoryboardPopoverSegue.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + FA61E357CF88BC5817DF5628C8C143CE /* CandleChartDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 825DF301497E57E00BC477A931E70268 /* CandleChartDataSet.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + FC7DC5345AC5BD330F9F9C640151C745 /* CandleStickChartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE5A0086B8B491233ACA0A363FE9294E /* CandleStickChartView.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + FDE4713E6FF767EC7157F283F969F8F9 /* ChartHighlighter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DCFD4B2CC0B5EC3A172CBD1531B747E /* ChartHighlighter.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + FE3BC02AF9FEFFA71AE4E0D8A3FB2B39 /* MarkerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5989CCB3F818BFA70ACE40F1730955AF /* MarkerView.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + FF3FE753D8E3A0AFB85E4CB28425FBDB /* ILineChartDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 358E5C11378F76DF53DC2D731F9B92E1 /* ILineChartDataSet.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 040DD17F67F5C6B36829805EACF08718 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; + proxyType = 1; + remoteGlobalIDString = 99E8E0D6846CC782E53B7D73C11ACDEA; + remoteInfo = UICircularProgressRing; + }; + 05CDBDD70C914ACD03F036471172EF25 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; + proxyType = 1; + remoteGlobalIDString = EBFD1DA8DB9C5E9C282BBCAD1778A64A; + remoteInfo = Charts; + }; + 25E062511F4390B4257132C49EE53E4F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5DA9D424D96F4D772D20C95ED50F5163; + remoteInfo = MZTimerLabel; + }; + 3BBE37EBD44CEEB1E429393BED020020 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; + proxyType = 1; + remoteGlobalIDString = 50C8BE3E50EE30CE69A6C1715D047E60; + remoteInfo = XMLDictionary; + }; + 407678FCDA2391826312C39C873E2AD7 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; + proxyType = 1; + remoteGlobalIDString = E715D783410216803ED82EC21CD5C31B; + remoteInfo = "IP-UIKit-Wisdom"; + }; + 44A6874453B72EF4CF0C7B9638E1D13B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5DA9D424D96F4D772D20C95ED50F5163; + remoteInfo = MZTimerLabel; + }; + 44AF829F114F5BD47234D263B4EAB240 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; + proxyType = 1; + remoteGlobalIDString = 50C8BE3E50EE30CE69A6C1715D047E60; + remoteInfo = XMLDictionary; + }; + 4CBBAB53C5F10A9FB624045976C15702 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; + proxyType = 1; + remoteGlobalIDString = EBFD1DA8DB9C5E9C282BBCAD1778A64A; + remoteInfo = Charts; + }; + 522366C4E5099B8A66E08AADD0680DD6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; + proxyType = 1; + remoteGlobalIDString = AEF4BF40039DBEDE68615E1A32E2E805; + remoteInfo = WYPopoverController; + }; + 52B7B5FBB8B8568C1FE07E1753E01833 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5DA9D424D96F4D772D20C95ED50F5163; + remoteInfo = MZTimerLabel; + }; + 569A85FBF454A6E63613619791CBA011 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5FA4F2F40241D9CBE948E0161E4C428D; + remoteInfo = "Eddystone-Eddystone"; + }; + 58F9B8BEFF51945699F440DB027C2C7A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5B03F2322DD9BCD22A8A37FD2E19849B; + remoteInfo = KVOController; + }; + 590CB6C0B8C316790FFACDBCBB241F9B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5B03F2322DD9BCD22A8A37FD2E19849B; + remoteInfo = KVOController; + }; + 59EA880CC6611A4B1EC3710D4F1FEEFF /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4273171B8F85B95806C7A7AEE258783F; + remoteInfo = ChameleonFramework; + }; + 5D4A0B9EA3E7783BC2BB0787D5709E96 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; + proxyType = 1; + remoteGlobalIDString = 212B86B3B83BCB71159494262747DFCF; + remoteInfo = PureLayout; + }; + 64B296C2BB7428DBED433726048E65DD /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; + proxyType = 1; + remoteGlobalIDString = E384B3C7B2878E9354E03BBC33901EA0; + remoteInfo = SVProgressHUD; + }; + 67CE2FA5E1438668ED773C446A65FAB5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; + proxyType = 1; + remoteGlobalIDString = E715D783410216803ED82EC21CD5C31B; + remoteInfo = "IP-UIKit-Wisdom"; + }; + 7C837EC14B9CAB3814A0E3D71E872F61 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; + proxyType = 1; + remoteGlobalIDString = 05B9852E4B188EF4EC93B1E3F0712B2E; + remoteInfo = "ActionSheetPicker-3.0"; + }; + 82B785194AFF67069223E549294CEFCE /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; + proxyType = 1; + remoteGlobalIDString = E715D783410216803ED82EC21CD5C31B; + remoteInfo = "IP-UIKit-Wisdom"; + }; + 8418229DD880FC1765DD23B913A04D49 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8D721B7ADC82CCCBC060EAA131A0A40A; + remoteInfo = Eddystone; + }; + 873988AD012BB421C984D9F002F81375 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; + proxyType = 1; + remoteGlobalIDString = AEF4BF40039DBEDE68615E1A32E2E805; + remoteInfo = WYPopoverController; + }; + 99DF5180C3163A766D4895990205331C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; + proxyType = 1; + remoteGlobalIDString = 05B9852E4B188EF4EC93B1E3F0712B2E; + remoteInfo = "ActionSheetPicker-3.0"; + }; + A5F2769EF1110B78E66270702F5D7563 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5B03F2322DD9BCD22A8A37FD2E19849B; + remoteInfo = KVOController; + }; + AA39FC7EDDB0B3734F3D8E7E48B9D487 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8D721B7ADC82CCCBC060EAA131A0A40A; + remoteInfo = Eddystone; + }; + AC7E0B9063E818CE46D2BCC7FA52FC37 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; + proxyType = 1; + remoteGlobalIDString = 212B86B3B83BCB71159494262747DFCF; + remoteInfo = PureLayout; + }; + B712C713D53B0D09D2CD708B43686731 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; + proxyType = 1; + remoteGlobalIDString = E384B3C7B2878E9354E03BBC33901EA0; + remoteInfo = SVProgressHUD; + }; + BB826E264CF976047CBAA5FB746D47FC /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; + proxyType = 1; + remoteGlobalIDString = 99E8E0D6846CC782E53B7D73C11ACDEA; + remoteInfo = UICircularProgressRing; + }; + C1D53C1DF89B8FE890E0A6AF60E1B95F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8D721B7ADC82CCCBC060EAA131A0A40A; + remoteInfo = Eddystone; + }; + C715AB70E2286971F58FB7BE2B4E2838 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; + proxyType = 1; + remoteGlobalIDString = 212B86B3B83BCB71159494262747DFCF; + remoteInfo = PureLayout; + }; + CB80A012B789FDB0E22747FA4821598C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; + proxyType = 1; + remoteGlobalIDString = 05B9852E4B188EF4EC93B1E3F0712B2E; + remoteInfo = "ActionSheetPicker-3.0"; + }; + CE34B180FE67D0E5442E72663BFA4D10 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; + proxyType = 1; + remoteGlobalIDString = AEF4BF40039DBEDE68615E1A32E2E805; + remoteInfo = WYPopoverController; + }; + D4598A2A1ACA0BAACBB5F59BF4E8655B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; + proxyType = 1; + remoteGlobalIDString = EBFD1DA8DB9C5E9C282BBCAD1778A64A; + remoteInfo = Charts; + }; + E16148F780C67003B95D64D23C828559 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4273171B8F85B95806C7A7AEE258783F; + remoteInfo = ChameleonFramework; + }; + E175C78B42F5B8EE323175F3E7AA7FB9 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4273171B8F85B95806C7A7AEE258783F; + remoteInfo = ChameleonFramework; + }; + F543B5BE201BDDFA99A50D89F635C002 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; + proxyType = 1; + remoteGlobalIDString = 50C8BE3E50EE30CE69A6C1715D047E60; + remoteInfo = XMLDictionary; + }; + F77856B5F0E5626B2F2CD27C5F42FC8B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; + proxyType = 1; + remoteGlobalIDString = E384B3C7B2878E9354E03BBC33901EA0; + remoteInfo = SVProgressHUD; + }; + FE83736314FFFCA50CCD6E11E03BDCCA /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; + proxyType = 1; + remoteGlobalIDString = 99E8E0D6846CC782E53B7D73C11ACDEA; + remoteInfo = UICircularProgressRing; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 002FD561FEA3D1497BD28C97A563E968 /* WYStoryboardPopoverSegue.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = WYStoryboardPopoverSegue.m; path = WYPopoverController/WYStoryboardPopoverSegue.m; sourceTree = ""; }; + 00DE8F8453D74BA2667E3E8086ABDD4A /* CandleChartData.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CandleChartData.swift; path = Source/Charts/Data/Implementations/Standard/CandleChartData.swift; sourceTree = ""; }; + 0229BF4F30B91B908D0DDBB40F9D9D31 /* CAGradientLayer+IPGradients.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "CAGradientLayer+IPGradients.m"; path = "src/CAGradientLayer/CAGradientLayer+IPGradients.m"; sourceTree = ""; }; + 024874D192E414F673383336E47E8011 /* ActionSheetStringPicker.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = ActionSheetStringPicker.h; path = Pickers/ActionSheetStringPicker.h; sourceTree = ""; }; + 025F3ABB22FDA99968B420F91E511D2A /* Scanner.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Scanner.swift; path = Pod/Classes/Scanner.swift; sourceTree = ""; }; + 031C1A1D4169F31403D9CBE6EF4B294B /* IPieChartDataSet.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = IPieChartDataSet.swift; path = Source/Charts/Data/Interfaces/IPieChartDataSet.swift; sourceTree = ""; }; + 04190BCB6CCD576431A82519AEE11E5A /* WYPopoverController.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = WYPopoverController.h; path = WYPopoverController/WYPopoverController.h; sourceTree = ""; }; + 0461CFEB46E08F25B56551C6A3C90472 /* UITableView+Utils.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UITableView+Utils.m"; path = "src/UITableView/UITableView+Utils.m"; sourceTree = ""; }; + 0490899449C723E7EC451A97FC77E5B9 /* RadarChartData.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = RadarChartData.swift; path = Source/Charts/Data/Implementations/Standard/RadarChartData.swift; sourceTree = ""; }; + 05AAE3AC4D5202C769F162FEF75D2E8B /* UIColor+Chameleon.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIColor+Chameleon.h"; path = "Pod/Classes/Objective-C/UIColor+Chameleon.h"; sourceTree = ""; }; + 072E19AD36FEF0C7BD2509195C2E122F /* IP-UIKit-Wisdom-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "IP-UIKit-Wisdom-prefix.pch"; sourceTree = ""; }; + 0A55D7A54C24B18ABB272F3F03760549 /* FBKVOController.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FBKVOController.m; path = FBKVOController/FBKVOController.m; sourceTree = ""; }; + 0A9984E2583E990609E9322A2CAB42C6 /* BarLineScatterCandleBubbleRenderer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BarLineScatterCandleBubbleRenderer.swift; path = Source/Charts/Renderers/BarLineScatterCandleBubbleRenderer.swift; sourceTree = ""; }; + 0AF09D04470F6A0FFBEB4247213736CE /* Pods-BlueGeckoWithHomeKit-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-BlueGeckoWithHomeKit-resources.sh"; sourceTree = ""; }; + 0C7BEF7AED5E42ED9B4819573519C515 /* CombinedChartData.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CombinedChartData.swift; path = Source/Charts/Data/Implementations/Standard/CombinedChartData.swift; sourceTree = ""; }; + 0CA40134452942E2A6CCCC7C47BCDE6E /* Uid.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Uid.swift; path = Pod/Classes/Uid.swift; sourceTree = ""; }; + 0D4B9267F4B053000B880E717283CCB2 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 0DCFD4B2CC0B5EC3A172CBD1531B747E /* ChartHighlighter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ChartHighlighter.swift; path = Source/Charts/Highlight/ChartHighlighter.swift; sourceTree = ""; }; + 0ED5292E2C23E871A0927BE6E4185FA5 /* Pods-WirelessGecko.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-WirelessGecko.modulemap"; sourceTree = ""; }; + 0FD65FD699B7A177648422A2B1CA70EE /* ActionSheetLocalePicker.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = ActionSheetLocalePicker.h; path = Pickers/ActionSheetLocalePicker.h; sourceTree = ""; }; + 0FF654CBD08386066DA5FC6DBDCFA5E3 /* XMLDictionary.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = XMLDictionary.framework; path = XMLDictionary.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 0FFC441E8AB88D1D4A267AE6C1013EFE /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 10123A0B7CC9766884B76E327E60A222 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 11E6DB3330CBDD52707CDF6E1C33A283 /* HorizontalBarChartView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = HorizontalBarChartView.swift; path = Source/Charts/Charts/HorizontalBarChartView.swift; sourceTree = ""; }; + 12183893149307FB085B68D57B1DEF66 /* ActionSheetPicker-3.0-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "ActionSheetPicker-3.0-dummy.m"; sourceTree = ""; }; + 12D031A69C52A7AC31D772114B2770F3 /* Eddystone-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Eddystone-umbrella.h"; sourceTree = ""; }; + 1341768F552F0BBF2C86A715DA0A0FFA /* BubbleChartDataProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BubbleChartDataProvider.swift; path = Source/Charts/Interfaces/BubbleChartDataProvider.swift; sourceTree = ""; }; + 137715DB8D84D99D2D291D8BB8E0CB98 /* ChameleonFramework.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = ChameleonFramework.modulemap; sourceTree = ""; }; + 14CD451ABCB610CFD12F47CAFF7BE531 /* NSArray+Chameleon.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSArray+Chameleon.m"; path = "Pod/Classes/Objective-C/NSArray+Chameleon.m"; sourceTree = ""; }; + 15BB98E46064549F9D687CB2734C6011 /* ActionSheetCustomPicker.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = ActionSheetCustomPicker.h; path = Pickers/ActionSheetCustomPicker.h; sourceTree = ""; }; + 15D70592F205341C68F9571682E433E7 /* ILineScatterCandleRadarChartDataSet.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ILineScatterCandleRadarChartDataSet.swift; path = Source/Charts/Data/Interfaces/ILineScatterCandleRadarChartDataSet.swift; sourceTree = ""; }; + 15FD537E0175B3C57E5421243EF658DB /* KVOController.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = KVOController.framework; path = KVOController.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 16CDC0EC422748B94114F308A908E51E /* IRadarChartDataSet.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = IRadarChartDataSet.swift; path = Source/Charts/Data/Interfaces/IRadarChartDataSet.swift; sourceTree = ""; }; + 176C4897F7F7A432B12A37BB4CC52EC6 /* PureLayout-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "PureLayout-dummy.m"; sourceTree = ""; }; + 177040E6D2D515FBF376337FD0273F59 /* Pods_BlueGecko.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_BlueGecko.framework; path = "Pods-BlueGecko.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; + 18C3F75647C4C195F26341298A87A180 /* XMLDictionary-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "XMLDictionary-umbrella.h"; sourceTree = ""; }; + 1A65EA7D791FCFF30973B7E6308FEC92 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1B336EDE579D4A86FD139ECB8D22B45E /* ActionSheetDistancePicker.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = ActionSheetDistancePicker.m; path = Pickers/ActionSheetDistancePicker.m; sourceTree = ""; }; + 1C94D25E7BF4C82F3F0FC450078C7D2B /* UIColor+ChameleonPrivate.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIColor+ChameleonPrivate.m"; path = "Pod/Classes/Objective-C/UIColor+ChameleonPrivate.m"; sourceTree = ""; }; + 1CD1F5A0BC106C02AC57A8F494FA748F /* NSArray+Chameleon.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSArray+Chameleon.h"; path = "Pod/Classes/Objective-C/NSArray+Chameleon.h"; sourceTree = ""; }; + 1E17B506648944D28343B82A00BAA8C4 /* Charts.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Charts.framework; path = Charts.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 1E3597E096BD1541EFC48B34E4899601 /* KVOController.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = KVOController.xcconfig; sourceTree = ""; }; + 1EAAAF5D5A1A5776B31EB0FA5C0E0F4E /* IShapeRenderer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = IShapeRenderer.swift; path = Source/Charts/Renderers/Scatter/IShapeRenderer.swift; sourceTree = ""; }; + 1F1C3175156D68F09309C6D90C0DA3B9 /* ActionSheetMultipleStringPicker.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = ActionSheetMultipleStringPicker.h; path = Pickers/ActionSheetMultipleStringPicker.h; sourceTree = ""; }; + 1F2C6B76362F95DA7C7D59F803049517 /* Range.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Range.swift; path = Source/Charts/Highlight/Range.swift; sourceTree = ""; }; + 1FA393BEE7E406E40ACD955FF8EEF18F /* XMLDictionary-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "XMLDictionary-prefix.pch"; sourceTree = ""; }; + 1FC3412280E72BE4AF1388DCDDA2D308 /* UICircularProgressRingGradientPosition.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = UICircularProgressRingGradientPosition.swift; path = src/UICircularProgressRing/UICircularProgressRingGradientPosition.swift; sourceTree = ""; }; + 200DC0152261F9AA7276C30BE32A9C8C /* XShapeRenderer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = XShapeRenderer.swift; path = Source/Charts/Renderers/Scatter/XShapeRenderer.swift; sourceTree = ""; }; + 219F6CF3CCC811E9083AA2F13750F9E9 /* HorizontalBarHighlighter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = HorizontalBarHighlighter.swift; path = Source/Charts/Highlight/HorizontalBarHighlighter.swift; sourceTree = ""; }; + 24F153C0771D8D8EBE02DE904B282195 /* Pods-WirelessGecko.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-WirelessGecko.debug.xcconfig"; sourceTree = ""; }; + 25C0783D77DD9E95A5DDFD863D8A39E8 /* PieChartData.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PieChartData.swift; path = Source/Charts/Data/Implementations/Standard/PieChartData.swift; sourceTree = ""; }; + 2608767335B92B9DA52F41E87B58A9F1 /* MZTimerLabel.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MZTimerLabel.m; path = MZTimerLabel/MZTimerLabel.m; sourceTree = ""; }; + 2612F4C6AD646E9719C2BBD4022C2ADE /* LineChartData.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = LineChartData.swift; path = Source/Charts/Data/Implementations/Standard/LineChartData.swift; sourceTree = ""; }; + 273C7DC661C73862256E8F1E24C36458 /* BarLineScatterCandleBubbleChartDataProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BarLineScatterCandleBubbleChartDataProvider.swift; path = Source/Charts/Interfaces/BarLineScatterCandleBubbleChartDataProvider.swift; sourceTree = ""; }; + 2B63F45487A8F5DB53C658E9CA920AF0 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 2CB215F35A867E9CF61FC553B61D4F6D /* MZTimerLabel-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "MZTimerLabel-umbrella.h"; sourceTree = ""; }; + 2CD0A3FA3E70958D084098CAC95338F3 /* ChameleonConstants.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = ChameleonConstants.m; path = "Pod/Classes/Objective-C/ChameleonConstants.m"; sourceTree = ""; }; + 2CF24195C175E960490AB9D5477BFD87 /* LineChartRenderer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = LineChartRenderer.swift; path = Source/Charts/Renderers/LineChartRenderer.swift; sourceTree = ""; }; + 2F73756828B80DDCA6EF49CA5F26F168 /* ChameleonFramework-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "ChameleonFramework-dummy.m"; sourceTree = ""; }; + 303726B29FCA0EAB7FA43803BB2FFC46 /* UrlFrame.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = UrlFrame.swift; path = Pod/Classes/UrlFrame.swift; sourceTree = ""; }; + 331778CD5CA75B334ED64534D22AED30 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 336BA1494AA67B6F791FF4FB3AF34FB2 /* UINavigationController+Chameleon.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UINavigationController+Chameleon.h"; path = "Pod/Classes/Objective-C/UINavigationController+Chameleon.h"; sourceTree = ""; }; + 33D149F302D5CF9FA1F7308DAF0ABD5B /* AnimatedViewPortJob.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AnimatedViewPortJob.swift; path = Source/Charts/Jobs/AnimatedViewPortJob.swift; sourceTree = ""; }; + 3471AE3783802E123428196BF7F2C48B /* LineRadarChartDataSet.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = LineRadarChartDataSet.swift; path = Source/Charts/Data/Implementations/Standard/LineRadarChartDataSet.swift; sourceTree = ""; }; + 358E5C11378F76DF53DC2D731F9B92E1 /* ILineChartDataSet.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ILineChartDataSet.swift; path = Source/Charts/Data/Interfaces/ILineChartDataSet.swift; sourceTree = ""; }; + 35D2F421107B1B0AAAF1A00095F56D53 /* RadarChartDataSet.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = RadarChartDataSet.swift; path = Source/Charts/Data/Implementations/Standard/RadarChartDataSet.swift; sourceTree = ""; }; + 36958433D03531713561115D14A4B289 /* UICircularProgressRingStyle.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = UICircularProgressRingStyle.swift; path = src/UICircularProgressRing/UICircularProgressRingStyle.swift; sourceTree = ""; }; + 37F49D184948DB3945E37E66E7854D7E /* XAxisRendererRadarChart.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = XAxisRendererRadarChart.swift; path = Source/Charts/Renderers/XAxisRendererRadarChart.swift; sourceTree = ""; }; + 389A3FE642BFDC7F2B5D76FAAE2EC913 /* ChartDataSet.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ChartDataSet.swift; path = Source/Charts/Data/Implementations/Standard/ChartDataSet.swift; sourceTree = ""; }; + 38A069D5E8D45C0192C4E76A29460F48 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 38AF2B25FCF8F38D923B2A8B9B5872FE /* RadarChartDataEntry.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = RadarChartDataEntry.swift; path = Source/Charts/Data/Implementations/Standard/RadarChartDataEntry.swift; sourceTree = ""; }; + 39142212EFDD9BDF3F5DDC66D222760A /* AbstractActionSheetPicker.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AbstractActionSheetPicker.h; path = Pickers/AbstractActionSheetPicker.h; sourceTree = ""; }; + 399399C6191136B400E65BC2F5803E77 /* Pods-BlueGeckoWithHomeKit-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-BlueGeckoWithHomeKit-acknowledgements.markdown"; sourceTree = ""; }; + 39D00D1E22849A388D7AB8362D50C1DD /* UIView+IPFrameUtils.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIView+IPFrameUtils.m"; path = "src/UIView/UIView+IPFrameUtils.m"; sourceTree = ""; }; + 3A1A4ADB688FA25351F308695E3392F7 /* BubbleChartData.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BubbleChartData.swift; path = Source/Charts/Data/Implementations/Standard/BubbleChartData.swift; sourceTree = ""; }; + 3B324A581DDD6EA8E88C978D063B53DA /* SVProgressHUD.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SVProgressHUD.m; path = SVProgressHUD/SVProgressHUD.m; sourceTree = ""; }; + 3BB1150EA100AD0F94AE6B49B9682CE4 /* Eddystone-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Eddystone-prefix.pch"; sourceTree = ""; }; + 3BF45EB6B838A2578EE62E2942C14FE0 /* ChameleonFramework.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = ChameleonFramework.framework; path = ChameleonFramework.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 3C12CA761777232CB084C77ECD8F64D2 /* UILabel+Chameleon.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UILabel+Chameleon.h"; path = "Pod/Classes/Objective-C/UILabel+Chameleon.h"; sourceTree = ""; }; + 3C1D93D382918BCF3CA502D4F94AAAA5 /* CircleShapeRenderer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CircleShapeRenderer.swift; path = Source/Charts/Renderers/Scatter/CircleShapeRenderer.swift; sourceTree = ""; }; + 3C6867A262E67FC1C407DBC28783F77E /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 3CBD6C421C3B20CA83FEF5F4894B4D4B /* Pods-WirelessGecko-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-WirelessGecko-dummy.m"; sourceTree = ""; }; + 3E3C794FD85107420F8B9D1D8EAE5451 /* UIImage+ChameleonPrivate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImage+ChameleonPrivate.h"; path = "Pod/Classes/Objective-C/UIImage+ChameleonPrivate.h"; sourceTree = ""; }; + 3F36FA7BD17CF42413AB49F4B85512BB /* SVProgressAnimatedView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SVProgressAnimatedView.m; path = SVProgressHUD/SVProgressAnimatedView.m; sourceTree = ""; }; + 3F6A9685BFC90D3A596AD7B760053227 /* Pods-BlueGecko.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-BlueGecko.release.xcconfig"; sourceTree = ""; }; + 406BF982BD3C5E9EEE3123C9441A7E73 /* UIView+IPAncestry.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIView+IPAncestry.h"; path = "src/UIView/UIView+IPAncestry.h"; sourceTree = ""; }; + 42B2EEC771BA840AE50CB797B0F162F8 /* CombinedChartRenderer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CombinedChartRenderer.swift; path = Source/Charts/Renderers/CombinedChartRenderer.swift; sourceTree = ""; }; + 432C3FC422E42C5D6C5E28256E4968B7 /* MoveViewJob.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MoveViewJob.swift; path = Source/Charts/Jobs/MoveViewJob.swift; sourceTree = ""; }; + 445B3D0F1F70C467F508C347E6ECC326 /* Pods-BlueGecko-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-BlueGecko-umbrella.h"; sourceTree = ""; }; + 44CD6AB8092A99D142C017FC4621AE8A /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 45059F949099ABAAD358FB1A3586CD3A /* Fill.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Fill.swift; path = Source/Charts/Utils/Fill.swift; sourceTree = ""; }; + 45709024E87F53D94EA3E6CB7463C190 /* SVIndefiniteAnimatedView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SVIndefiniteAnimatedView.m; path = SVProgressHUD/SVIndefiniteAnimatedView.m; sourceTree = ""; }; + 478CF550BE7D801EB6E55E5D4CFE151A /* IBubbleChartDataSet.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = IBubbleChartDataSet.swift; path = Source/Charts/Data/Interfaces/IBubbleChartDataSet.swift; sourceTree = ""; }; + 47E053279BCB14FD7D9DCF76AA6B4CBE /* UIView+NibInitable.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIView+NibInitable.h"; path = "src/UIView/UIView+NibInitable.h"; sourceTree = ""; }; + 4809C50ED705FC7AA75BA712BEA3E606 /* SVProgressHUD.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = SVProgressHUD.modulemap; sourceTree = ""; }; + 4A1C73A26B8BA66527D199ABCE9F3C98 /* WYPopoverController.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = WYPopoverController.xcconfig; sourceTree = ""; }; + 4A3B168913F0573313A17DDB4317B3B2 /* IChartDataSet.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = IChartDataSet.swift; path = Source/Charts/Data/Interfaces/IChartDataSet.swift; sourceTree = ""; }; + 4D5A9E2EC3DD2F51BA182A00E5DEC6E3 /* KVOController-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "KVOController-umbrella.h"; sourceTree = ""; }; + 4D7285B8C5720CD543F416409A3B443E /* UIImage+ColorMaskedImage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImage+ColorMaskedImage.h"; path = "src/UIImage/UIImage+ColorMaskedImage.h"; sourceTree = ""; }; + 4D9D9C5B78F513003B8393913329AC75 /* Eddystone.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Eddystone.xcconfig; sourceTree = ""; }; + 4E872B141543C04195F4AA6253DCB46A /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; + 4F1ED9B0B53CB5D2EE236D8CB7EDBC29 /* IP_UIKit_Wisdom.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = IP_UIKit_Wisdom.framework; path = "IP-UIKit-Wisdom.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; + 504690566E595BB0A03D20B7BA480ABC /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.0.sdk/System/Library/Frameworks/QuartzCore.framework; sourceTree = DEVELOPER_DIR; }; + 505136F6C931876302F18B5A06035CA7 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 513761915E3ED039E2120E0FF8B65600 /* BubbleChartDataEntry.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BubbleChartDataEntry.swift; path = Source/Charts/Data/Implementations/Standard/BubbleChartDataEntry.swift; sourceTree = ""; }; + 516B0ED428665BD90D818DEE11C340B9 /* Chameleon_.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = Chameleon_.m; path = "Pod/Classes/Objective-C/Chameleon_.m"; sourceTree = ""; }; + 530DA5F79FC49F4F24129ACF69B64177 /* UINavigationController+Chameleon.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UINavigationController+Chameleon.m"; path = "Pod/Classes/Objective-C/UINavigationController+Chameleon.m"; sourceTree = ""; }; + 544145B0B14DBBD37A7AD8E40B5F0456 /* BarChartDataSet.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BarChartDataSet.swift; path = Source/Charts/Data/Implementations/Standard/BarChartDataSet.swift; sourceTree = ""; }; + 54663D619A0D3881CE170F7EE40A8CF9 /* NSArray+PureLayout.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSArray+PureLayout.m"; path = "PureLayout/PureLayout/NSArray+PureLayout.m"; sourceTree = ""; }; + 54C0A5BFB438BA11FB583A383BD621CA /* Charts.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = Charts.modulemap; sourceTree = ""; }; + 54E6CCB4DDD5185E52FB9F09B31D815A /* MZTimerLabel.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = MZTimerLabel.framework; path = MZTimerLabel.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 558F2F7A2DC6222F1FF0FA94D5957844 /* XMLDictionary.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = XMLDictionary.h; path = XMLDictionary/XMLDictionary.h; sourceTree = ""; }; + 55EEDB11AB6F96E6F97DC96F2C476230 /* IP-UIKit-Wisdom.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "IP-UIKit-Wisdom.xcconfig"; sourceTree = ""; }; + 569BA96B108F04FD9CC4CD686513297E /* PureLayoutDefines.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = PureLayoutDefines.h; path = PureLayout/PureLayout/PureLayoutDefines.h; sourceTree = ""; }; + 56F8646F89CBE3CC0FF913D2B1B52E8A /* UIImage+ColorMaskedImage.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImage+ColorMaskedImage.m"; path = "src/UIImage/UIImage+ColorMaskedImage.m"; sourceTree = ""; }; + 570A1B1BC5E57682C35D8D67DA876885 /* Eddystone.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; name = Eddystone.bundle; path = "Eddystone-Eddystone.bundle"; sourceTree = BUILT_PRODUCTS_DIR; }; + 57634E7A180647CF43FBC74A5BD446F3 /* LineScatterCandleRadarChartDataSet.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = LineScatterCandleRadarChartDataSet.swift; path = Source/Charts/Data/Implementations/Standard/LineScatterCandleRadarChartDataSet.swift; sourceTree = ""; }; + 58F964009ECA3B64814787A3435B10BD /* ViewPortJob.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ViewPortJob.swift; path = Source/Charts/Jobs/ViewPortJob.swift; sourceTree = ""; }; + 593927968B65C54CDBDAE2DCFDA383D2 /* Pods-BlueGecko-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-BlueGecko-frameworks.sh"; sourceTree = ""; }; + 5989CCB3F818BFA70ACE40F1730955AF /* MarkerView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MarkerView.swift; path = Source/Charts/Components/MarkerView.swift; sourceTree = ""; }; + 5A0D91B6CCA43C65C5E5AFF3DB9B1F50 /* UIViewController+Chameleon.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIViewController+Chameleon.h"; path = "Pod/Classes/Objective-C/UIViewController+Chameleon.h"; sourceTree = ""; }; + 5A22154EBF2F0DE92536644E78FA6A5D /* SVProgressHUD.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SVProgressHUD.h; path = SVProgressHUD/SVProgressHUD.h; sourceTree = ""; }; + 5A3A22D5D7DFFBCC072A618962C29187 /* RadarChartRenderer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = RadarChartRenderer.swift; path = Source/Charts/Renderers/RadarChartRenderer.swift; sourceTree = ""; }; + 5B84E7008E8ED3FEE44C7E74AA1EB1AD /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 5C33F8227CCE6399F69AFDC719E0DEB9 /* DefaultValueFormatter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = DefaultValueFormatter.swift; path = Source/Charts/Formatters/DefaultValueFormatter.swift; sourceTree = ""; }; + 5C94721C4A0B4B47781D9AA1C5DF1ACF /* Legend.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Legend.swift; path = Source/Charts/Components/Legend.swift; sourceTree = ""; }; + 5D42210E27817B3FB477DA7FB69F030D /* WYPopoverController.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = WYPopoverController.modulemap; sourceTree = ""; }; + 5E063F0C244C3ED32C67EC74FCD5E4AF /* BarChartDataEntry.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BarChartDataEntry.swift; path = Source/Charts/Data/Implementations/Standard/BarChartDataEntry.swift; sourceTree = ""; }; + 5E106DA25719FD85DCF726D5B7128773 /* Charts-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Charts-prefix.pch"; sourceTree = ""; }; + 5E7F96C3694731B746BDA5FE375B7FFC /* UIButton+IPUtils.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIButton+IPUtils.h"; path = "src/UIButton/UIButton+IPUtils.h"; sourceTree = ""; }; + 5EC623EFD593FF4960B3618BE14F5630 /* CAGradientLayer+IPGradients.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "CAGradientLayer+IPGradients.h"; path = "src/CAGradientLayer/CAGradientLayer+IPGradients.h"; sourceTree = ""; }; + 5F2B4631847D37507D49C3BDF1244ACB /* UICircularProgressRing-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "UICircularProgressRing-umbrella.h"; sourceTree = ""; }; + 60636B604BABF9DE0CC5107B72A0BCF9 /* TriangleShapeRenderer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TriangleShapeRenderer.swift; path = Source/Charts/Renderers/Scatter/TriangleShapeRenderer.swift; sourceTree = ""; }; + 615EB05A5D732CD0F7153D6D8294F3CF /* ActionSheetPicker_3_0.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = ActionSheetPicker_3_0.framework; path = "ActionSheetPicker-3.0.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; + 6174E65A0E21BA21D32E3C972B070371 /* UICircularProgressRing-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "UICircularProgressRing-dummy.m"; sourceTree = ""; }; + 61C4F376C04A8E77F23D0F3AD6A9E95D /* UIColor+IPRandomColor.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIColor+IPRandomColor.m"; path = "src/UIColor/UIColor+IPRandomColor.m"; sourceTree = ""; }; + 620F97B263A04521A767E9838781254F /* Generic.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Generic.swift; path = Pod/Classes/Generic.swift; sourceTree = ""; }; + 63F658BBCC7371AB5CA6BC9BBF022159 /* UIViewController+Containment.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIViewController+Containment.m"; path = "src/UIViewController/UIViewController+Containment.m"; sourceTree = ""; }; + 643484DF9098D57753F164AB155E2D8B /* DefaultFillFormatter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = DefaultFillFormatter.swift; path = Source/Charts/Formatters/DefaultFillFormatter.swift; sourceTree = ""; }; + 65B77D36C6A6C8F5149CC077A793CAEA /* PureLayout.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = PureLayout.modulemap; sourceTree = ""; }; + 65D9CBA1C9C448F48A1B55B1E0D465D2 /* BubbleChartRenderer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BubbleChartRenderer.swift; path = Source/Charts/Renderers/BubbleChartRenderer.swift; sourceTree = ""; }; + 660FDCC8D1D1C260A6C9AFC394C62175 /* NSLayoutConstraint+PureLayout.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSLayoutConstraint+PureLayout.h"; path = "PureLayout/PureLayout/NSLayoutConstraint+PureLayout.h"; sourceTree = ""; }; + 67949A93DA0CE3246D1073C194798C1D /* ActionSheetCustomPickerDelegate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = ActionSheetCustomPickerDelegate.h; path = Pickers/ActionSheetCustomPickerDelegate.h; sourceTree = ""; }; + 679DA6BE5AD33B38F3A7E14AA89CB2C9 /* HorizontalBarChartRenderer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = HorizontalBarChartRenderer.swift; path = Source/Charts/Renderers/HorizontalBarChartRenderer.swift; sourceTree = ""; }; + 683F26A72165D255BCDA83A03B0E4BCD /* Eddystone-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Eddystone-dummy.m"; sourceTree = ""; }; + 691E229FAC3EF29B4F989FB5BAF1999D /* Pods-WirelessGecko.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-WirelessGecko.release.xcconfig"; sourceTree = ""; }; + 6A353EA5D77D5A677BB2A7CC8C0200C1 /* ChameleonEnums.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = ChameleonEnums.h; path = "Pod/Classes/Objective-C/ChameleonEnums.h"; sourceTree = ""; }; + 6A8E67432D41F0ED22EF1767FE3FD7BC /* UICircularProgressRingLayer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = UICircularProgressRingLayer.swift; path = src/UICircularProgressRing/UICircularProgressRingLayer.swift; sourceTree = ""; }; + 6B20E8445BA0DDD43FB3071C1C0E4BD6 /* AnimatedZoomViewJob.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AnimatedZoomViewJob.swift; path = Source/Charts/Jobs/AnimatedZoomViewJob.swift; sourceTree = ""; }; + 6BB8DF922263956771255F26D1DF0ABD /* SVProgressHUD-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SVProgressHUD-umbrella.h"; sourceTree = ""; }; + 6C48E807343CABA2262D85BFE1A1D8BA /* ChartDataRendererBase.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ChartDataRendererBase.swift; path = Source/Charts/Renderers/ChartDataRendererBase.swift; sourceTree = ""; }; + 6D2F8F42E69A19C4EA3F859F7A0F512A /* AbstractActionSheetPicker.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AbstractActionSheetPicker.m; path = Pickers/AbstractActionSheetPicker.m; sourceTree = ""; }; + 6D48BFF0B5781A3D1EAEDF2A6C3D6B81 /* WYPopoverController.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = WYPopoverController.m; path = WYPopoverController/WYPopoverController.m; sourceTree = ""; }; + 6DF6D9D9AB6E5A2673FE8D86E15CBFD8 /* PureLayout.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = PureLayout.xcconfig; sourceTree = ""; }; + 6E43803662EE53000A57538DAA5A6B70 /* Url.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Url.swift; path = Pod/Classes/Url.swift; sourceTree = ""; }; + 6E6227BF90B1AAD393A68FB8234816CD /* CandleChartDataEntry.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CandleChartDataEntry.swift; path = Source/Charts/Data/Implementations/Standard/CandleChartDataEntry.swift; sourceTree = ""; }; + 6E9625AEF2DDDF05E981EC1CC74352E6 /* IBarLineScatterCandleBubbleChartDataSet.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = IBarLineScatterCandleBubbleChartDataSet.swift; path = Source/Charts/Data/Interfaces/IBarLineScatterCandleBubbleChartDataSet.swift; sourceTree = ""; }; + 6FE53421F581B66DF6A0AF5505042A96 /* XAxisRendererHorizontalBarChart.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = XAxisRendererHorizontalBarChart.swift; path = Source/Charts/Renderers/XAxisRendererHorizontalBarChart.swift; sourceTree = ""; }; + 7181A7AF7266173B7C8FB3AE317A77BF /* UIColor+ChameleonPrivate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIColor+ChameleonPrivate.h"; path = "Pod/Classes/Objective-C/UIColor+ChameleonPrivate.h"; sourceTree = ""; }; + 741CF545C29BBBD5B91CB19812F6F1AB /* BarLineScatterCandleBubbleChartData.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BarLineScatterCandleBubbleChartData.swift; path = Source/Charts/Data/Implementations/Standard/BarLineScatterCandleBubbleChartData.swift; sourceTree = ""; }; + 7477A476ADD5E869E1A4B11E8186721E /* ILineRadarChartDataSet.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ILineRadarChartDataSet.swift; path = Source/Charts/Data/Interfaces/ILineRadarChartDataSet.swift; sourceTree = ""; }; + 7481CF72D407C3ABE3C21CE4EA0663DF /* XAxisRenderer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = XAxisRenderer.swift; path = Source/Charts/Renderers/XAxisRenderer.swift; sourceTree = ""; }; + 74DB70308405A78C5D9B053473907B31 /* UIButton+IPUtils.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIButton+IPUtils.m"; path = "src/UIButton/UIButton+IPUtils.m"; sourceTree = ""; }; + 77AA3DA113378A3CD340D07AF9878B77 /* PieHighlighter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PieHighlighter.swift; path = Source/Charts/Highlight/PieHighlighter.swift; sourceTree = ""; }; + 7816EA5D91D0971F1BD9E2269ABDD6DB /* Pods-BlueGecko-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-BlueGecko-acknowledgements.plist"; sourceTree = ""; }; + 78CFE7161B732D7100419480AF27DF04 /* ActionSheetStringPicker.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = ActionSheetStringPicker.m; path = Pickers/ActionSheetStringPicker.m; sourceTree = ""; }; + 7A59D71277F8A7EBB7698E856B46D253 /* NSObject+FBKVOController.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSObject+FBKVOController.m"; path = "FBKVOController/NSObject+FBKVOController.m"; sourceTree = ""; }; + 7A6266FA2DC2B84E6EB17221047CB303 /* TlmFrame.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TlmFrame.swift; path = Pod/Classes/TlmFrame.swift; sourceTree = ""; }; + 7C6B867B228C9685532C77EC4B77893F /* WYPopoverController-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "WYPopoverController-prefix.pch"; sourceTree = ""; }; + 7C9254F379DC1DB830541F92590F4488 /* UIButton+Chameleon.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIButton+Chameleon.m"; path = "Pod/Classes/Objective-C/UIButton+Chameleon.m"; sourceTree = ""; }; + 7D20CD4B0F1917F76DBF804904257E7F /* YAxisRendererRadarChart.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = YAxisRendererRadarChart.swift; path = Source/Charts/Renderers/YAxisRendererRadarChart.swift; sourceTree = ""; }; + 7D46FFE9FA8DD84EAA516AE74508BD1A /* YAxisRendererHorizontalBarChart.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = YAxisRendererHorizontalBarChart.swift; path = Source/Charts/Renderers/YAxisRendererHorizontalBarChart.swift; sourceTree = ""; }; + 7E15B2865C9220510128DD12E8BCA588 /* UICircularProgressRingDelegate.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = UICircularProgressRingDelegate.swift; path = src/UICircularProgressRing/UICircularProgressRingDelegate.swift; sourceTree = ""; }; + 7E1663FBB43F97FD1F8C5074DB77FEC7 /* Renderer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Renderer.swift; path = Source/Charts/Renderers/Renderer.swift; sourceTree = ""; }; + 7FCEC7ED703FE901FF913298159DEA0C /* ScatterChartView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ScatterChartView.swift; path = Source/Charts/Charts/ScatterChartView.swift; sourceTree = ""; }; + 800785DCA911E2E3AE42AD4A0A4F1EC6 /* ActionSheetDatePicker.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = ActionSheetDatePicker.m; path = Pickers/ActionSheetDatePicker.m; sourceTree = ""; }; + 80106BF869F5D236D9896410F1E83729 /* UIAppearance+Swift.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIAppearance+Swift.m"; path = "Pod/Classes/Objective-C/UIAppearance+Swift.m"; sourceTree = ""; }; + 8072DE6C57BC4BF3AA233DB26AAA9EB0 /* ChartUtils.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ChartUtils.swift; path = Source/Charts/Utils/ChartUtils.swift; sourceTree = ""; }; + 80ACA67493C63D6EE695846006AA65D9 /* BarChartView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BarChartView.swift; path = Source/Charts/Charts/BarChartView.swift; sourceTree = ""; }; + 81787386F805E581DA154CB7C1A23CFA /* ChartBaseDataSet.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ChartBaseDataSet.swift; path = Source/Charts/Data/Implementations/ChartBaseDataSet.swift; sourceTree = ""; }; + 825DF301497E57E00BC477A931E70268 /* CandleChartDataSet.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CandleChartDataSet.swift; path = Source/Charts/Data/Implementations/Standard/CandleChartDataSet.swift; sourceTree = ""; }; + 827E476839A9B3D5C5DE6CE53EF74952 /* ChameleonFramework.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = ChameleonFramework.xcconfig; sourceTree = ""; }; + 82926FBBD1B0798B1F00AAA4397F2372 /* YAxisRenderer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = YAxisRenderer.swift; path = Source/Charts/Renderers/YAxisRenderer.swift; sourceTree = ""; }; + 82B47BBB47AA508581319CF64EDDA84C /* UICircularProgressRing.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = UICircularProgressRing.modulemap; sourceTree = ""; }; + 83BDE113AC6294183C2FCF0741961434 /* Pods-BlueGeckoWithHomeKit-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-BlueGeckoWithHomeKit-frameworks.sh"; sourceTree = ""; }; + 86122BE76B25FF9C7AF6EA44A5B7F04C /* BarChartDataProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BarChartDataProvider.swift; path = Source/Charts/Interfaces/BarChartDataProvider.swift; sourceTree = ""; }; + 8642C5BE3AB754F356C8DB11D0836BD2 /* ScatterChartDataProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ScatterChartDataProvider.swift; path = Source/Charts/Interfaces/ScatterChartDataProvider.swift; sourceTree = ""; }; + 8663053901ADA8C9A0577FEA61654E57 /* UICircularProgressRing.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = UICircularProgressRing.xcconfig; sourceTree = ""; }; + 86776919F26940B88993D5676026EB2B /* Frame.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Frame.swift; path = Pod/Classes/Frame.swift; sourceTree = ""; }; + 869BD6F301C2BCF357DEFDE087F0D06F /* ChameleonFramework-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "ChameleonFramework-prefix.pch"; sourceTree = ""; }; + 86A10CA50571306393F36FAD321FD71B /* KVOController.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = KVOController.h; path = FBKVOController/KVOController.h; sourceTree = ""; }; + 874D1A4C10E1A719AF9A96ADA25C2E5C /* ActionSheetPicker-3.0-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "ActionSheetPicker-3.0-prefix.pch"; sourceTree = ""; }; + 8A2CEAB98F32984CFE1E2BAD7687FCB6 /* ComponentBase.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ComponentBase.swift; path = Source/Charts/Components/ComponentBase.swift; sourceTree = ""; }; + 8C05186A656AF61E24A61B7ABD10CF87 /* Pods-WirelessGecko-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-WirelessGecko-resources.sh"; sourceTree = ""; }; + 8D6EF8626404CE5AA97A83FA08910E76 /* ChartViewBase.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ChartViewBase.swift; path = Source/Charts/Charts/ChartViewBase.swift; sourceTree = ""; }; + 8EBA1DD0ED252939E1BCA5C1B8578A45 /* CandleStickChartRenderer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CandleStickChartRenderer.swift; path = Source/Charts/Renderers/CandleStickChartRenderer.swift; sourceTree = ""; }; + 8FC40DD75DDD0B5E07D3A92A26F87C95 /* UIView+Constraints.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIView+Constraints.h"; path = "src/UIView/UIView+Constraints.h"; sourceTree = ""; }; + 902543F7869A31661B0AC19E3C9AE9C6 /* IMarker.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = IMarker.swift; path = Source/Charts/Components/IMarker.swift; sourceTree = ""; }; + 9027945388741C2D88415E3D7201D9EC /* ChameleonMacros.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = ChameleonMacros.h; path = "Pod/Classes/Objective-C/ChameleonMacros.h"; sourceTree = ""; }; + 903DC957219810A92394E22C6B19629D /* CombinedChartView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CombinedChartView.swift; path = Source/Charts/Charts/CombinedChartView.swift; sourceTree = ""; }; + 90A3B781B047A3280FE14967BCC59A4D /* TransformerHorizontalBarChart.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TransformerHorizontalBarChart.swift; path = Source/Charts/Utils/TransformerHorizontalBarChart.swift; sourceTree = ""; }; + 91E94BCA50C419D7C1B1B5E4FDBE3D2E /* AxisBase.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AxisBase.swift; path = Source/Charts/Components/AxisBase.swift; sourceTree = ""; }; + 927881679707E7BB35FBF5CCF8A0183A /* CombinedChartDataProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CombinedChartDataProvider.swift; path = Source/Charts/Interfaces/CombinedChartDataProvider.swift; sourceTree = ""; }; + 93151302C6ACEE98EA43A21A83585A38 /* ICandleChartDataSet.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ICandleChartDataSet.swift; path = Source/Charts/Data/Interfaces/ICandleChartDataSet.swift; sourceTree = ""; }; + 934072CF1F79CE797EB562EE16407C5B /* ALView+PureLayout.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "ALView+PureLayout.h"; path = "PureLayout/PureLayout/ALView+PureLayout.h"; sourceTree = ""; }; + 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + 944AE29058BAC80AB15D436CE874AFFF /* PureLayout-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "PureLayout-umbrella.h"; sourceTree = ""; }; + 94C3444270D503940943E477B3105B39 /* MZTimerLabel.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MZTimerLabel.h; path = MZTimerLabel/MZTimerLabel.h; sourceTree = ""; }; + 965D4237C5D838A4CF76399A7566B7EA /* PureLayout.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = PureLayout.framework; path = PureLayout.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 96919220F12F29935EABD3E47DEC7444 /* LineChartDataProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = LineChartDataProvider.swift; path = Source/Charts/Interfaces/LineChartDataProvider.swift; sourceTree = ""; }; + 96DC2C89C66682D28AC10AB157F59C00 /* UIViewController+Chameleon.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIViewController+Chameleon.m"; path = "Pod/Classes/Objective-C/UIViewController+Chameleon.m"; sourceTree = ""; }; + 974238420F393E9C2D8D7861B751177A /* MZTimerLabel.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = MZTimerLabel.modulemap; sourceTree = ""; }; + 97E5B70FBD11A68B3A9CD66E057AB5BC /* MarkerImage.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MarkerImage.swift; path = Source/Charts/Components/MarkerImage.swift; sourceTree = ""; }; + 985BC5A9FDFCD09FA3C33FD0313A280B /* Eddystone.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Eddystone.framework; path = Eddystone.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 98D10BE70758053EEECAB14726A3BE77 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 99FC4D414E8D92A3687B983B5DD082E7 /* ChartAnimationEasing.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ChartAnimationEasing.swift; path = Source/Charts/Animation/ChartAnimationEasing.swift; sourceTree = ""; }; + 9A8D2421C65541CCF69398D1E4E69307 /* ActionSheetPicker-3.0.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "ActionSheetPicker-3.0.modulemap"; sourceTree = ""; }; + 9CD0288571DA72DC1251D12E561A6271 /* XMLDictionary-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "XMLDictionary-dummy.m"; sourceTree = ""; }; + 9CEC245B78279AF03A87DC3867F4325D /* UIImage+ChameleonPrivate.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImage+ChameleonPrivate.m"; path = "Pod/Classes/Objective-C/UIImage+ChameleonPrivate.m"; sourceTree = ""; }; + 9D81B4AD7AE06F5508984C088568B1FC /* SVProgressHUD-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SVProgressHUD-prefix.pch"; sourceTree = ""; }; + 9EE21DBBF5702F3F31F823B4AFF90A30 /* PieChartView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PieChartView.swift; path = Source/Charts/Charts/PieChartView.swift; sourceTree = ""; }; + 9EE8B89B13BC78BB5EF06D06E96AE057 /* ActionSheetDistancePicker.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = ActionSheetDistancePicker.h; path = Pickers/ActionSheetDistancePicker.h; sourceTree = ""; }; + 9F7F0B2C801D84E4DBCC848D00DC4F5B /* Pods-BlueGeckoWithHomeKit.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-BlueGeckoWithHomeKit.debug.xcconfig"; sourceTree = ""; }; + 9F897B9413247295364D38AE83A36795 /* BarChartRenderer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BarChartRenderer.swift; path = Source/Charts/Renderers/BarChartRenderer.swift; sourceTree = ""; }; + A1982ED7CE88E71925D5F535C6C7A062 /* IntExtensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = IntExtensions.swift; path = Pod/Classes/IntExtensions.swift; sourceTree = ""; }; + A2254E1A588165AF3B57FA75E6701BA1 /* SVProgressAnimatedView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SVProgressAnimatedView.h; path = SVProgressHUD/SVProgressAnimatedView.h; sourceTree = ""; }; + A2FF71834CDD54D9F20FF33B199FCF2F /* ChameleonFramework-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "ChameleonFramework-umbrella.h"; sourceTree = ""; }; + A3376FA5C8A5D1B2D506D0C0F53E8604 /* Description.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Description.swift; path = Source/Charts/Components/Description.swift; sourceTree = ""; }; + A42C54279BC67244768580CFF31D4599 /* Pods-WirelessGecko-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-WirelessGecko-frameworks.sh"; sourceTree = ""; }; + A4FE66660693AED28587ACC5B8E64B1A /* PieRadarChartViewBase.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PieRadarChartViewBase.swift; path = Source/Charts/Charts/PieRadarChartViewBase.swift; sourceTree = ""; }; + A51C44019E3A894C8895D6D8BC036A7A /* KVOController-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "KVOController-dummy.m"; sourceTree = ""; }; + A6818EA23B9838465296147045EB0FE9 /* Charts-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Charts-umbrella.h"; sourceTree = ""; }; + A77DCA4D571A1924308CE4C4E30714DC /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + A7C4D7A7A0FCF2F95A58B32C9FF20AEC /* PieChartDataSet.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PieChartDataSet.swift; path = Source/Charts/Data/Implementations/Standard/PieChartDataSet.swift; sourceTree = ""; }; + A851794C72EE6DDC0384C1F864B82499 /* Pods_BlueGeckoWithHomeKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_BlueGeckoWithHomeKit.framework; path = "Pods-BlueGeckoWithHomeKit.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; + A8BB3CC60E25C2EDC28E0BE7B33B9771 /* ActionSheetLocalePicker.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = ActionSheetLocalePicker.m; path = Pickers/ActionSheetLocalePicker.m; sourceTree = ""; }; + A9D138A21FE364D0713D12F6DBC142DB /* Pods-BlueGecko-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-BlueGecko-acknowledgements.markdown"; sourceTree = ""; }; + A9E2418BD84AE19AF343489786757C64 /* ActionSheetCustomPicker.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = ActionSheetCustomPicker.m; path = Pickers/ActionSheetCustomPicker.m; sourceTree = ""; }; + AB4339FE933969A2E75A32AA820C00E0 /* ActionSheetDatePicker.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = ActionSheetDatePicker.h; path = Pickers/ActionSheetDatePicker.h; sourceTree = ""; }; + AB45DB51C553CD1C857F74D4F812C2DD /* UIView+IPAncestry.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIView+IPAncestry.m"; path = "src/UIView/UIView+IPAncestry.m"; sourceTree = ""; }; + AC02D409F9D0CDB1548871DE4058600E /* SVRadialGradientLayer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SVRadialGradientLayer.m; path = SVProgressHUD/SVRadialGradientLayer.m; sourceTree = ""; }; + ADA5FED26D4E88D6BF457EEC69A96F00 /* UIView+Constraints.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIView+Constraints.m"; path = "src/UIView/UIView+Constraints.m"; sourceTree = ""; }; + ADDA572D256D8ED1E567B40D462692AD /* SVProgressHUD.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SVProgressHUD.xcconfig; sourceTree = ""; }; + AE80CF5B6B184DD01438693A2D92C91A /* SVRadialGradientLayer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SVRadialGradientLayer.h; path = SVProgressHUD/SVRadialGradientLayer.h; sourceTree = ""; }; + AEA060E5659F19B47BEFBE9D4D7E9CD8 /* MZTimerLabel-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "MZTimerLabel-dummy.m"; sourceTree = ""; }; + AEB313383347CAE84ACC1CCFF18522D2 /* XMLDictionary.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = XMLDictionary.modulemap; sourceTree = ""; }; + AF1663184D583927C6FB7569D549A840 /* DoubleExtensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = DoubleExtensions.swift; path = Pod/Classes/DoubleExtensions.swift; sourceTree = ""; }; + AF397E288BBA899C89859AE01F8425AE /* ChevronUpShapeRenderer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ChevronUpShapeRenderer.swift; path = Source/Charts/Renderers/Scatter/ChevronUpShapeRenderer.swift; sourceTree = ""; }; + AFE0F36C767EFA0FC72A2FAF6F6A69AC /* PureLayout.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = PureLayout.h; path = PureLayout/PureLayout/PureLayout.h; sourceTree = ""; }; + B14F5C11BC82C3487CE61453DCC8D7D3 /* UICircularProgressRing.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = UICircularProgressRing.h; path = src/UICircularProgressRing/UICircularProgressRing.h; sourceTree = ""; }; + B1695C077A2B000F61B2346A16513BBD /* Pods-WirelessGecko-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-WirelessGecko-umbrella.h"; sourceTree = ""; }; + B170548C418591605F95F0166769ECEF /* ScatterChartRenderer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ScatterChartRenderer.swift; path = Source/Charts/Renderers/ScatterChartRenderer.swift; sourceTree = ""; }; + B1CBDF8C87B269DA8720E3DCBF935D85 /* BarChartData.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BarChartData.swift; path = Source/Charts/Data/Implementations/Standard/BarChartData.swift; sourceTree = ""; }; + B2DA037E74E22ECED19872F41B8DFB61 /* Transformer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Transformer.swift; path = Source/Charts/Utils/Transformer.swift; sourceTree = ""; }; + B34262047C80B45B8586528E63030076 /* BubbleChartView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BubbleChartView.swift; path = Source/Charts/Charts/BubbleChartView.swift; sourceTree = ""; }; + B3806B1746648AE0FE2D1C14613A62BE /* Pods-BlueGecko.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-BlueGecko.modulemap"; sourceTree = ""; }; + B3FB7553E32B27A6CC38F6038C2E713A /* Pods_WirelessGecko.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_WirelessGecko.framework; path = "Pods-WirelessGecko.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; + B4A721ED9B3C069A0640FAC201570CD4 /* PieChartRenderer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PieChartRenderer.swift; path = Source/Charts/Renderers/PieChartRenderer.swift; sourceTree = ""; }; + B4CA7F046A7C0B76968EE081A003297E /* DataApproximator+N.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "DataApproximator+N.swift"; path = "Source/Charts/Filters/DataApproximator+N.swift"; sourceTree = ""; }; + B5261E962563940D18C492010A79DDBE /* LineChartView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = LineChartView.swift; path = Source/Charts/Charts/LineChartView.swift; sourceTree = ""; }; + B52DB73DAFFAEE1E6D19D9EF203AF2D4 /* CoreBluetoothExtensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CoreBluetoothExtensions.swift; path = Pod/Classes/CoreBluetoothExtensions.swift; sourceTree = ""; }; + B7C3AE64DC7C46FA86DF3DC695DCB1E0 /* DistancePickerView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = DistancePickerView.h; path = Pickers/DistancePickerView.h; sourceTree = ""; }; + B9103643A78ABD199104FDA2F498075F /* SVProgressHUD-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "SVProgressHUD-dummy.m"; sourceTree = ""; }; + B92124638605120A20179A134DC7D453 /* IAxisValueFormatter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = IAxisValueFormatter.swift; path = Source/Charts/Formatters/IAxisValueFormatter.swift; sourceTree = ""; }; + B925D33DE5068460A5AC15AE02620971 /* LineChartDataSet.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = LineChartDataSet.swift; path = Source/Charts/Data/Implementations/Standard/LineChartDataSet.swift; sourceTree = ""; }; + B92F13E1729CF4C443C0733ACC1626CB /* NSObject+FBKVOController.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSObject+FBKVOController.h"; path = "FBKVOController/NSObject+FBKVOController.h"; sourceTree = ""; }; + B9C2D281D2F7CFBA3E82DFF491399A30 /* Pods-BlueGeckoWithHomeKit.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-BlueGeckoWithHomeKit.release.xcconfig"; sourceTree = ""; }; + BBA4AA1162CC5B98CDC08F04FF60062F /* Chameleon_.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Chameleon_.h; path = "Pod/Classes/Objective-C/Chameleon_.h"; sourceTree = ""; }; + BC4A51780BC2A1E6DD2EA6CC18289A01 /* UIButton+Chameleon.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIButton+Chameleon.h"; path = "Pod/Classes/Objective-C/UIButton+Chameleon.h"; sourceTree = ""; }; + BC4D91A05AAE23D52A352167C10F2973 /* Charts.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Charts.xcconfig; sourceTree = ""; }; + BC606CB7ADB7FF23C1EAD29C9963B8FC /* Pods-BlueGecko-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-BlueGecko-dummy.m"; sourceTree = ""; }; + BC7375A662C818F404C6A619DB9F7CEF /* ALView+PureLayout.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "ALView+PureLayout.m"; path = "PureLayout/PureLayout/ALView+PureLayout.m"; sourceTree = ""; }; + BD13961E49F3C85E0868C6E54F2206F0 /* YAxis.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = YAxis.swift; path = Source/Charts/Components/YAxis.swift; sourceTree = ""; }; + BD285263C7058B6A5238144A6D51AF21 /* FBKVOController.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FBKVOController.h; path = FBKVOController/FBKVOController.h; sourceTree = ""; }; + BDA86CB4CE1E763824D832694A3298ED /* KVOController.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = KVOController.modulemap; sourceTree = ""; }; + BDC68D229D7ACA3ECCD9A12B1D27D6E7 /* SquareShapeRenderer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SquareShapeRenderer.swift; path = Source/Charts/Renderers/Scatter/SquareShapeRenderer.swift; sourceTree = ""; }; + BDCDBDA222AD05425F42DFDF81FA9C4A /* LegendEntry.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = LegendEntry.swift; path = Source/Charts/Components/LegendEntry.swift; sourceTree = ""; }; + BDF39A530290D04E3EE6CE2217C92AAD /* IFillFormatter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = IFillFormatter.swift; path = Source/Charts/Formatters/IFillFormatter.swift; sourceTree = ""; }; + BEC0C0F6DDF9F7DD405020FCAB4AA5FA /* RadarChartView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = RadarChartView.swift; path = Source/Charts/Charts/RadarChartView.swift; sourceTree = ""; }; + BEF29C0A3B8D72102653C7E6B6C8ABC9 /* ChartData.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ChartData.swift; path = Source/Charts/Data/Implementations/Standard/ChartData.swift; sourceTree = ""; }; + BF5FEF3243553F8AA6BD62CBF22CCBD3 /* ActionSheetPicker-3.0-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "ActionSheetPicker-3.0-umbrella.h"; sourceTree = ""; }; + BF8905ECF8F6A06CA05E91AB2B999D85 /* IBarChartDataSet.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = IBarChartDataSet.swift; path = Source/Charts/Data/Interfaces/IBarChartDataSet.swift; sourceTree = ""; }; + C04C69B2D8638A19159459318390E183 /* AxisRendererBase.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AxisRendererBase.swift; path = Source/Charts/Renderers/AxisRendererBase.swift; sourceTree = ""; }; + C18C76D402F2741A0AA1D8C0017FA5CF /* XAxis.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = XAxis.swift; path = Source/Charts/Components/XAxis.swift; sourceTree = ""; }; + C1DD71C90FA4CFBDA4C96EC1F1A74FD2 /* KVOController-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "KVOController-prefix.pch"; sourceTree = ""; }; + C2D420A528F10334AFCC1EC2BCF47C2D /* PureLayout-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "PureLayout-prefix.pch"; sourceTree = ""; }; + C3432CEDF6D175E95F2450A31A2F89D9 /* Chameleon.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Chameleon.h; path = "Pod/Classes/Objective-C/Chameleon.h"; sourceTree = ""; }; + C45F3EF251E12C20F8057B0A78C04B8D /* IValueFormatter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = IValueFormatter.swift; path = Source/Charts/Formatters/IValueFormatter.swift; sourceTree = ""; }; + C4682DB57203991EA7CE1B2690A8FDFF /* ActionSheetPicker-3.0.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "ActionSheetPicker-3.0.xcconfig"; sourceTree = ""; }; + C559D1D35A8475FE2A8DE5DB4270AFED /* Pods-BlueGeckoWithHomeKit-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-BlueGeckoWithHomeKit-umbrella.h"; sourceTree = ""; }; + C5DBAFCBF02C2DA202DC635A1BB5F6CC /* Pods-BlueGeckoWithHomeKit-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-BlueGeckoWithHomeKit-acknowledgements.plist"; sourceTree = ""; }; + C69372D9713A79E1FA52EADFC027C46D /* WYStoryboardPopoverSegue.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = WYStoryboardPopoverSegue.h; path = WYPopoverController/WYStoryboardPopoverSegue.h; sourceTree = ""; }; + C6DE07451184226559FF238DF864CA32 /* ResourceBundle-Eddystone-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "ResourceBundle-Eddystone-Info.plist"; sourceTree = ""; }; + C733D2BFA082C72EAAB468D9E9678FB4 /* LineScatterCandleRadarRenderer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = LineScatterCandleRadarRenderer.swift; path = Source/Charts/Renderers/LineScatterCandleRadarRenderer.swift; sourceTree = ""; }; + C754AAB7BBBFAE48AE426D462403CE3D /* AnimatedMoveViewJob.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AnimatedMoveViewJob.swift; path = Source/Charts/Jobs/AnimatedMoveViewJob.swift; sourceTree = ""; }; + C7A73385CBB863151DAE52BC522CCF88 /* UILabel+Chameleon.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UILabel+Chameleon.m"; path = "Pod/Classes/Objective-C/UILabel+Chameleon.m"; sourceTree = ""; }; + C7E3380A0C6FF861791E5246074059AD /* Pods-BlueGeckoWithHomeKit.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-BlueGeckoWithHomeKit.modulemap"; sourceTree = ""; }; + C87A2240B5E8AA65D71063700E91E228 /* UIColor+IPRandomColor.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIColor+IPRandomColor.h"; path = "src/UIColor/UIColor+IPRandomColor.h"; sourceTree = ""; }; + C8E1F569037FF8B010639F61B2735AD5 /* CrossShapeRenderer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CrossShapeRenderer.swift; path = Source/Charts/Renderers/Scatter/CrossShapeRenderer.swift; sourceTree = ""; }; + C974CC9984A7E1EEC9FC46D0F06A7A38 /* ZoomViewJob.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ZoomViewJob.swift; path = Source/Charts/Jobs/ZoomViewJob.swift; sourceTree = ""; }; + C990526B92854DD7A167D6893C1068F5 /* Pods-WirelessGecko-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-WirelessGecko-acknowledgements.plist"; sourceTree = ""; }; + CA2D0995041FD3A752B936A161DC59DA /* IHighlighter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = IHighlighter.swift; path = Source/Charts/Highlight/IHighlighter.swift; sourceTree = ""; }; + CABE3C668778FA66499CAD161C9BF3FB /* BubbleChartDataSet.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BubbleChartDataSet.swift; path = Source/Charts/Data/Implementations/Standard/BubbleChartDataSet.swift; sourceTree = ""; }; + CAE4D25A498A6C786D1C24C7371CB396 /* IndexAxisValueFormatter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = IndexAxisValueFormatter.swift; path = Source/Charts/Formatters/IndexAxisValueFormatter.swift; sourceTree = ""; }; + CBA2332E85CBD14390399A0763306C4F /* Eddystone.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = Eddystone.modulemap; sourceTree = ""; }; + CBFA07FF80A69AF7BC4D8F64CB3CD59E /* ScatterChartData.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ScatterChartData.swift; path = Source/Charts/Data/Implementations/Standard/ScatterChartData.swift; sourceTree = ""; }; + CD4CAAF550DE1A78EEC5ED881A5AAF84 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.0.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; + CD74EF71D2FD41F0B37F068EFDCB49FC /* SVProgressHUD.bundle */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "wrapper.plug-in"; name = SVProgressHUD.bundle; path = SVProgressHUD/SVProgressHUD.bundle; sourceTree = ""; }; + CDE4AFBEEB6BFB9C2FF99FE78615BFC4 /* MZTimerLabel.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = MZTimerLabel.xcconfig; sourceTree = ""; }; + CE5A0086B8B491233ACA0A363FE9294E /* CandleStickChartView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CandleStickChartView.swift; path = Source/Charts/Charts/CandleStickChartView.swift; sourceTree = ""; }; + CE826E34150BE5022DF9B502C9A90972 /* PureLayout+Internal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "PureLayout+Internal.h"; path = "PureLayout/PureLayout/PureLayout+Internal.h"; sourceTree = ""; }; + CF374CE19902BD37E880A0504B5A7D54 /* Beacon.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Beacon.swift; path = Pod/Classes/Beacon.swift; sourceTree = ""; }; + CFF6C104AA6D1D496B19D102FF515BD4 /* NSArray+PureLayout.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSArray+PureLayout.h"; path = "PureLayout/PureLayout/NSArray+PureLayout.h"; sourceTree = ""; }; + D04619A6F9C66546B4D7F74614F1BD55 /* MZTimerLabel-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "MZTimerLabel-prefix.pch"; sourceTree = ""; }; + D132CE6A14A414E7F42ABB051E16BBED /* ChartLimitLine.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ChartLimitLine.swift; path = Source/Charts/Components/ChartLimitLine.swift; sourceTree = ""; }; + D23BFA6030DCBB4D45C339D070837F9D /* ChartColorTemplates.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ChartColorTemplates.swift; path = Source/Charts/Utils/ChartColorTemplates.swift; sourceTree = ""; }; + D3BD3586B983B0E863C734EBF95EB51C /* UICircularProgressRing.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = UICircularProgressRing.framework; path = UICircularProgressRing.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + D49789494660D719206D7DA7E901452F /* UIView+IPFrameUtils.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIView+IPFrameUtils.h"; path = "src/UIView/UIView+IPFrameUtils.h"; sourceTree = ""; }; + D4B50C7A6F17A840A6331420D07FD52E /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.0.sdk/System/Library/Frameworks/CoreGraphics.framework; sourceTree = DEVELOPER_DIR; }; + D518D2422D85805564148DE4B68EEF51 /* ActionSheetPicker.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = ActionSheetPicker.h; path = Pickers/ActionSheetPicker.h; sourceTree = ""; }; + D543986FAD2C7E8031D36DBA0AD3D1C3 /* Platform.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Platform.swift; path = Source/Charts/Utils/Platform.swift; sourceTree = ""; }; + D5D4833825615D141834B3888572FB4D /* SWActionSheet.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SWActionSheet.h; path = Pickers/SWActionSheet.h; sourceTree = ""; }; + D6CAA76B33E404D17DCA3072BE4BE355 /* ActionSheetMultipleStringPicker.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = ActionSheetMultipleStringPicker.m; path = Pickers/ActionSheetMultipleStringPicker.m; sourceTree = ""; }; + D747B0E5D7EB2EC6EF683B23CA4DD4D4 /* CombinedHighlighter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CombinedHighlighter.swift; path = Source/Charts/Highlight/CombinedHighlighter.swift; sourceTree = ""; }; + D86F2E52155C22E5F25E972563F6C26D /* ViewPortHandler.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ViewPortHandler.swift; path = Source/Charts/Utils/ViewPortHandler.swift; sourceTree = ""; }; + D8996CEC882A79A5A5BE3418FB9E0EF2 /* UIView+NibInitable.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIView+NibInitable.m"; path = "src/UIView/UIView+NibInitable.m"; sourceTree = ""; }; + D8D46001FF3B13E1D0356D03F0DFA3F8 /* CoreBluetooth.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreBluetooth.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.0.sdk/System/Library/Frameworks/CoreBluetooth.framework; sourceTree = DEVELOPER_DIR; }; + D8FFE18660B58C85834F19D7C0DDFB86 /* Pods-WirelessGecko-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-WirelessGecko-acknowledgements.markdown"; sourceTree = ""; }; + D926BF98B90DCDD6524156075D62DB00 /* LegendRenderer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = LegendRenderer.swift; path = Source/Charts/Renderers/LegendRenderer.swift; sourceTree = ""; }; + DB6A33E9927E27B3E713B019BC3F7D90 /* PieChartDataEntry.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PieChartDataEntry.swift; path = Source/Charts/Data/Implementations/Standard/PieChartDataEntry.swift; sourceTree = ""; }; + DC175F823BE751179FE17865635FD1A4 /* ChartDataEntry.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ChartDataEntry.swift; path = Source/Charts/Data/Implementations/Standard/ChartDataEntry.swift; sourceTree = ""; }; + DD30F88B1309FBDA6BE6DF8C40865F67 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + DD48BB50FD2F678163C6BF95A2E107EA /* Charts-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Charts-dummy.m"; sourceTree = ""; }; + DDCF4967B8D3E3851C5D5CEC725E65CE /* UIView+ChameleonPrivate.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIView+ChameleonPrivate.m"; path = "Pod/Classes/Objective-C/UIView+ChameleonPrivate.m"; sourceTree = ""; }; + DE027CB2591F19C7568E2F416B905C09 /* LineRadarRenderer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = LineRadarRenderer.swift; path = Source/Charts/Renderers/LineRadarRenderer.swift; sourceTree = ""; }; + DF301E949BBC69BBD8C5B5E4A6A9D2A0 /* UIAppearance+Swift.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIAppearance+Swift.h"; path = "Pod/Classes/Objective-C/UIAppearance+Swift.h"; sourceTree = ""; }; + DF36090CBEC6C05735606412FDE437E8 /* PieRadarHighlighter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PieRadarHighlighter.swift; path = Source/Charts/Highlight/PieRadarHighlighter.swift; sourceTree = ""; }; + DF7547EE0C14160B4A0E364D03BDA5D8 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + DFDE5E86B3473EBCB408792B8AF230C1 /* SVIndefiniteAnimatedView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SVIndefiniteAnimatedView.h; path = SVProgressHUD/SVIndefiniteAnimatedView.h; sourceTree = ""; }; + DFF1F7E3F419F2BB2B0A022589059283 /* WYPopoverController-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "WYPopoverController-umbrella.h"; sourceTree = ""; }; + E03F34DE3C542EDD599D7589F75DF745 /* SWActionSheet.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SWActionSheet.m; path = Pickers/SWActionSheet.m; sourceTree = ""; }; + E0C4884D7D0D7F9DF9F036CF7BF21086 /* IP-UIKit-Wisdom.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "IP-UIKit-Wisdom.modulemap"; sourceTree = ""; }; + E0DC9F0E418367CC13C7CF9B881FA05A /* DistancePickerView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = DistancePickerView.m; path = Pickers/DistancePickerView.m; sourceTree = ""; }; + E14AC5EF05604CFDA41013CF1E515DE8 /* XMLDictionary.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = XMLDictionary.m; path = XMLDictionary/XMLDictionary.m; sourceTree = ""; }; + E24F2FE0868E027D230A6740354DF31B /* Pods-BlueGeckoWithHomeKit-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-BlueGeckoWithHomeKit-dummy.m"; sourceTree = ""; }; + E293A98447A787C3FAC6AFB7FC85C952 /* BarLineChartViewBase.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BarLineChartViewBase.swift; path = Source/Charts/Charts/BarLineChartViewBase.swift; sourceTree = ""; }; + E2A3FDF0E87B088C76C1B6F500538CAB /* CandleChartDataProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CandleChartDataProvider.swift; path = Source/Charts/Interfaces/CandleChartDataProvider.swift; sourceTree = ""; }; + E35C53F4C58D4FA912F93BE606F90F3A /* BarHighlighter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BarHighlighter.swift; path = Source/Charts/Highlight/BarHighlighter.swift; sourceTree = ""; }; + E397227EFC2CDC9D2D030F6828E29438 /* DataApproximator.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = DataApproximator.swift; path = Source/Charts/Filters/DataApproximator.swift; sourceTree = ""; }; + E3BBE24439621C9151D831BB4B15804F /* XMLDictionary.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = XMLDictionary.xcconfig; sourceTree = ""; }; + E5C99345C40FE98B4270E8A2E48AE48D /* IP-UIKit-Wisdom-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "IP-UIKit-Wisdom-umbrella.h"; sourceTree = ""; }; + E60CC74084D7EA7D9F5DFABA2EC2427A /* UIColor+Chameleon.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIColor+Chameleon.m"; path = "Pod/Classes/Objective-C/UIColor+Chameleon.m"; sourceTree = ""; }; + E6A05BEEAFC77CB25A3B7CF32C1B5AFD /* UIViewController+Containment.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIViewController+Containment.h"; path = "src/UIViewController/UIViewController+Containment.h"; sourceTree = ""; }; + E79878BB77CBFDEACC606421F3D85809 /* Animator.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Animator.swift; path = Source/Charts/Animation/Animator.swift; sourceTree = ""; }; + E890C33AFCECA497B8CB5ABEF758FECD /* UITableView+Utils.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UITableView+Utils.h"; path = "src/UITableView/UITableView+Utils.h"; sourceTree = ""; }; + E95C06D092FED1A9E0156EC26035A130 /* ChartDataProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ChartDataProvider.swift; path = Source/Charts/Interfaces/ChartDataProvider.swift; sourceTree = ""; }; + F0B92ED39CF0DAB364E406CBD53F3E6E /* UIView+ChameleonPrivate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIView+ChameleonPrivate.h"; path = "Pod/Classes/Objective-C/UIView+ChameleonPrivate.h"; sourceTree = ""; }; + F1882C013DBA9375628D90C7C984182A /* ChameleonConstants.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = ChameleonConstants.h; path = "Pod/Classes/Objective-C/ChameleonConstants.h"; sourceTree = ""; }; + F1AF3F2BF2A6C179D6B9807122543F6F /* ChevronDownShapeRenderer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ChevronDownShapeRenderer.swift; path = Source/Charts/Renderers/Scatter/ChevronDownShapeRenderer.swift; sourceTree = ""; }; + F21204C8D0DC1E497B87C2D0664168CF /* Object.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Object.swift; path = Pod/Classes/Object.swift; sourceTree = ""; }; + F239D34F40279DC33EBF3CB789FDCFC0 /* BarLineScatterCandleBubbleChartDataSet.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BarLineScatterCandleBubbleChartDataSet.swift; path = Source/Charts/Data/Implementations/Standard/BarLineScatterCandleBubbleChartDataSet.swift; sourceTree = ""; }; + F277DCA16CD08392ACBAA96448BBC7D4 /* Highlight.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Highlight.swift; path = Source/Charts/Highlight/Highlight.swift; sourceTree = ""; }; + F2F466AB97BC42F81997A351E1C02ABB /* Global.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Global.swift; path = Pod/Classes/Global.swift; sourceTree = ""; }; + F343DF467FE87DE5EA940B4A5871B71E /* Platform+Accessibility.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Platform+Accessibility.swift"; path = "Source/Charts/Utils/Platform+Accessibility.swift"; sourceTree = ""; }; + F3B3DB6838440E7C8960A0A9210CE16C /* NSTimeIntervalExtensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = NSTimeIntervalExtensions.swift; path = Pod/Classes/NSTimeIntervalExtensions.swift; sourceTree = ""; }; + F4D22822A7DF1234CB711AEA38325A51 /* WYPopoverController.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = WYPopoverController.framework; path = WYPopoverController.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + F57A945D55D26E04879CC95388336A5C /* Pods-BlueGecko-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-BlueGecko-resources.sh"; sourceTree = ""; }; + F5C98FBEA7EE4DE626AF9CAD20A9D362 /* UICircularProgressRing-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "UICircularProgressRing-prefix.pch"; sourceTree = ""; }; + F5F6C9219F51DD4C41E6625C1ED9DE89 /* SVProgressHUD.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = SVProgressHUD.framework; path = SVProgressHUD.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + F6250A58A1D3A73FCFDB3397BB0BD028 /* NSLayoutConstraint+PureLayout.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSLayoutConstraint+PureLayout.m"; path = "PureLayout/PureLayout/NSLayoutConstraint+PureLayout.m"; sourceTree = ""; }; + F899C4ACCAED413DAD887FDB3114531F /* Pods-BlueGecko.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-BlueGecko.debug.xcconfig"; sourceTree = ""; }; + F8A0DFAF5F40F9B206C01736F0E25323 /* UICircularProgressRing.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = UICircularProgressRing.swift; path = src/UICircularProgressRing/UICircularProgressRing.swift; sourceTree = ""; }; + FB04D371FBAD3969A38BE86D78D0186A /* WYPopoverController-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "WYPopoverController-dummy.m"; sourceTree = ""; }; + FB28E4CC9EFD878DD9E1A3BC492EB783 /* RadarHighlighter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = RadarHighlighter.swift; path = Source/Charts/Highlight/RadarHighlighter.swift; sourceTree = ""; }; + FCF3202267AD590E1B2762F7D9B6C11F /* IP-UIKit-Wisdom-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "IP-UIKit-Wisdom-dummy.m"; sourceTree = ""; }; + FD82D404096AD6B24F60109F298A3FDD /* IScatterChartDataSet.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = IScatterChartDataSet.swift; path = Source/Charts/Data/Interfaces/IScatterChartDataSet.swift; sourceTree = ""; }; + FE4EF2CE77C0378F2F9A8CFD5AB9B210 /* UidFrame.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = UidFrame.swift; path = Pod/Classes/UidFrame.swift; sourceTree = ""; }; + FE8657AEC36257F2FA3F10753A556B2F /* ChartDataEntryBase.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ChartDataEntryBase.swift; path = Source/Charts/Data/Implementations/Standard/ChartDataEntryBase.swift; sourceTree = ""; }; + FECB9375AFB533BCE9A3B5294FE6EBC9 /* DefaultAxisValueFormatter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = DefaultAxisValueFormatter.swift; path = Source/Charts/Formatters/DefaultAxisValueFormatter.swift; sourceTree = ""; }; + FFE82A85642B53FF28CB6B150276BF47 /* ScatterChartDataSet.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ScatterChartDataSet.swift; path = Source/Charts/Data/Implementations/Standard/ScatterChartDataSet.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 07D5F2600190C23737FC75988AE55E3C /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + CEE5894FE73DB9EEAE919DCA0B138625 /* Foundation.framework in Frameworks */, + C6FAFCCF65C6889EC5E3DBE85B9A77C1 /* QuartzCore.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0F501AE1C2B4AFE81D4D7615BBB8B847 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + B6B21BB894F5A086977EE4F2A6AD77AE /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1988D50CAD70C441B83C21034BDF3930 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 428403E1C426C8A0034067E3720CFC9C /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 27651B48E00B05B5B51AABD201BABD7A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 11C0446A534BD7B800C6E756CFE527A7 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 39BEF469CC65E846DCF1E7A056C0AD80 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 662C582EC89CF306976E72064982C6D9 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 490C2BF785E49900C2AF94977BD5BF15 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 18664D7207318ABD018F139B52543492 /* CoreGraphics.framework in Frameworks */, + E16CF9C974AFA7CB156AA72E71A1365B /* Foundation.framework in Frameworks */, + F25A402EF79272E1802569409E7B3345 /* QuartzCore.framework in Frameworks */, + B031532D7673C9889B31F453BAEEB88D /* UIKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5CE57E768FCAE6C778F71A96A88574C9 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ED42CE0BF78638A8AC06534F1ADDCB24 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6044F31A04D991E32712DC4BE35BAA89 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 607EB1E5DDEEE39A34B6FF76481E5240 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 7B8FB2F06997DC0E98F0B377347786E0 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + EAE2466CD147DFEA36C889EA6081785E /* Foundation.framework in Frameworks */, + 89BDE1A2792C976E5CD1A94BA57B4652 /* UIKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 94B41328ED431B6EE4EE1F810BA0E51F /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D8D4BFE7C0666D68D6649E9A95D3A03D /* CoreBluetooth.framework in Frameworks */, + 8F87677FB3ACD2195081D31024A91893 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + BC996BC15A9DDDBF8178263A9A538C84 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C04435A890A45A88F67D4CB1088C6651 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + A36943D28C83AAB32E4D4AFD91F3237F /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D1B9672CEFB3642DF314D45859F65B38 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 2662F6DE516DD05C48FFAC5B6CF7DAF7 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E64ADE0F2AC7EE029405E7FE5414626E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 8718A99B43F4456F1CFFD90F990727D1 /* CoreGraphics.framework in Frameworks */, + 5E32EFEC310E2F472D9DA085FBCC5667 /* Foundation.framework in Frameworks */, + 86308120B2AA61C15A8EB3569D5E38FF /* QuartzCore.framework in Frameworks */, + 83C015F328C7606792488E0421FF7083 /* UIKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E7AC33846B2CD4AEB1866E4358CD769B /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DB4D064C6F10F24273D7DC4A127DE99A /* Foundation.framework in Frameworks */, + 80BD732089E1B3A6E5E9E453D08AADCC /* UIKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + F9A23D07EA2CB83AB5CE4EC8BC9538FF /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 7B177AE0EF7941102ABF676ED4187EE9 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 07503A9A199156F16CA0D05ABC0D1364 /* Support Files */ = { + isa = PBXGroup; + children = ( + 38A069D5E8D45C0192C4E76A29460F48 /* Info.plist */, + AEB313383347CAE84ACC1CCFF18522D2 /* XMLDictionary.modulemap */, + E3BBE24439621C9151D831BB4B15804F /* XMLDictionary.xcconfig */, + 9CD0288571DA72DC1251D12E561A6271 /* XMLDictionary-dummy.m */, + 1FA393BEE7E406E40ACD955FF8EEF18F /* XMLDictionary-prefix.pch */, + 18C3F75647C4C195F26341298A87A180 /* XMLDictionary-umbrella.h */, + ); + name = "Support Files"; + path = "../Target Support Files/XMLDictionary"; + sourceTree = ""; + }; + 1532075CF2428AE96F1DC71AE48B0A71 /* ChameleonFramework */ = { + isa = PBXGroup; + children = ( + 99B58B0D137701D83C098AE7534CA44D /* Default */, + 1C592B14CEACEDCDF906E00AC9CB2B92 /* Support Files */, + ); + name = ChameleonFramework; + path = ChameleonFramework; + sourceTree = ""; + }; + 15AF3446369F36EAF6C4E05ECD673BED /* IP-UIKit-Wisdom */ = { + isa = PBXGroup; + children = ( + 5EC623EFD593FF4960B3618BE14F5630 /* CAGradientLayer+IPGradients.h */, + 0229BF4F30B91B908D0DDBB40F9D9D31 /* CAGradientLayer+IPGradients.m */, + 5E7F96C3694731B746BDA5FE375B7FFC /* UIButton+IPUtils.h */, + 74DB70308405A78C5D9B053473907B31 /* UIButton+IPUtils.m */, + C87A2240B5E8AA65D71063700E91E228 /* UIColor+IPRandomColor.h */, + 61C4F376C04A8E77F23D0F3AD6A9E95D /* UIColor+IPRandomColor.m */, + 4D7285B8C5720CD543F416409A3B443E /* UIImage+ColorMaskedImage.h */, + 56F8646F89CBE3CC0FF913D2B1B52E8A /* UIImage+ColorMaskedImage.m */, + E890C33AFCECA497B8CB5ABEF758FECD /* UITableView+Utils.h */, + 0461CFEB46E08F25B56551C6A3C90472 /* UITableView+Utils.m */, + 8FC40DD75DDD0B5E07D3A92A26F87C95 /* UIView+Constraints.h */, + ADA5FED26D4E88D6BF457EEC69A96F00 /* UIView+Constraints.m */, + 406BF982BD3C5E9EEE3123C9441A7E73 /* UIView+IPAncestry.h */, + AB45DB51C553CD1C857F74D4F812C2DD /* UIView+IPAncestry.m */, + D49789494660D719206D7DA7E901452F /* UIView+IPFrameUtils.h */, + 39D00D1E22849A388D7AB8362D50C1DD /* UIView+IPFrameUtils.m */, + 47E053279BCB14FD7D9DCF76AA6B4CBE /* UIView+NibInitable.h */, + D8996CEC882A79A5A5BE3418FB9E0EF2 /* UIView+NibInitable.m */, + E6A05BEEAFC77CB25A3B7CF32C1B5AFD /* UIViewController+Containment.h */, + 63F658BBCC7371AB5CA6BC9BBF022159 /* UIViewController+Containment.m */, + E065EEDD4D43B68D7B7E3DD7B876EDEA /* Support Files */, + ); + name = "IP-UIKit-Wisdom"; + path = "IP-UIKit-Wisdom"; + sourceTree = ""; + }; + 182FC5647FB0B328E30CF728FF92A33F /* Support Files */ = { + isa = PBXGroup; + children = ( + 10123A0B7CC9766884B76E327E60A222 /* Info.plist */, + 4809C50ED705FC7AA75BA712BEA3E606 /* SVProgressHUD.modulemap */, + ADDA572D256D8ED1E567B40D462692AD /* SVProgressHUD.xcconfig */, + B9103643A78ABD199104FDA2F498075F /* SVProgressHUD-dummy.m */, + 9D81B4AD7AE06F5508984C088568B1FC /* SVProgressHUD-prefix.pch */, + 6BB8DF922263956771255F26D1DF0ABD /* SVProgressHUD-umbrella.h */, + ); + name = "Support Files"; + path = "../Target Support Files/SVProgressHUD"; + sourceTree = ""; + }; + 1871C5A81593170B2ED25B4D395737F6 /* UICircularProgressRing */ = { + isa = PBXGroup; + children = ( + B14F5C11BC82C3487CE61453DCC8D7D3 /* UICircularProgressRing.h */, + F8A0DFAF5F40F9B206C01736F0E25323 /* UICircularProgressRing.swift */, + 7E15B2865C9220510128DD12E8BCA588 /* UICircularProgressRingDelegate.swift */, + 1FC3412280E72BE4AF1388DCDDA2D308 /* UICircularProgressRingGradientPosition.swift */, + 6A8E67432D41F0ED22EF1767FE3FD7BC /* UICircularProgressRingLayer.swift */, + 36958433D03531713561115D14A4B289 /* UICircularProgressRingStyle.swift */, + 4D39ABF4F429271DA63A4399A461F333 /* Support Files */, + ); + name = UICircularProgressRing; + path = UICircularProgressRing; + sourceTree = ""; + }; + 1C592B14CEACEDCDF906E00AC9CB2B92 /* Support Files */ = { + isa = PBXGroup; + children = ( + 137715DB8D84D99D2D291D8BB8E0CB98 /* ChameleonFramework.modulemap */, + 827E476839A9B3D5C5DE6CE53EF74952 /* ChameleonFramework.xcconfig */, + 2F73756828B80DDCA6EF49CA5F26F168 /* ChameleonFramework-dummy.m */, + 869BD6F301C2BCF357DEFDE087F0D06F /* ChameleonFramework-prefix.pch */, + A2FF71834CDD54D9F20FF33B199FCF2F /* ChameleonFramework-umbrella.h */, + 2B63F45487A8F5DB53C658E9CA920AF0 /* Info.plist */, + ); + name = "Support Files"; + path = "../Target Support Files/ChameleonFramework"; + sourceTree = ""; + }; + 20B56609144CE204DFA8221F742B2D76 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 55545C827964DCA138AB34C2513CB863 /* iOS */, + ); + name = Frameworks; + sourceTree = ""; + }; + 23D528EB635015ADAF5ECE96F7F7B504 /* PureLayout */ = { + isa = PBXGroup; + children = ( + 934072CF1F79CE797EB562EE16407C5B /* ALView+PureLayout.h */, + BC7375A662C818F404C6A619DB9F7CEF /* ALView+PureLayout.m */, + CFF6C104AA6D1D496B19D102FF515BD4 /* NSArray+PureLayout.h */, + 54663D619A0D3881CE170F7EE40A8CF9 /* NSArray+PureLayout.m */, + 660FDCC8D1D1C260A6C9AFC394C62175 /* NSLayoutConstraint+PureLayout.h */, + F6250A58A1D3A73FCFDB3397BB0BD028 /* NSLayoutConstraint+PureLayout.m */, + AFE0F36C767EFA0FC72A2FAF6F6A69AC /* PureLayout.h */, + CE826E34150BE5022DF9B502C9A90972 /* PureLayout+Internal.h */, + 569BA96B108F04FD9CC4CD686513297E /* PureLayoutDefines.h */, + AB68ACC33692289ADF350F8D71D6C347 /* Support Files */, + ); + name = PureLayout; + path = PureLayout; + sourceTree = ""; + }; + 2CFAFEC72CB820AA5E1399D0ACCE3E5C /* Support Files */ = { + isa = PBXGroup; + children = ( + 44CD6AB8092A99D142C017FC4621AE8A /* Info.plist */, + BDA86CB4CE1E763824D832694A3298ED /* KVOController.modulemap */, + 1E3597E096BD1541EFC48B34E4899601 /* KVOController.xcconfig */, + A51C44019E3A894C8895D6D8BC036A7A /* KVOController-dummy.m */, + C1DD71C90FA4CFBDA4C96EC1F1A74FD2 /* KVOController-prefix.pch */, + 4D5A9E2EC3DD2F51BA182A00E5DEC6E3 /* KVOController-umbrella.h */, + ); + name = "Support Files"; + path = "../Target Support Files/KVOController"; + sourceTree = ""; + }; + 4106AD956D8FB20311DB347F3925CF02 /* ActionSheetPicker-3.0 */ = { + isa = PBXGroup; + children = ( + 39142212EFDD9BDF3F5DDC66D222760A /* AbstractActionSheetPicker.h */, + 6D2F8F42E69A19C4EA3F859F7A0F512A /* AbstractActionSheetPicker.m */, + 15BB98E46064549F9D687CB2734C6011 /* ActionSheetCustomPicker.h */, + A9E2418BD84AE19AF343489786757C64 /* ActionSheetCustomPicker.m */, + 67949A93DA0CE3246D1073C194798C1D /* ActionSheetCustomPickerDelegate.h */, + AB4339FE933969A2E75A32AA820C00E0 /* ActionSheetDatePicker.h */, + 800785DCA911E2E3AE42AD4A0A4F1EC6 /* ActionSheetDatePicker.m */, + 9EE8B89B13BC78BB5EF06D06E96AE057 /* ActionSheetDistancePicker.h */, + 1B336EDE579D4A86FD139ECB8D22B45E /* ActionSheetDistancePicker.m */, + 0FD65FD699B7A177648422A2B1CA70EE /* ActionSheetLocalePicker.h */, + A8BB3CC60E25C2EDC28E0BE7B33B9771 /* ActionSheetLocalePicker.m */, + 1F1C3175156D68F09309C6D90C0DA3B9 /* ActionSheetMultipleStringPicker.h */, + D6CAA76B33E404D17DCA3072BE4BE355 /* ActionSheetMultipleStringPicker.m */, + D518D2422D85805564148DE4B68EEF51 /* ActionSheetPicker.h */, + 024874D192E414F673383336E47E8011 /* ActionSheetStringPicker.h */, + 78CFE7161B732D7100419480AF27DF04 /* ActionSheetStringPicker.m */, + B7C3AE64DC7C46FA86DF3DC695DCB1E0 /* DistancePickerView.h */, + E0DC9F0E418367CC13C7CF9B881FA05A /* DistancePickerView.m */, + D5D4833825615D141834B3888572FB4D /* SWActionSheet.h */, + E03F34DE3C542EDD599D7589F75DF745 /* SWActionSheet.m */, + 5F2D2CF83AADAACF5906BA9E993849CB /* Support Files */, + ); + name = "ActionSheetPicker-3.0"; + path = "ActionSheetPicker-3.0"; + sourceTree = ""; + }; + 4256FCBF90D2903D38ED24BE472ADA60 /* Support Files */ = { + isa = PBXGroup; + children = ( + 1A65EA7D791FCFF30973B7E6308FEC92 /* Info.plist */, + 5D42210E27817B3FB477DA7FB69F030D /* WYPopoverController.modulemap */, + 4A1C73A26B8BA66527D199ABCE9F3C98 /* WYPopoverController.xcconfig */, + FB04D371FBAD3969A38BE86D78D0186A /* WYPopoverController-dummy.m */, + 7C6B867B228C9685532C77EC4B77893F /* WYPopoverController-prefix.pch */, + DFF1F7E3F419F2BB2B0A022589059283 /* WYPopoverController-umbrella.h */, + ); + name = "Support Files"; + path = "../Target Support Files/WYPopoverController"; + sourceTree = ""; + }; + 4D39ABF4F429271DA63A4399A461F333 /* Support Files */ = { + isa = PBXGroup; + children = ( + DF7547EE0C14160B4A0E364D03BDA5D8 /* Info.plist */, + 82B47BBB47AA508581319CF64EDDA84C /* UICircularProgressRing.modulemap */, + 8663053901ADA8C9A0577FEA61654E57 /* UICircularProgressRing.xcconfig */, + 6174E65A0E21BA21D32E3C972B070371 /* UICircularProgressRing-dummy.m */, + F5C98FBEA7EE4DE626AF9CAD20A9D362 /* UICircularProgressRing-prefix.pch */, + 5F2B4631847D37507D49C3BDF1244ACB /* UICircularProgressRing-umbrella.h */, + ); + name = "Support Files"; + path = "../Target Support Files/UICircularProgressRing"; + sourceTree = ""; + }; + 4D43CE08EFDAC9FCE2B558AAB47580EB /* Pods */ = { + isa = PBXGroup; + children = ( + 4106AD956D8FB20311DB347F3925CF02 /* ActionSheetPicker-3.0 */, + 1532075CF2428AE96F1DC71AE48B0A71 /* ChameleonFramework */, + 7BDD27E9CCF40BA21C4E7E1FC672A6C9 /* Charts */, + 83C6E70BF02FA3751DB228C0E8036E6E /* Eddystone */, + 15AF3446369F36EAF6C4E05ECD673BED /* IP-UIKit-Wisdom */, + 9084241E9C1E17173F1965BAEA8057DA /* KVOController */, + 744EDDEEA536048A4EBB3225ECC01931 /* MZTimerLabel */, + 23D528EB635015ADAF5ECE96F7F7B504 /* PureLayout */, + DD0348DE00D9DD57BCBD4869B0722AB5 /* SVProgressHUD */, + 1871C5A81593170B2ED25B4D395737F6 /* UICircularProgressRing */, + 65AB04EC718AA0B137C1EAA9E981CA5B /* WYPopoverController */, + D747507F54E6395A6F84B1076F4D95F9 /* XMLDictionary */, + ); + name = Pods; + sourceTree = ""; + }; + 540912AB503C95894AA492CE4A7436C1 /* Targets Support Files */ = { + isa = PBXGroup; + children = ( + C04CF9D49649E1ACD37FF2EC3E585E69 /* Pods-BlueGecko */, + CB51CDF5E50D09A713F7D44AD02396F1 /* Pods-BlueGeckoWithHomeKit */, + 62A85B3527B202C029713FF4FF74FF33 /* Pods-WirelessGecko */, + ); + name = "Targets Support Files"; + sourceTree = ""; + }; + 55545C827964DCA138AB34C2513CB863 /* iOS */ = { + isa = PBXGroup; + children = ( + D8D46001FF3B13E1D0356D03F0DFA3F8 /* CoreBluetooth.framework */, + D4B50C7A6F17A840A6331420D07FD52E /* CoreGraphics.framework */, + 4E872B141543C04195F4AA6253DCB46A /* Foundation.framework */, + 504690566E595BB0A03D20B7BA480ABC /* QuartzCore.framework */, + CD4CAAF550DE1A78EEC5ED881A5AAF84 /* UIKit.framework */, + ); + name = iOS; + sourceTree = ""; + }; + 5F2D2CF83AADAACF5906BA9E993849CB /* Support Files */ = { + isa = PBXGroup; + children = ( + 9A8D2421C65541CCF69398D1E4E69307 /* ActionSheetPicker-3.0.modulemap */, + C4682DB57203991EA7CE1B2690A8FDFF /* ActionSheetPicker-3.0.xcconfig */, + 12183893149307FB085B68D57B1DEF66 /* ActionSheetPicker-3.0-dummy.m */, + 874D1A4C10E1A719AF9A96ADA25C2E5C /* ActionSheetPicker-3.0-prefix.pch */, + BF5FEF3243553F8AA6BD62CBF22CCBD3 /* ActionSheetPicker-3.0-umbrella.h */, + 5B84E7008E8ED3FEE44C7E74AA1EB1AD /* Info.plist */, + ); + name = "Support Files"; + path = "../Target Support Files/ActionSheetPicker-3.0"; + sourceTree = ""; + }; + 62A85B3527B202C029713FF4FF74FF33 /* Pods-WirelessGecko */ = { + isa = PBXGroup; + children = ( + 0FFC441E8AB88D1D4A267AE6C1013EFE /* Info.plist */, + 0ED5292E2C23E871A0927BE6E4185FA5 /* Pods-WirelessGecko.modulemap */, + D8FFE18660B58C85834F19D7C0DDFB86 /* Pods-WirelessGecko-acknowledgements.markdown */, + C990526B92854DD7A167D6893C1068F5 /* Pods-WirelessGecko-acknowledgements.plist */, + 3CBD6C421C3B20CA83FEF5F4894B4D4B /* Pods-WirelessGecko-dummy.m */, + A42C54279BC67244768580CFF31D4599 /* Pods-WirelessGecko-frameworks.sh */, + 8C05186A656AF61E24A61B7ABD10CF87 /* Pods-WirelessGecko-resources.sh */, + B1695C077A2B000F61B2346A16513BBD /* Pods-WirelessGecko-umbrella.h */, + 24F153C0771D8D8EBE02DE904B282195 /* Pods-WirelessGecko.debug.xcconfig */, + 691E229FAC3EF29B4F989FB5BAF1999D /* Pods-WirelessGecko.release.xcconfig */, + ); + name = "Pods-WirelessGecko"; + path = "Target Support Files/Pods-WirelessGecko"; + sourceTree = ""; + }; + 63C4F662759676E3FB3D870571D7C9CE /* Products */ = { + isa = PBXGroup; + children = ( + 615EB05A5D732CD0F7153D6D8294F3CF /* ActionSheetPicker_3_0.framework */, + 3BF45EB6B838A2578EE62E2942C14FE0 /* ChameleonFramework.framework */, + 1E17B506648944D28343B82A00BAA8C4 /* Charts.framework */, + 570A1B1BC5E57682C35D8D67DA876885 /* Eddystone.bundle */, + 985BC5A9FDFCD09FA3C33FD0313A280B /* Eddystone.framework */, + 4F1ED9B0B53CB5D2EE236D8CB7EDBC29 /* IP_UIKit_Wisdom.framework */, + 15FD537E0175B3C57E5421243EF658DB /* KVOController.framework */, + 54E6CCB4DDD5185E52FB9F09B31D815A /* MZTimerLabel.framework */, + 177040E6D2D515FBF376337FD0273F59 /* Pods_BlueGecko.framework */, + A851794C72EE6DDC0384C1F864B82499 /* Pods_BlueGeckoWithHomeKit.framework */, + B3FB7553E32B27A6CC38F6038C2E713A /* Pods_WirelessGecko.framework */, + 965D4237C5D838A4CF76399A7566B7EA /* PureLayout.framework */, + F5F6C9219F51DD4C41E6625C1ED9DE89 /* SVProgressHUD.framework */, + D3BD3586B983B0E863C734EBF95EB51C /* UICircularProgressRing.framework */, + F4D22822A7DF1234CB711AEA38325A51 /* WYPopoverController.framework */, + 0FF654CBD08386066DA5FC6DBDCFA5E3 /* XMLDictionary.framework */, + ); + name = Products; + sourceTree = ""; + }; + 65AB04EC718AA0B137C1EAA9E981CA5B /* WYPopoverController */ = { + isa = PBXGroup; + children = ( + 04190BCB6CCD576431A82519AEE11E5A /* WYPopoverController.h */, + 6D48BFF0B5781A3D1EAEDF2A6C3D6B81 /* WYPopoverController.m */, + C69372D9713A79E1FA52EADFC027C46D /* WYStoryboardPopoverSegue.h */, + 002FD561FEA3D1497BD28C97A563E968 /* WYStoryboardPopoverSegue.m */, + 4256FCBF90D2903D38ED24BE472ADA60 /* Support Files */, + ); + name = WYPopoverController; + path = WYPopoverController; + sourceTree = ""; + }; + 744EDDEEA536048A4EBB3225ECC01931 /* MZTimerLabel */ = { + isa = PBXGroup; + children = ( + 94C3444270D503940943E477B3105B39 /* MZTimerLabel.h */, + 2608767335B92B9DA52F41E87B58A9F1 /* MZTimerLabel.m */, + 75EBF2909699FAD2FEE606B14BF74077 /* Support Files */, + ); + name = MZTimerLabel; + path = MZTimerLabel; + sourceTree = ""; + }; + 75EBF2909699FAD2FEE606B14BF74077 /* Support Files */ = { + isa = PBXGroup; + children = ( + DD30F88B1309FBDA6BE6DF8C40865F67 /* Info.plist */, + 974238420F393E9C2D8D7861B751177A /* MZTimerLabel.modulemap */, + CDE4AFBEEB6BFB9C2FF99FE78615BFC4 /* MZTimerLabel.xcconfig */, + AEA060E5659F19B47BEFBE9D4D7E9CD8 /* MZTimerLabel-dummy.m */, + D04619A6F9C66546B4D7F74614F1BD55 /* MZTimerLabel-prefix.pch */, + 2CB215F35A867E9CF61FC553B61D4F6D /* MZTimerLabel-umbrella.h */, + ); + name = "Support Files"; + path = "../Target Support Files/MZTimerLabel"; + sourceTree = ""; + }; + 7BDD27E9CCF40BA21C4E7E1FC672A6C9 /* Charts */ = { + isa = PBXGroup; + children = ( + D19AA75AE7CE5C39272D31EFA47A0B79 /* Core */, + CD9464CE23ECC1A364EAAA8E98FCE4A4 /* Support Files */, + ); + name = Charts; + path = Charts; + sourceTree = ""; + }; + 7DB346D0F39D3F0E887471402A8071AB = { + isa = PBXGroup; + children = ( + 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */, + 20B56609144CE204DFA8221F742B2D76 /* Frameworks */, + 4D43CE08EFDAC9FCE2B558AAB47580EB /* Pods */, + 63C4F662759676E3FB3D870571D7C9CE /* Products */, + 540912AB503C95894AA492CE4A7436C1 /* Targets Support Files */, + ); + sourceTree = ""; + }; + 83C6E70BF02FA3751DB228C0E8036E6E /* Eddystone */ = { + isa = PBXGroup; + children = ( + CF374CE19902BD37E880A0504B5A7D54 /* Beacon.swift */, + B52DB73DAFFAEE1E6D19D9EF203AF2D4 /* CoreBluetoothExtensions.swift */, + AF1663184D583927C6FB7569D549A840 /* DoubleExtensions.swift */, + 86776919F26940B88993D5676026EB2B /* Frame.swift */, + 620F97B263A04521A767E9838781254F /* Generic.swift */, + F2F466AB97BC42F81997A351E1C02ABB /* Global.swift */, + A1982ED7CE88E71925D5F535C6C7A062 /* IntExtensions.swift */, + F3B3DB6838440E7C8960A0A9210CE16C /* NSTimeIntervalExtensions.swift */, + F21204C8D0DC1E497B87C2D0664168CF /* Object.swift */, + 025F3ABB22FDA99968B420F91E511D2A /* Scanner.swift */, + 7A6266FA2DC2B84E6EB17221047CB303 /* TlmFrame.swift */, + 0CA40134452942E2A6CCCC7C47BCDE6E /* Uid.swift */, + FE4EF2CE77C0378F2F9A8CFD5AB9B210 /* UidFrame.swift */, + 6E43803662EE53000A57538DAA5A6B70 /* Url.swift */, + 303726B29FCA0EAB7FA43803BB2FFC46 /* UrlFrame.swift */, + ED92B3AD69B41706417A381AFFA24916 /* Support Files */, + ); + name = Eddystone; + path = Eddystone; + sourceTree = ""; + }; + 9084241E9C1E17173F1965BAEA8057DA /* KVOController */ = { + isa = PBXGroup; + children = ( + BD285263C7058B6A5238144A6D51AF21 /* FBKVOController.h */, + 0A55D7A54C24B18ABB272F3F03760549 /* FBKVOController.m */, + 86A10CA50571306393F36FAD321FD71B /* KVOController.h */, + B92F13E1729CF4C443C0733ACC1626CB /* NSObject+FBKVOController.h */, + 7A59D71277F8A7EBB7698E856B46D253 /* NSObject+FBKVOController.m */, + 2CFAFEC72CB820AA5E1399D0ACCE3E5C /* Support Files */, + ); + name = KVOController; + path = KVOController; + sourceTree = ""; + }; + 997F7565A1165C0C863515115FD45B83 /* Resources */ = { + isa = PBXGroup; + children = ( + CD74EF71D2FD41F0B37F068EFDCB49FC /* SVProgressHUD.bundle */, + ); + name = Resources; + sourceTree = ""; + }; + 99B58B0D137701D83C098AE7534CA44D /* Default */ = { + isa = PBXGroup; + children = ( + C3432CEDF6D175E95F2450A31A2F89D9 /* Chameleon.h */, + BBA4AA1162CC5B98CDC08F04FF60062F /* Chameleon_.h */, + 516B0ED428665BD90D818DEE11C340B9 /* Chameleon_.m */, + F1882C013DBA9375628D90C7C984182A /* ChameleonConstants.h */, + 2CD0A3FA3E70958D084098CAC95338F3 /* ChameleonConstants.m */, + 6A353EA5D77D5A677BB2A7CC8C0200C1 /* ChameleonEnums.h */, + 9027945388741C2D88415E3D7201D9EC /* ChameleonMacros.h */, + 1CD1F5A0BC106C02AC57A8F494FA748F /* NSArray+Chameleon.h */, + 14CD451ABCB610CFD12F47CAFF7BE531 /* NSArray+Chameleon.m */, + DF301E949BBC69BBD8C5B5E4A6A9D2A0 /* UIAppearance+Swift.h */, + 80106BF869F5D236D9896410F1E83729 /* UIAppearance+Swift.m */, + BC4A51780BC2A1E6DD2EA6CC18289A01 /* UIButton+Chameleon.h */, + 7C9254F379DC1DB830541F92590F4488 /* UIButton+Chameleon.m */, + 05AAE3AC4D5202C769F162FEF75D2E8B /* UIColor+Chameleon.h */, + E60CC74084D7EA7D9F5DFABA2EC2427A /* UIColor+Chameleon.m */, + 7181A7AF7266173B7C8FB3AE317A77BF /* UIColor+ChameleonPrivate.h */, + 1C94D25E7BF4C82F3F0FC450078C7D2B /* UIColor+ChameleonPrivate.m */, + 3E3C794FD85107420F8B9D1D8EAE5451 /* UIImage+ChameleonPrivate.h */, + 9CEC245B78279AF03A87DC3867F4325D /* UIImage+ChameleonPrivate.m */, + 3C12CA761777232CB084C77ECD8F64D2 /* UILabel+Chameleon.h */, + C7A73385CBB863151DAE52BC522CCF88 /* UILabel+Chameleon.m */, + 336BA1494AA67B6F791FF4FB3AF34FB2 /* UINavigationController+Chameleon.h */, + 530DA5F79FC49F4F24129ACF69B64177 /* UINavigationController+Chameleon.m */, + F0B92ED39CF0DAB364E406CBD53F3E6E /* UIView+ChameleonPrivate.h */, + DDCF4967B8D3E3851C5D5CEC725E65CE /* UIView+ChameleonPrivate.m */, + 5A0D91B6CCA43C65C5E5AFF3DB9B1F50 /* UIViewController+Chameleon.h */, + 96DC2C89C66682D28AC10AB157F59C00 /* UIViewController+Chameleon.m */, + ); + name = Default; + sourceTree = ""; + }; + AB68ACC33692289ADF350F8D71D6C347 /* Support Files */ = { + isa = PBXGroup; + children = ( + 0D4B9267F4B053000B880E717283CCB2 /* Info.plist */, + 65B77D36C6A6C8F5149CC077A793CAEA /* PureLayout.modulemap */, + 6DF6D9D9AB6E5A2673FE8D86E15CBFD8 /* PureLayout.xcconfig */, + 176C4897F7F7A432B12A37BB4CC52EC6 /* PureLayout-dummy.m */, + C2D420A528F10334AFCC1EC2BCF47C2D /* PureLayout-prefix.pch */, + 944AE29058BAC80AB15D436CE874AFFF /* PureLayout-umbrella.h */, + ); + name = "Support Files"; + path = "../Target Support Files/PureLayout"; + sourceTree = ""; + }; + C04CF9D49649E1ACD37FF2EC3E585E69 /* Pods-BlueGecko */ = { + isa = PBXGroup; + children = ( + 331778CD5CA75B334ED64534D22AED30 /* Info.plist */, + B3806B1746648AE0FE2D1C14613A62BE /* Pods-BlueGecko.modulemap */, + A9D138A21FE364D0713D12F6DBC142DB /* Pods-BlueGecko-acknowledgements.markdown */, + 7816EA5D91D0971F1BD9E2269ABDD6DB /* Pods-BlueGecko-acknowledgements.plist */, + BC606CB7ADB7FF23C1EAD29C9963B8FC /* Pods-BlueGecko-dummy.m */, + 593927968B65C54CDBDAE2DCFDA383D2 /* Pods-BlueGecko-frameworks.sh */, + F57A945D55D26E04879CC95388336A5C /* Pods-BlueGecko-resources.sh */, + 445B3D0F1F70C467F508C347E6ECC326 /* Pods-BlueGecko-umbrella.h */, + F899C4ACCAED413DAD887FDB3114531F /* Pods-BlueGecko.debug.xcconfig */, + 3F6A9685BFC90D3A596AD7B760053227 /* Pods-BlueGecko.release.xcconfig */, + ); + name = "Pods-BlueGecko"; + path = "Target Support Files/Pods-BlueGecko"; + sourceTree = ""; + }; + CB51CDF5E50D09A713F7D44AD02396F1 /* Pods-BlueGeckoWithHomeKit */ = { + isa = PBXGroup; + children = ( + 505136F6C931876302F18B5A06035CA7 /* Info.plist */, + C7E3380A0C6FF861791E5246074059AD /* Pods-BlueGeckoWithHomeKit.modulemap */, + 399399C6191136B400E65BC2F5803E77 /* Pods-BlueGeckoWithHomeKit-acknowledgements.markdown */, + C5DBAFCBF02C2DA202DC635A1BB5F6CC /* Pods-BlueGeckoWithHomeKit-acknowledgements.plist */, + E24F2FE0868E027D230A6740354DF31B /* Pods-BlueGeckoWithHomeKit-dummy.m */, + 83BDE113AC6294183C2FCF0741961434 /* Pods-BlueGeckoWithHomeKit-frameworks.sh */, + 0AF09D04470F6A0FFBEB4247213736CE /* Pods-BlueGeckoWithHomeKit-resources.sh */, + C559D1D35A8475FE2A8DE5DB4270AFED /* Pods-BlueGeckoWithHomeKit-umbrella.h */, + 9F7F0B2C801D84E4DBCC848D00DC4F5B /* Pods-BlueGeckoWithHomeKit.debug.xcconfig */, + B9C2D281D2F7CFBA3E82DFF491399A30 /* Pods-BlueGeckoWithHomeKit.release.xcconfig */, + ); + name = "Pods-BlueGeckoWithHomeKit"; + path = "Target Support Files/Pods-BlueGeckoWithHomeKit"; + sourceTree = ""; + }; + CD9464CE23ECC1A364EAAA8E98FCE4A4 /* Support Files */ = { + isa = PBXGroup; + children = ( + 54C0A5BFB438BA11FB583A383BD621CA /* Charts.modulemap */, + BC4D91A05AAE23D52A352167C10F2973 /* Charts.xcconfig */, + DD48BB50FD2F678163C6BF95A2E107EA /* Charts-dummy.m */, + 5E106DA25719FD85DCF726D5B7128773 /* Charts-prefix.pch */, + A6818EA23B9838465296147045EB0FE9 /* Charts-umbrella.h */, + 98D10BE70758053EEECAB14726A3BE77 /* Info.plist */, + ); + name = "Support Files"; + path = "../Target Support Files/Charts"; + sourceTree = ""; + }; + D19AA75AE7CE5C39272D31EFA47A0B79 /* Core */ = { + isa = PBXGroup; + children = ( + C754AAB7BBBFAE48AE426D462403CE3D /* AnimatedMoveViewJob.swift */, + 33D149F302D5CF9FA1F7308DAF0ABD5B /* AnimatedViewPortJob.swift */, + 6B20E8445BA0DDD43FB3071C1C0E4BD6 /* AnimatedZoomViewJob.swift */, + E79878BB77CBFDEACC606421F3D85809 /* Animator.swift */, + 91E94BCA50C419D7C1B1B5E4FDBE3D2E /* AxisBase.swift */, + C04C69B2D8638A19159459318390E183 /* AxisRendererBase.swift */, + B1CBDF8C87B269DA8720E3DCBF935D85 /* BarChartData.swift */, + 5E063F0C244C3ED32C67EC74FCD5E4AF /* BarChartDataEntry.swift */, + 86122BE76B25FF9C7AF6EA44A5B7F04C /* BarChartDataProvider.swift */, + 544145B0B14DBBD37A7AD8E40B5F0456 /* BarChartDataSet.swift */, + 9F897B9413247295364D38AE83A36795 /* BarChartRenderer.swift */, + 80ACA67493C63D6EE695846006AA65D9 /* BarChartView.swift */, + E35C53F4C58D4FA912F93BE606F90F3A /* BarHighlighter.swift */, + E293A98447A787C3FAC6AFB7FC85C952 /* BarLineChartViewBase.swift */, + 741CF545C29BBBD5B91CB19812F6F1AB /* BarLineScatterCandleBubbleChartData.swift */, + 273C7DC661C73862256E8F1E24C36458 /* BarLineScatterCandleBubbleChartDataProvider.swift */, + F239D34F40279DC33EBF3CB789FDCFC0 /* BarLineScatterCandleBubbleChartDataSet.swift */, + 0A9984E2583E990609E9322A2CAB42C6 /* BarLineScatterCandleBubbleRenderer.swift */, + 3A1A4ADB688FA25351F308695E3392F7 /* BubbleChartData.swift */, + 513761915E3ED039E2120E0FF8B65600 /* BubbleChartDataEntry.swift */, + 1341768F552F0BBF2C86A715DA0A0FFA /* BubbleChartDataProvider.swift */, + CABE3C668778FA66499CAD161C9BF3FB /* BubbleChartDataSet.swift */, + 65D9CBA1C9C448F48A1B55B1E0D465D2 /* BubbleChartRenderer.swift */, + B34262047C80B45B8586528E63030076 /* BubbleChartView.swift */, + 00DE8F8453D74BA2667E3E8086ABDD4A /* CandleChartData.swift */, + 6E6227BF90B1AAD393A68FB8234816CD /* CandleChartDataEntry.swift */, + E2A3FDF0E87B088C76C1B6F500538CAB /* CandleChartDataProvider.swift */, + 825DF301497E57E00BC477A931E70268 /* CandleChartDataSet.swift */, + 8EBA1DD0ED252939E1BCA5C1B8578A45 /* CandleStickChartRenderer.swift */, + CE5A0086B8B491233ACA0A363FE9294E /* CandleStickChartView.swift */, + 99FC4D414E8D92A3687B983B5DD082E7 /* ChartAnimationEasing.swift */, + 81787386F805E581DA154CB7C1A23CFA /* ChartBaseDataSet.swift */, + D23BFA6030DCBB4D45C339D070837F9D /* ChartColorTemplates.swift */, + BEF29C0A3B8D72102653C7E6B6C8ABC9 /* ChartData.swift */, + DC175F823BE751179FE17865635FD1A4 /* ChartDataEntry.swift */, + FE8657AEC36257F2FA3F10753A556B2F /* ChartDataEntryBase.swift */, + E95C06D092FED1A9E0156EC26035A130 /* ChartDataProvider.swift */, + 6C48E807343CABA2262D85BFE1A1D8BA /* ChartDataRendererBase.swift */, + 389A3FE642BFDC7F2B5D76FAAE2EC913 /* ChartDataSet.swift */, + 0DCFD4B2CC0B5EC3A172CBD1531B747E /* ChartHighlighter.swift */, + D132CE6A14A414E7F42ABB051E16BBED /* ChartLimitLine.swift */, + 8072DE6C57BC4BF3AA233DB26AAA9EB0 /* ChartUtils.swift */, + 8D6EF8626404CE5AA97A83FA08910E76 /* ChartViewBase.swift */, + F1AF3F2BF2A6C179D6B9807122543F6F /* ChevronDownShapeRenderer.swift */, + AF397E288BBA899C89859AE01F8425AE /* ChevronUpShapeRenderer.swift */, + 3C1D93D382918BCF3CA502D4F94AAAA5 /* CircleShapeRenderer.swift */, + 0C7BEF7AED5E42ED9B4819573519C515 /* CombinedChartData.swift */, + 927881679707E7BB35FBF5CCF8A0183A /* CombinedChartDataProvider.swift */, + 42B2EEC771BA840AE50CB797B0F162F8 /* CombinedChartRenderer.swift */, + 903DC957219810A92394E22C6B19629D /* CombinedChartView.swift */, + D747B0E5D7EB2EC6EF683B23CA4DD4D4 /* CombinedHighlighter.swift */, + 8A2CEAB98F32984CFE1E2BAD7687FCB6 /* ComponentBase.swift */, + C8E1F569037FF8B010639F61B2735AD5 /* CrossShapeRenderer.swift */, + E397227EFC2CDC9D2D030F6828E29438 /* DataApproximator.swift */, + B4CA7F046A7C0B76968EE081A003297E /* DataApproximator+N.swift */, + FECB9375AFB533BCE9A3B5294FE6EBC9 /* DefaultAxisValueFormatter.swift */, + 643484DF9098D57753F164AB155E2D8B /* DefaultFillFormatter.swift */, + 5C33F8227CCE6399F69AFDC719E0DEB9 /* DefaultValueFormatter.swift */, + A3376FA5C8A5D1B2D506D0C0F53E8604 /* Description.swift */, + 45059F949099ABAAD358FB1A3586CD3A /* Fill.swift */, + F277DCA16CD08392ACBAA96448BBC7D4 /* Highlight.swift */, + 679DA6BE5AD33B38F3A7E14AA89CB2C9 /* HorizontalBarChartRenderer.swift */, + 11E6DB3330CBDD52707CDF6E1C33A283 /* HorizontalBarChartView.swift */, + 219F6CF3CCC811E9083AA2F13750F9E9 /* HorizontalBarHighlighter.swift */, + B92124638605120A20179A134DC7D453 /* IAxisValueFormatter.swift */, + BF8905ECF8F6A06CA05E91AB2B999D85 /* IBarChartDataSet.swift */, + 6E9625AEF2DDDF05E981EC1CC74352E6 /* IBarLineScatterCandleBubbleChartDataSet.swift */, + 478CF550BE7D801EB6E55E5D4CFE151A /* IBubbleChartDataSet.swift */, + 93151302C6ACEE98EA43A21A83585A38 /* ICandleChartDataSet.swift */, + 4A3B168913F0573313A17DDB4317B3B2 /* IChartDataSet.swift */, + BDF39A530290D04E3EE6CE2217C92AAD /* IFillFormatter.swift */, + CA2D0995041FD3A752B936A161DC59DA /* IHighlighter.swift */, + 358E5C11378F76DF53DC2D731F9B92E1 /* ILineChartDataSet.swift */, + 7477A476ADD5E869E1A4B11E8186721E /* ILineRadarChartDataSet.swift */, + 15D70592F205341C68F9571682E433E7 /* ILineScatterCandleRadarChartDataSet.swift */, + 902543F7869A31661B0AC19E3C9AE9C6 /* IMarker.swift */, + CAE4D25A498A6C786D1C24C7371CB396 /* IndexAxisValueFormatter.swift */, + 031C1A1D4169F31403D9CBE6EF4B294B /* IPieChartDataSet.swift */, + 16CDC0EC422748B94114F308A908E51E /* IRadarChartDataSet.swift */, + FD82D404096AD6B24F60109F298A3FDD /* IScatterChartDataSet.swift */, + 1EAAAF5D5A1A5776B31EB0FA5C0E0F4E /* IShapeRenderer.swift */, + C45F3EF251E12C20F8057B0A78C04B8D /* IValueFormatter.swift */, + 5C94721C4A0B4B47781D9AA1C5DF1ACF /* Legend.swift */, + BDCDBDA222AD05425F42DFDF81FA9C4A /* LegendEntry.swift */, + D926BF98B90DCDD6524156075D62DB00 /* LegendRenderer.swift */, + 2612F4C6AD646E9719C2BBD4022C2ADE /* LineChartData.swift */, + 96919220F12F29935EABD3E47DEC7444 /* LineChartDataProvider.swift */, + B925D33DE5068460A5AC15AE02620971 /* LineChartDataSet.swift */, + 2CF24195C175E960490AB9D5477BFD87 /* LineChartRenderer.swift */, + B5261E962563940D18C492010A79DDBE /* LineChartView.swift */, + 3471AE3783802E123428196BF7F2C48B /* LineRadarChartDataSet.swift */, + DE027CB2591F19C7568E2F416B905C09 /* LineRadarRenderer.swift */, + 57634E7A180647CF43FBC74A5BD446F3 /* LineScatterCandleRadarChartDataSet.swift */, + C733D2BFA082C72EAAB468D9E9678FB4 /* LineScatterCandleRadarRenderer.swift */, + 97E5B70FBD11A68B3A9CD66E057AB5BC /* MarkerImage.swift */, + 5989CCB3F818BFA70ACE40F1730955AF /* MarkerView.swift */, + 432C3FC422E42C5D6C5E28256E4968B7 /* MoveViewJob.swift */, + 25C0783D77DD9E95A5DDFD863D8A39E8 /* PieChartData.swift */, + DB6A33E9927E27B3E713B019BC3F7D90 /* PieChartDataEntry.swift */, + A7C4D7A7A0FCF2F95A58B32C9FF20AEC /* PieChartDataSet.swift */, + B4A721ED9B3C069A0640FAC201570CD4 /* PieChartRenderer.swift */, + 9EE21DBBF5702F3F31F823B4AFF90A30 /* PieChartView.swift */, + 77AA3DA113378A3CD340D07AF9878B77 /* PieHighlighter.swift */, + A4FE66660693AED28587ACC5B8E64B1A /* PieRadarChartViewBase.swift */, + DF36090CBEC6C05735606412FDE437E8 /* PieRadarHighlighter.swift */, + D543986FAD2C7E8031D36DBA0AD3D1C3 /* Platform.swift */, + F343DF467FE87DE5EA940B4A5871B71E /* Platform+Accessibility.swift */, + 0490899449C723E7EC451A97FC77E5B9 /* RadarChartData.swift */, + 38AF2B25FCF8F38D923B2A8B9B5872FE /* RadarChartDataEntry.swift */, + 35D2F421107B1B0AAAF1A00095F56D53 /* RadarChartDataSet.swift */, + 5A3A22D5D7DFFBCC072A618962C29187 /* RadarChartRenderer.swift */, + BEC0C0F6DDF9F7DD405020FCAB4AA5FA /* RadarChartView.swift */, + FB28E4CC9EFD878DD9E1A3BC492EB783 /* RadarHighlighter.swift */, + 1F2C6B76362F95DA7C7D59F803049517 /* Range.swift */, + 7E1663FBB43F97FD1F8C5074DB77FEC7 /* Renderer.swift */, + CBFA07FF80A69AF7BC4D8F64CB3CD59E /* ScatterChartData.swift */, + 8642C5BE3AB754F356C8DB11D0836BD2 /* ScatterChartDataProvider.swift */, + FFE82A85642B53FF28CB6B150276BF47 /* ScatterChartDataSet.swift */, + B170548C418591605F95F0166769ECEF /* ScatterChartRenderer.swift */, + 7FCEC7ED703FE901FF913298159DEA0C /* ScatterChartView.swift */, + BDC68D229D7ACA3ECCD9A12B1D27D6E7 /* SquareShapeRenderer.swift */, + B2DA037E74E22ECED19872F41B8DFB61 /* Transformer.swift */, + 90A3B781B047A3280FE14967BCC59A4D /* TransformerHorizontalBarChart.swift */, + 60636B604BABF9DE0CC5107B72A0BCF9 /* TriangleShapeRenderer.swift */, + D86F2E52155C22E5F25E972563F6C26D /* ViewPortHandler.swift */, + 58F964009ECA3B64814787A3435B10BD /* ViewPortJob.swift */, + C18C76D402F2741A0AA1D8C0017FA5CF /* XAxis.swift */, + 7481CF72D407C3ABE3C21CE4EA0663DF /* XAxisRenderer.swift */, + 6FE53421F581B66DF6A0AF5505042A96 /* XAxisRendererHorizontalBarChart.swift */, + 37F49D184948DB3945E37E66E7854D7E /* XAxisRendererRadarChart.swift */, + 200DC0152261F9AA7276C30BE32A9C8C /* XShapeRenderer.swift */, + BD13961E49F3C85E0868C6E54F2206F0 /* YAxis.swift */, + 82926FBBD1B0798B1F00AAA4397F2372 /* YAxisRenderer.swift */, + 7D46FFE9FA8DD84EAA516AE74508BD1A /* YAxisRendererHorizontalBarChart.swift */, + 7D20CD4B0F1917F76DBF804904257E7F /* YAxisRendererRadarChart.swift */, + C974CC9984A7E1EEC9FC46D0F06A7A38 /* ZoomViewJob.swift */, + ); + name = Core; + sourceTree = ""; + }; + D747507F54E6395A6F84B1076F4D95F9 /* XMLDictionary */ = { + isa = PBXGroup; + children = ( + 558F2F7A2DC6222F1FF0FA94D5957844 /* XMLDictionary.h */, + E14AC5EF05604CFDA41013CF1E515DE8 /* XMLDictionary.m */, + 07503A9A199156F16CA0D05ABC0D1364 /* Support Files */, + ); + name = XMLDictionary; + path = XMLDictionary; + sourceTree = ""; + }; + DD0348DE00D9DD57BCBD4869B0722AB5 /* SVProgressHUD */ = { + isa = PBXGroup; + children = ( + DFDE5E86B3473EBCB408792B8AF230C1 /* SVIndefiniteAnimatedView.h */, + 45709024E87F53D94EA3E6CB7463C190 /* SVIndefiniteAnimatedView.m */, + A2254E1A588165AF3B57FA75E6701BA1 /* SVProgressAnimatedView.h */, + 3F36FA7BD17CF42413AB49F4B85512BB /* SVProgressAnimatedView.m */, + 5A22154EBF2F0DE92536644E78FA6A5D /* SVProgressHUD.h */, + 3B324A581DDD6EA8E88C978D063B53DA /* SVProgressHUD.m */, + AE80CF5B6B184DD01438693A2D92C91A /* SVRadialGradientLayer.h */, + AC02D409F9D0CDB1548871DE4058600E /* SVRadialGradientLayer.m */, + 997F7565A1165C0C863515115FD45B83 /* Resources */, + 182FC5647FB0B328E30CF728FF92A33F /* Support Files */, + ); + name = SVProgressHUD; + path = SVProgressHUD; + sourceTree = ""; + }; + E065EEDD4D43B68D7B7E3DD7B876EDEA /* Support Files */ = { + isa = PBXGroup; + children = ( + 3C6867A262E67FC1C407DBC28783F77E /* Info.plist */, + E0C4884D7D0D7F9DF9F036CF7BF21086 /* IP-UIKit-Wisdom.modulemap */, + 55EEDB11AB6F96E6F97DC96F2C476230 /* IP-UIKit-Wisdom.xcconfig */, + FCF3202267AD590E1B2762F7D9B6C11F /* IP-UIKit-Wisdom-dummy.m */, + 072E19AD36FEF0C7BD2509195C2E122F /* IP-UIKit-Wisdom-prefix.pch */, + E5C99345C40FE98B4270E8A2E48AE48D /* IP-UIKit-Wisdom-umbrella.h */, + ); + name = "Support Files"; + path = "../Target Support Files/IP-UIKit-Wisdom"; + sourceTree = ""; + }; + ED92B3AD69B41706417A381AFFA24916 /* Support Files */ = { + isa = PBXGroup; + children = ( + CBA2332E85CBD14390399A0763306C4F /* Eddystone.modulemap */, + 4D9D9C5B78F513003B8393913329AC75 /* Eddystone.xcconfig */, + 683F26A72165D255BCDA83A03B0E4BCD /* Eddystone-dummy.m */, + 3BB1150EA100AD0F94AE6B49B9682CE4 /* Eddystone-prefix.pch */, + 12D031A69C52A7AC31D772114B2770F3 /* Eddystone-umbrella.h */, + A77DCA4D571A1924308CE4C4E30714DC /* Info.plist */, + C6DE07451184226559FF238DF864CA32 /* ResourceBundle-Eddystone-Info.plist */, + ); + name = "Support Files"; + path = "../Target Support Files/Eddystone"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 29C44169C519BC7CB5DFA88661C2B20A /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 1686B7ED74B5905B476E93FE2E1BC5EE /* Pods-WirelessGecko-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 39552F1C3126CC2B9003A65330CE0E6D /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 588226751006A9F4DE29BA5C13F2363A /* WYPopoverController-umbrella.h in Headers */, + 658632A1D06C3D6E228DA9920792531F /* WYPopoverController.h in Headers */, + 986BBFA10788030132379E305A0C9E15 /* WYStoryboardPopoverSegue.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 45BE5DEFE0CC671E8F138442B4155B4A /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 4C4A18F2AA41A8E7654F4A51F6C10C62 /* CAGradientLayer+IPGradients.h in Headers */, + 42C6EAB75A829100C4E9D59D5F7C23A1 /* IP-UIKit-Wisdom-umbrella.h in Headers */, + F3AA3D91880B982B7C9BDED7E4DF2A67 /* UIButton+IPUtils.h in Headers */, + 65D5D6D89B0395AEA80F0E320D8EB487 /* UIColor+IPRandomColor.h in Headers */, + 420C6EBE96BE76B50666F337BF251E61 /* UIImage+ColorMaskedImage.h in Headers */, + 3873106BA37978286AD9F211E1179A84 /* UITableView+Utils.h in Headers */, + 7E9DED37321416EB9F4EBE87FA4E0869 /* UIView+Constraints.h in Headers */, + 42C9F91772B66FD0D9960D4BC331E9BD /* UIView+IPAncestry.h in Headers */, + C8BC2FEF74A2D51E779E4BAB60B1F1CE /* UIView+IPFrameUtils.h in Headers */, + C22161A14023C0E8B7C9CED95FEDB6EC /* UIView+NibInitable.h in Headers */, + CCF010AF65241F580D3E461A790679D2 /* UIViewController+Containment.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4E7E5DC34B7E382207E43517A01E899A /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 084CAE071F5CA81328307F56DBEEFA85 /* Pods-BlueGecko-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 54300B358FA282D36084AA0126604146 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + A9E8BF7B194CF266508F39D3123BFCB9 /* Chameleon.h in Headers */, + F4B03991D0708E3C8909CE66F291ECA8 /* Chameleon_.h in Headers */, + AE90811F6C330C0483BE86C370611882 /* ChameleonConstants.h in Headers */, + 7BC8CA21A04DAC9ECB08D905BF13608C /* ChameleonEnums.h in Headers */, + A35F9A4C8C7E3EE526F99863BF2D3EEA /* ChameleonFramework-umbrella.h in Headers */, + F442C35711C3B60C74D66F237619C391 /* ChameleonMacros.h in Headers */, + 2E718BB83D6D450CB4A00C3C8E80221E /* NSArray+Chameleon.h in Headers */, + 741FDA313164BF386A7BADA9DE6A272C /* UIAppearance+Swift.h in Headers */, + D2F1D3744CDB46E673C8CA26FAA92B8C /* UIButton+Chameleon.h in Headers */, + 32DFD092F9BE0BDE0D4DEEA84E713D4F /* UIColor+Chameleon.h in Headers */, + 6160CC839154784B974F4120EC1B82C2 /* UIColor+ChameleonPrivate.h in Headers */, + A8483FA08C7504C84AAFA435EC431387 /* UIImage+ChameleonPrivate.h in Headers */, + 3AFFB565BBE38E813794E136B9F07832 /* UILabel+Chameleon.h in Headers */, + 3DFEDD8DA551D14D5C1EDA8E8CD95EF9 /* UINavigationController+Chameleon.h in Headers */, + 6CE49BF2883BEAD623FE702ECDA5C508 /* UIView+ChameleonPrivate.h in Headers */, + 9CB529305884D774BDCB2FDD5F7B27A0 /* UIViewController+Chameleon.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5C9EB7AEA7731EEB7CA79A8E6E651D8F /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + A0501B7D192BE61470F409C7DEAB2731 /* Pods-BlueGeckoWithHomeKit-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5D3BAC2B0B7E85F3D8782E1BB866D427 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 005B70F9BE90730CC4DD68BF32E6C20A /* MZTimerLabel-umbrella.h in Headers */, + F5A5996E49FB0CC06D9A964B7431192C /* MZTimerLabel.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 73957F140CBBD023C8756A8DA0DE1B47 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + C2CB66F328C91D46BD14669B85BA90B3 /* SVIndefiniteAnimatedView.h in Headers */, + BACFCF38BA6890B3C70BC7C1753C8045 /* SVProgressAnimatedView.h in Headers */, + 28E5726B8CB0E98A529EA111FA82B672 /* SVProgressHUD-umbrella.h in Headers */, + D78AEE61D4F95442EB9266D432E69C14 /* SVProgressHUD.h in Headers */, + F622D7EA5FD98CFBD9EA62FFADD13396 /* SVRadialGradientLayer.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 777508A22BC8235FB0387E89D6A9C12A /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + D6D007B23FA5DF1701D61350DFC40500 /* AbstractActionSheetPicker.h in Headers */, + D80520F915604ECE5AFC7C198210BD4F /* ActionSheetCustomPicker.h in Headers */, + 0DEE8FE78BFA6837741490D5AE7E70D3 /* ActionSheetCustomPickerDelegate.h in Headers */, + 04DC3AB008D664C94B53378D92A8357C /* ActionSheetDatePicker.h in Headers */, + 6BC552C40935F9164B0565799E276A70 /* ActionSheetDistancePicker.h in Headers */, + 0B58249E18BC6B5059BA58BF1F41ACB8 /* ActionSheetLocalePicker.h in Headers */, + B4FFBAAAB2020487F48B39A18F09BABC /* ActionSheetMultipleStringPicker.h in Headers */, + BD8C15CEC12E2C97775FCCF763C45DBF /* ActionSheetPicker-3.0-umbrella.h in Headers */, + D72525552EA381EFC7AC1F2617B30F12 /* ActionSheetPicker.h in Headers */, + BEE3F41C1AE3F63252F05C59C7E14088 /* ActionSheetStringPicker.h in Headers */, + A1805B3522AD2C8941E19640D7AA616B /* DistancePickerView.h in Headers */, + 81F48B45BB3364F85399A085D2C6EB5D /* SWActionSheet.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A0CE1CA51299B34C4C74CCA305981B1D /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 3D9C7B78E9C34E2B37D15A0C1724638E /* FBKVOController.h in Headers */, + BD9D1FFE56D8A8760686B46136980400 /* KVOController-umbrella.h in Headers */, + 24EA7AADDF4DEB2C5803988A52AA3034 /* KVOController.h in Headers */, + 3177D9AAD46AADF1B22E17E8C764B47D /* NSObject+FBKVOController.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A9199DFFF761F3724080492034518DA2 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 508547AFDF31532896F7859DA75FB625 /* XMLDictionary-umbrella.h in Headers */, + D86CEE6DDC971DF965723FDD1682648F /* XMLDictionary.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + ACBE8CC3EBD2241E730ED6EC0C4DBEFE /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 6E8F39BF4A1C5F1E982D92DCA17F3F81 /* ALView+PureLayout.h in Headers */, + BE96007160D646D5D68896BDE0B00D9E /* NSArray+PureLayout.h in Headers */, + F7494F8E4C6D5539E6C0F508835D855E /* NSLayoutConstraint+PureLayout.h in Headers */, + 424B6359A6CAD01698B3BCBB378ADEC4 /* PureLayout+Internal.h in Headers */, + 47DD648261705696CD717E721480E312 /* PureLayout-umbrella.h in Headers */, + 242EF6A41F451AE94E70F6D3865B2115 /* PureLayout.h in Headers */, + 83A1D722DD1D5887B34219BF898DF1F1 /* PureLayoutDefines.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D04A8FE1A0C091B803D65246BD8EC96D /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 48C2284F5ACCBC817C5A01C6D02D2F65 /* Charts-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D152500F4571A8F34F693E2649D0A20B /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 73BD034A9B00F30A1A4014EC98C5A2FC /* Eddystone-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FD7134B3FF76D9D20AF301B1F872564D /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 80EBFB2111125DA63FA6F204357D515F /* UICircularProgressRing-umbrella.h in Headers */, + 010278E0BBEA52A0CB768888480E3E04 /* UICircularProgressRing.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 05B9852E4B188EF4EC93B1E3F0712B2E /* ActionSheetPicker-3.0 */ = { + isa = PBXNativeTarget; + buildConfigurationList = B834EE00D33BF8584CE5177AF20C74F5 /* Build configuration list for PBXNativeTarget "ActionSheetPicker-3.0" */; + buildPhases = ( + 777508A22BC8235FB0387E89D6A9C12A /* Headers */, + 3F7FFB982F0051A523B49D4585B3471E /* Sources */, + E7AC33846B2CD4AEB1866E4358CD769B /* Frameworks */, + 5087E7F7F15CCE848382FEF4A0A3C777 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "ActionSheetPicker-3.0"; + productName = "ActionSheetPicker-3.0"; + productReference = 615EB05A5D732CD0F7153D6D8294F3CF /* ActionSheetPicker_3_0.framework */; + productType = "com.apple.product-type.framework"; + }; + 212B86B3B83BCB71159494262747DFCF /* PureLayout */ = { + isa = PBXNativeTarget; + buildConfigurationList = 291A39B31F01BB2B0ADF4D6B9F952D2A /* Build configuration list for PBXNativeTarget "PureLayout" */; + buildPhases = ( + ACBE8CC3EBD2241E730ED6EC0C4DBEFE /* Headers */, + C5A3EF26A67FD629FF2EA74A3E4C7CD1 /* Sources */, + 6044F31A04D991E32712DC4BE35BAA89 /* Frameworks */, + 07D2FF2D9CA44BAE25F049A872723114 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = PureLayout; + productName = PureLayout; + productReference = 965D4237C5D838A4CF76399A7566B7EA /* PureLayout.framework */; + productType = "com.apple.product-type.framework"; + }; + 4273171B8F85B95806C7A7AEE258783F /* ChameleonFramework */ = { + isa = PBXNativeTarget; + buildConfigurationList = B4616CC585387D9A6335E1A1A4776AEA /* Build configuration list for PBXNativeTarget "ChameleonFramework" */; + buildPhases = ( + 54300B358FA282D36084AA0126604146 /* Headers */, + C882EDC0ED816FC0E17E7FC9270FE8AB /* Sources */, + 490C2BF785E49900C2AF94977BD5BF15 /* Frameworks */, + F9FD8BB69ECA8A8A8481522FDCD9806A /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = ChameleonFramework; + productName = ChameleonFramework; + productReference = 3BF45EB6B838A2578EE62E2942C14FE0 /* ChameleonFramework.framework */; + productType = "com.apple.product-type.framework"; + }; + 4290C2C625CBB8BADA3E2237D4C59EC2 /* Pods-BlueGeckoWithHomeKit */ = { + isa = PBXNativeTarget; + buildConfigurationList = 2C9C780415F74DD9F39BE8872C5650DA /* Build configuration list for PBXNativeTarget "Pods-BlueGeckoWithHomeKit" */; + buildPhases = ( + 5C9EB7AEA7731EEB7CA79A8E6E651D8F /* Headers */, + 4AB77914F382D6BE370F39D16EFD249D /* Sources */, + C04435A890A45A88F67D4CB1088C6651 /* Frameworks */, + 0CB8BFFA854CCC659FBE07C77A149E06 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 1F85290DF2A38C1089137E36EA72635D /* PBXTargetDependency */, + 61D0F0C641B54F991664B592317CAACF /* PBXTargetDependency */, + 3A30B3FE4DA6006A3B6EBC47878BF776 /* PBXTargetDependency */, + 44FE209DD968B7EA36C9EECD2D93CBA1 /* PBXTargetDependency */, + 331327299D31120D1E39CB80BD7B771E /* PBXTargetDependency */, + 307AF4C6F7D7DBBA2F924C6BD749F785 /* PBXTargetDependency */, + 7A1D1648158A02C64EE37FB55D86592F /* PBXTargetDependency */, + 8E7F5A759BCED603D1C66B2AD570E6DC /* PBXTargetDependency */, + 99D8E66C28EB81DCA85D946A033B6DDC /* PBXTargetDependency */, + E93735055BFDB5736612D54EEC66BD16 /* PBXTargetDependency */, + 2BD1440D1529E34BCCF44DBE97204D41 /* PBXTargetDependency */, + 911A989C20DFA5EE0380A247C84C5F0C /* PBXTargetDependency */, + ); + name = "Pods-BlueGeckoWithHomeKit"; + productName = "Pods-BlueGeckoWithHomeKit"; + productReference = A851794C72EE6DDC0384C1F864B82499 /* Pods_BlueGeckoWithHomeKit.framework */; + productType = "com.apple.product-type.framework"; + }; + 50C8BE3E50EE30CE69A6C1715D047E60 /* XMLDictionary */ = { + isa = PBXNativeTarget; + buildConfigurationList = AF8912DE519E16140B8D79115FE8B9DB /* Build configuration list for PBXNativeTarget "XMLDictionary" */; + buildPhases = ( + A9199DFFF761F3724080492034518DA2 /* Headers */, + F570AF41DB7E6E80A8FC1513AB29A2FE /* Sources */, + 1988D50CAD70C441B83C21034BDF3930 /* Frameworks */, + 68C9643351621D359980C898E909E9E3 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = XMLDictionary; + productName = XMLDictionary; + productReference = 0FF654CBD08386066DA5FC6DBDCFA5E3 /* XMLDictionary.framework */; + productType = "com.apple.product-type.framework"; + }; + 5B03F2322DD9BCD22A8A37FD2E19849B /* KVOController */ = { + isa = PBXNativeTarget; + buildConfigurationList = C33F2C7CA199F19B1C71AC1910CB0DD2 /* Build configuration list for PBXNativeTarget "KVOController" */; + buildPhases = ( + A0CE1CA51299B34C4C74CCA305981B1D /* Headers */, + 71E7E5338ACBB5F968C4DBD413D812A0 /* Sources */, + D1B9672CEFB3642DF314D45859F65B38 /* Frameworks */, + 05A52CF833C2A25F69E79CB7FF2A3079 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = KVOController; + productName = KVOController; + productReference = 15FD537E0175B3C57E5421243EF658DB /* KVOController.framework */; + productType = "com.apple.product-type.framework"; + }; + 5DA9D424D96F4D772D20C95ED50F5163 /* MZTimerLabel */ = { + isa = PBXNativeTarget; + buildConfigurationList = A36326D57965E7621B61FEC00B1B4775 /* Build configuration list for PBXNativeTarget "MZTimerLabel" */; + buildPhases = ( + 5D3BAC2B0B7E85F3D8782E1BB866D427 /* Headers */, + DB1BB097ACB2650A2CBE06D550120AD4 /* Sources */, + 0F501AE1C2B4AFE81D4D7615BBB8B847 /* Frameworks */, + 590CA445C46751EB18A6F629E4A33940 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = MZTimerLabel; + productName = MZTimerLabel; + productReference = 54E6CCB4DDD5185E52FB9F09B31D815A /* MZTimerLabel.framework */; + productType = "com.apple.product-type.framework"; + }; + 5FA4F2F40241D9CBE948E0161E4C428D /* Eddystone-Eddystone */ = { + isa = PBXNativeTarget; + buildConfigurationList = EDA758D09698B63034770DE3E00C2AA8 /* Build configuration list for PBXNativeTarget "Eddystone-Eddystone" */; + buildPhases = ( + 8AE69C7794446E77CAF997A70EE416EB /* Sources */, + BC996BC15A9DDDBF8178263A9A538C84 /* Frameworks */, + E1F081DACE0212F8E9CB849F24D3975A /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Eddystone-Eddystone"; + productName = "Eddystone-Eddystone"; + productReference = 570A1B1BC5E57682C35D8D67DA876885 /* Eddystone.bundle */; + productType = "com.apple.product-type.bundle"; + }; + 8D721B7ADC82CCCBC060EAA131A0A40A /* Eddystone */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4944B2FE6AD982ED2987052521780E16 /* Build configuration list for PBXNativeTarget "Eddystone" */; + buildPhases = ( + D152500F4571A8F34F693E2649D0A20B /* Headers */, + 49E053662C9A717154E08702185CC9E1 /* Sources */, + 94B41328ED431B6EE4EE1F810BA0E51F /* Frameworks */, + 61086FDA7A72BAFF3767E3DCED555E1E /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + FBC7CF501F6A8AE65EDF14D119E4202D /* PBXTargetDependency */, + ); + name = Eddystone; + productName = Eddystone; + productReference = 985BC5A9FDFCD09FA3C33FD0313A280B /* Eddystone.framework */; + productType = "com.apple.product-type.framework"; + }; + 99E8E0D6846CC782E53B7D73C11ACDEA /* UICircularProgressRing */ = { + isa = PBXNativeTarget; + buildConfigurationList = B2542112051BCD04F474D595AAF717EE /* Build configuration list for PBXNativeTarget "UICircularProgressRing" */; + buildPhases = ( + FD7134B3FF76D9D20AF301B1F872564D /* Headers */, + E815F39BFA635CCA79320783CD788B4E /* Sources */, + F9A23D07EA2CB83AB5CE4EC8BC9538FF /* Frameworks */, + 30B80BC208D5D194804B0911E33638C0 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = UICircularProgressRing; + productName = UICircularProgressRing; + productReference = D3BD3586B983B0E863C734EBF95EB51C /* UICircularProgressRing.framework */; + productType = "com.apple.product-type.framework"; + }; + ADC77208EBF819EC34A108BD6FF127AB /* Pods-BlueGecko */ = { + isa = PBXNativeTarget; + buildConfigurationList = 398F9CB00B060EB64F66747820AA5DDE /* Build configuration list for PBXNativeTarget "Pods-BlueGecko" */; + buildPhases = ( + 4E7E5DC34B7E382207E43517A01E899A /* Headers */, + 811F6CB4BC5D3D8E1656031B9B98F613 /* Sources */, + 5CE57E768FCAE6C778F71A96A88574C9 /* Frameworks */, + D7EC8371191775CCFC318D5C484E2910 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 97707B05C62F2BC63BDEFCDA4FDF1399 /* PBXTargetDependency */, + 362F2BD139D14654E7E9AA5CC8B80591 /* PBXTargetDependency */, + 8C7676A6F8701E301660D42005E35BD2 /* PBXTargetDependency */, + 67C516BEB56BBC4563B7BD32E3F437B6 /* PBXTargetDependency */, + 9C5716FCB164C5A938225E6352B305C3 /* PBXTargetDependency */, + 38374D4A6FB1D1AE51823E961C0DDFF3 /* PBXTargetDependency */, + AC06D1E19C67FDA3958137C5A06E634B /* PBXTargetDependency */, + B1756DE869CCE608C096CE6EA633E5DF /* PBXTargetDependency */, + F6ED5090C578B9A67084101FDD9CBF57 /* PBXTargetDependency */, + 6A2D86558FD87AF11179C6B49AC1A493 /* PBXTargetDependency */, + 9578B8F51ADBA198790D05654E3CF49F /* PBXTargetDependency */, + EC364459FC580F99E6BD3AE2182449D7 /* PBXTargetDependency */, + ); + name = "Pods-BlueGecko"; + productName = "Pods-BlueGecko"; + productReference = 177040E6D2D515FBF376337FD0273F59 /* Pods_BlueGecko.framework */; + productType = "com.apple.product-type.framework"; + }; + AEF4BF40039DBEDE68615E1A32E2E805 /* WYPopoverController */ = { + isa = PBXNativeTarget; + buildConfigurationList = 651E09ACC296CD9A4D79FDD91EBB82BC /* Build configuration list for PBXNativeTarget "WYPopoverController" */; + buildPhases = ( + 39552F1C3126CC2B9003A65330CE0E6D /* Headers */, + 66E82ABAD47CFB92EFD85C8EF3A3F1F0 /* Sources */, + E64ADE0F2AC7EE029405E7FE5414626E /* Frameworks */, + 66804BF9445DAAE5C5D763ECE9B5ADBF /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = WYPopoverController; + productName = WYPopoverController; + productReference = F4D22822A7DF1234CB711AEA38325A51 /* WYPopoverController.framework */; + productType = "com.apple.product-type.framework"; + }; + E384B3C7B2878E9354E03BBC33901EA0 /* SVProgressHUD */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4A2EAC09B8DFF5A4B349CDB5A08984FA /* Build configuration list for PBXNativeTarget "SVProgressHUD" */; + buildPhases = ( + 73957F140CBBD023C8756A8DA0DE1B47 /* Headers */, + 4E896F5C62A7E68D14102BE3FD2C56CD /* Sources */, + 07D5F2600190C23737FC75988AE55E3C /* Frameworks */, + 5022D1CEF02E535F4339F7ECDC3D6BAD /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = SVProgressHUD; + productName = SVProgressHUD; + productReference = F5F6C9219F51DD4C41E6625C1ED9DE89 /* SVProgressHUD.framework */; + productType = "com.apple.product-type.framework"; + }; + E715D783410216803ED82EC21CD5C31B /* IP-UIKit-Wisdom */ = { + isa = PBXNativeTarget; + buildConfigurationList = AD71D43FB0431C3180B7C19CD57E279B /* Build configuration list for PBXNativeTarget "IP-UIKit-Wisdom" */; + buildPhases = ( + 45BE5DEFE0CC671E8F138442B4155B4A /* Headers */, + DF16A50C5C93C2A7DFC323A6E2D20B73 /* Sources */, + 7B8FB2F06997DC0E98F0B377347786E0 /* Frameworks */, + 96EAC626D08EB584438F5E53907BAC1C /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "IP-UIKit-Wisdom"; + productName = "IP-UIKit-Wisdom"; + productReference = 4F1ED9B0B53CB5D2EE236D8CB7EDBC29 /* IP_UIKit_Wisdom.framework */; + productType = "com.apple.product-type.framework"; + }; + EBFD1DA8DB9C5E9C282BBCAD1778A64A /* Charts */ = { + isa = PBXNativeTarget; + buildConfigurationList = 232465D02EE4BB98B5673A80AB4C5B0C /* Build configuration list for PBXNativeTarget "Charts" */; + buildPhases = ( + D04A8FE1A0C091B803D65246BD8EC96D /* Headers */, + C3F85362D2C1A448871B75640E779191 /* Sources */, + 27651B48E00B05B5B51AABD201BABD7A /* Frameworks */, + 074ADB43C9DB1D9F8675F3FA016C16F8 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Charts; + productName = Charts; + productReference = 1E17B506648944D28343B82A00BAA8C4 /* Charts.framework */; + productType = "com.apple.product-type.framework"; + }; + F054EBE09B5C440F963244283160FC0F /* Pods-WirelessGecko */ = { + isa = PBXNativeTarget; + buildConfigurationList = 5B15DDC21CB08F831A6D2CF2828836DF /* Build configuration list for PBXNativeTarget "Pods-WirelessGecko" */; + buildPhases = ( + 29C44169C519BC7CB5DFA88661C2B20A /* Headers */, + F847381E93F53CC0C5F247ED955AB292 /* Sources */, + 39BEF469CC65E846DCF1E7A056C0AD80 /* Frameworks */, + 62202003CD42EEB0E64681A0D86BA00C /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + DF401E4DF9F70B692EECF66D208D8C6C /* PBXTargetDependency */, + 31608157B7C435C2D2F1576DCCD26722 /* PBXTargetDependency */, + 67AEB7D5B7319B30FD1AEE79DA8B65B7 /* PBXTargetDependency */, + E869A0C85DC5B4212580A52FF957B853 /* PBXTargetDependency */, + D354861A72BF938A67B52E5A0F5DE8FA /* PBXTargetDependency */, + 97052024D1AAE01C7BD0847B51307DC3 /* PBXTargetDependency */, + 78D6A27DF7B9B4851AE32E3590AE989E /* PBXTargetDependency */, + 1F4FCF75D804486929083B9BBC9D4290 /* PBXTargetDependency */, + 8F1A4F01A849D2EF25FF8B4AF2C68DC3 /* PBXTargetDependency */, + 1628ECFBA6FD7A6D7FC101BA42B8CEAF /* PBXTargetDependency */, + 8A7A01F9359F89E8F15E255DCE327413 /* PBXTargetDependency */, + B799EB5B2B14CC48FA6789D6C959BC1D /* PBXTargetDependency */, + ); + name = "Pods-WirelessGecko"; + productName = "Pods-WirelessGecko"; + productReference = B3FB7553E32B27A6CC38F6038C2E713A /* Pods_WirelessGecko.framework */; + productType = "com.apple.product-type.framework"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + D41D8CD98F00B204E9800998ECF8427E /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0930; + LastUpgradeCheck = 0930; + }; + buildConfigurationList = 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 7DB346D0F39D3F0E887471402A8071AB; + productRefGroup = 63C4F662759676E3FB3D870571D7C9CE /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 05B9852E4B188EF4EC93B1E3F0712B2E /* ActionSheetPicker-3.0 */, + 4273171B8F85B95806C7A7AEE258783F /* ChameleonFramework */, + EBFD1DA8DB9C5E9C282BBCAD1778A64A /* Charts */, + 8D721B7ADC82CCCBC060EAA131A0A40A /* Eddystone */, + 5FA4F2F40241D9CBE948E0161E4C428D /* Eddystone-Eddystone */, + E715D783410216803ED82EC21CD5C31B /* IP-UIKit-Wisdom */, + 5B03F2322DD9BCD22A8A37FD2E19849B /* KVOController */, + 5DA9D424D96F4D772D20C95ED50F5163 /* MZTimerLabel */, + ADC77208EBF819EC34A108BD6FF127AB /* Pods-BlueGecko */, + 4290C2C625CBB8BADA3E2237D4C59EC2 /* Pods-BlueGeckoWithHomeKit */, + F054EBE09B5C440F963244283160FC0F /* Pods-WirelessGecko */, + 212B86B3B83BCB71159494262747DFCF /* PureLayout */, + E384B3C7B2878E9354E03BBC33901EA0 /* SVProgressHUD */, + 99E8E0D6846CC782E53B7D73C11ACDEA /* UICircularProgressRing */, + AEF4BF40039DBEDE68615E1A32E2E805 /* WYPopoverController */, + 50C8BE3E50EE30CE69A6C1715D047E60 /* XMLDictionary */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 05A52CF833C2A25F69E79CB7FF2A3079 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 074ADB43C9DB1D9F8675F3FA016C16F8 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 07D2FF2D9CA44BAE25F049A872723114 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0CB8BFFA854CCC659FBE07C77A149E06 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 30B80BC208D5D194804B0911E33638C0 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5022D1CEF02E535F4339F7ECDC3D6BAD /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 465287E08F63302BA3C1784CC76A68BF /* SVProgressHUD.bundle in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5087E7F7F15CCE848382FEF4A0A3C777 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 590CA445C46751EB18A6F629E4A33940 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 61086FDA7A72BAFF3767E3DCED555E1E /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 11955C722AC0851FA9B22BECF682E504 /* Eddystone.bundle in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 62202003CD42EEB0E64681A0D86BA00C /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 66804BF9445DAAE5C5D763ECE9B5ADBF /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 68C9643351621D359980C898E909E9E3 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 96EAC626D08EB584438F5E53907BAC1C /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D7EC8371191775CCFC318D5C484E2910 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E1F081DACE0212F8E9CB849F24D3975A /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + F9FD8BB69ECA8A8A8481522FDCD9806A /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 3F7FFB982F0051A523B49D4585B3471E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 2DA0045270F2FE8718E7366D1CFC01B2 /* AbstractActionSheetPicker.m in Sources */, + F131FE90B8E873F55FF192FF10A19076 /* ActionSheetCustomPicker.m in Sources */, + 10D4EFE38FFFE3C7F222D35B62E728ED /* ActionSheetDatePicker.m in Sources */, + F61761312E0D741D61DC09E02BCA6DE9 /* ActionSheetDistancePicker.m in Sources */, + 9E1EA37140FB4DB5589924D069E0F040 /* ActionSheetLocalePicker.m in Sources */, + 33FF9B2BEC508A588DCB31462B7306A0 /* ActionSheetMultipleStringPicker.m in Sources */, + DA35E172CFC080BBAB284AF2790DB7F2 /* ActionSheetPicker-3.0-dummy.m in Sources */, + 403C5D9AAD792C6FAFFE3961911E5162 /* ActionSheetStringPicker.m in Sources */, + 6DE8C977E77B7A9F692376E009B82254 /* DistancePickerView.m in Sources */, + 70052EBBCE4D6B524FD4558E1C2E1696 /* SWActionSheet.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 49E053662C9A717154E08702185CC9E1 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + C9A262A3B22241C5F9C5EE2064636869 /* Beacon.swift in Sources */, + D65C1FF368529A12B2E8B7F157B1DCD6 /* CoreBluetoothExtensions.swift in Sources */, + 5327D9E9061239D9A5218F343DB785DA /* DoubleExtensions.swift in Sources */, + 5531E1784474442E9ADB17A7539521AC /* Eddystone-dummy.m in Sources */, + 15E5AD179F758E805959ED9B862CB5BC /* Frame.swift in Sources */, + A6570502D82990F2A31D021D685B69F7 /* Generic.swift in Sources */, + 867B5476B4D0056DE696287063748449 /* Global.swift in Sources */, + 9C9E8501F44A72B46ECF922859CFED03 /* IntExtensions.swift in Sources */, + 0C153F4A8B82DC9EA5E04215CD3415B2 /* NSTimeIntervalExtensions.swift in Sources */, + A6721015E658A04A721FE760643D6157 /* Object.swift in Sources */, + B4F8DF6260122D8C12A3A1D59026BC3B /* Scanner.swift in Sources */, + 0BCB4BFFCBDAC83FF711E9AE95E74615 /* TlmFrame.swift in Sources */, + 27744A9BE9F4E1D629F27C9C0B2CA0EB /* Uid.swift in Sources */, + DB4F08C219191CDB5225FCE00473BA33 /* UidFrame.swift in Sources */, + 337D6A47FE93CE6CF2012C62824DE835 /* Url.swift in Sources */, + 640DFE29FC42AAB9B97720C6C4143432 /* UrlFrame.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4AB77914F382D6BE370F39D16EFD249D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 262CBA8BDB05D437E3228708E7C31451 /* Pods-BlueGeckoWithHomeKit-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4E896F5C62A7E68D14102BE3FD2C56CD /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DBD7F1B4E5FCD19ED2AF4587ECB135FE /* SVIndefiniteAnimatedView.m in Sources */, + EF17EA942480F7242CFDBC3A7BBD5705 /* SVProgressAnimatedView.m in Sources */, + EA10E82D4BBDBE2575862FBE7A0C4C04 /* SVProgressHUD-dummy.m in Sources */, + AD1F14554F6D1F1313568CCF7346FF6F /* SVProgressHUD.m in Sources */, + B4F1A6377FC8113770335D930C079C70 /* SVRadialGradientLayer.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 66E82ABAD47CFB92EFD85C8EF3A3F1F0 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + F5E44281520A56C266B186F502B7B23B /* WYPopoverController-dummy.m in Sources */, + 4F2ADB5162BDB173B960EC455FFC76D1 /* WYPopoverController.m in Sources */, + F8BB86EAA51DCC2F1121B7907EC5D21B /* WYStoryboardPopoverSegue.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 71E7E5338ACBB5F968C4DBD413D812A0 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DCD507135C42B7651AD685A2D3811BB2 /* FBKVOController.m in Sources */, + D979651A01A2CCB1600FC373C39B4C3A /* KVOController-dummy.m in Sources */, + E1AD4B4DE359DF79DDCDCC0D877797A2 /* NSObject+FBKVOController.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 811F6CB4BC5D3D8E1656031B9B98F613 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 9EAE6A25D87CACB3469A5FE41922F582 /* Pods-BlueGecko-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8AE69C7794446E77CAF997A70EE416EB /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C3F85362D2C1A448871B75640E779191 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D12FB77C9C64D1E7A691407206DA2348 /* AnimatedMoveViewJob.swift in Sources */, + 77AAE9E936660E1EFB1BAD250D10C5C8 /* AnimatedViewPortJob.swift in Sources */, + C3CC572A93496D96D1514C110C05D4A9 /* AnimatedZoomViewJob.swift in Sources */, + A5AB8E85B4EAB2E0958191FA978948E6 /* Animator.swift in Sources */, + 6B2D8E86FC5988707F276D63E6D09843 /* AxisBase.swift in Sources */, + B3AC852255B3BB778847B171C675296B /* AxisRendererBase.swift in Sources */, + 2D178BC8412501794934B2C13AD6FE0B /* BarChartData.swift in Sources */, + 5E7F7D5A2B60547DEDB75E322B85C1E3 /* BarChartDataEntry.swift in Sources */, + F869D5CDB92AFEAFB507B3BC097E87D6 /* BarChartDataProvider.swift in Sources */, + DC4BBBCECB152203D4901B930197C668 /* BarChartDataSet.swift in Sources */, + AD8BDD5A9231068B37619FBDAEC06DE4 /* BarChartRenderer.swift in Sources */, + 13BCBF3CEA918A8C633835213BA3029D /* BarChartView.swift in Sources */, + 9523929E8668F0E72243B5D8E7379CF2 /* BarHighlighter.swift in Sources */, + EF203789B9D827C23D6C5B894C239CAE /* BarLineChartViewBase.swift in Sources */, + 8817670F999F88091A8E1A7AC59B5DD0 /* BarLineScatterCandleBubbleChartData.swift in Sources */, + A497C4B9650355975228FC86A9F88026 /* BarLineScatterCandleBubbleChartDataProvider.swift in Sources */, + 81E72938A6165A7F476DF08F511A1B66 /* BarLineScatterCandleBubbleChartDataSet.swift in Sources */, + 3813534CDF6D03A333E4624D011DD887 /* BarLineScatterCandleBubbleRenderer.swift in Sources */, + 0523419917399AD061A8590C49C94419 /* BubbleChartData.swift in Sources */, + C7948DD19484AD97B80E7622B9A9BCAC /* BubbleChartDataEntry.swift in Sources */, + F87B87AB390DE5D24C4CAE8C30108A16 /* BubbleChartDataProvider.swift in Sources */, + 6B8FC7C9E95AB1715333AAAB260C8185 /* BubbleChartDataSet.swift in Sources */, + 9512CDA083EA61F299A467BF4678A2FB /* BubbleChartRenderer.swift in Sources */, + 9CCF6EF2287763656A9E86F7552998E7 /* BubbleChartView.swift in Sources */, + CEAF967ACE976FF757ECDC3524E0F03D /* CandleChartData.swift in Sources */, + 8CD86FA725C57D6F6FE9DA4132AC16E9 /* CandleChartDataEntry.swift in Sources */, + 8C46ADC14759E79D0D4CBC63E3E14B80 /* CandleChartDataProvider.swift in Sources */, + FA61E357CF88BC5817DF5628C8C143CE /* CandleChartDataSet.swift in Sources */, + 934543CDC3E37251DE163ADB4B6820FD /* CandleStickChartRenderer.swift in Sources */, + FC7DC5345AC5BD330F9F9C640151C745 /* CandleStickChartView.swift in Sources */, + 8EEBBB90A27B8CCF754B7BEAC5E460C8 /* ChartAnimationEasing.swift in Sources */, + CC2E2E413D6125F7636C4A0B3F6DFFCC /* ChartBaseDataSet.swift in Sources */, + 7306E7AA1468FE0833BEAEB0D50A99DD /* ChartColorTemplates.swift in Sources */, + 1374ABF417D13A2D8EFEAFFC359F4E08 /* ChartData.swift in Sources */, + 2716A86BD9C6CFE03AC4E43024380CCD /* ChartDataEntry.swift in Sources */, + 567E47EE5AA042E2475AA8AC19F35060 /* ChartDataEntryBase.swift in Sources */, + 0C2D47415AE6B9354BAE3B627A92142E /* ChartDataProvider.swift in Sources */, + 8502610E39EA4DA1C645D85AC1BD9F49 /* ChartDataRendererBase.swift in Sources */, + A11AA27F116FF1637A8FE254AF6F044C /* ChartDataSet.swift in Sources */, + FDE4713E6FF767EC7157F283F969F8F9 /* ChartHighlighter.swift in Sources */, + E86B6328D8296809B25F536C5F10CD4B /* ChartLimitLine.swift in Sources */, + 3AC69C422C561D15607B45558F50EE05 /* Charts-dummy.m in Sources */, + B15FC25978BE630AAE96635D17907A71 /* ChartUtils.swift in Sources */, + EE30E67B79136BE20215583604092326 /* ChartViewBase.swift in Sources */, + B05E520812AA92A479EB9EAA29C88B97 /* ChevronDownShapeRenderer.swift in Sources */, + 120700249562CDA7600D877DC70FAA25 /* ChevronUpShapeRenderer.swift in Sources */, + 20DF05B97A06AE53FAC46AEF64C38C9B /* CircleShapeRenderer.swift in Sources */, + 092011BD13C259D986642B5A842CF997 /* CombinedChartData.swift in Sources */, + 582C17C37CCCCC12A71016020B1E6F9A /* CombinedChartDataProvider.swift in Sources */, + 61C446A2F28E4F813CB130B6C772F857 /* CombinedChartRenderer.swift in Sources */, + A00B3B20DB010F2F289E90A965E0ACA9 /* CombinedChartView.swift in Sources */, + 5B92725F46360893493FA626926F80F2 /* CombinedHighlighter.swift in Sources */, + F7A9B63B2EE7B49C97809FF5F8F2E413 /* ComponentBase.swift in Sources */, + 74EC7DA37555A322E231D48B8E11F774 /* CrossShapeRenderer.swift in Sources */, + 4B4EDA65A6E6FAE8B37BA47B53A3C7E3 /* DataApproximator+N.swift in Sources */, + ACC0988FA6FD531E5EF82ECD0B0F8F72 /* DataApproximator.swift in Sources */, + 10422A83E5E7CE748FEC304F9910EE7F /* DefaultAxisValueFormatter.swift in Sources */, + 66F8FFDDA535894825A2E9D3490A85F6 /* DefaultFillFormatter.swift in Sources */, + EFE5F0E288D5582F37B69E838FE907BC /* DefaultValueFormatter.swift in Sources */, + 96C8BE77C6E26E4B9312D62F5C211269 /* Description.swift in Sources */, + D6FB3C2B3E18583390ECA4FDA97A1EEA /* Fill.swift in Sources */, + 259E5C8AE4AD8BC8C9FB88460A605B81 /* Highlight.swift in Sources */, + F16A032A811867FF6323143582E47951 /* HorizontalBarChartRenderer.swift in Sources */, + 2A5B8D6DE57B4AA3CEF0B365282AE019 /* HorizontalBarChartView.swift in Sources */, + F1D096BE7FD7AD4CE1135805B170BBB4 /* HorizontalBarHighlighter.swift in Sources */, + A191E3933EEFD02A9ACEC22B12A436A5 /* IAxisValueFormatter.swift in Sources */, + E60188A7E4C69337B6840D7875A539C2 /* IBarChartDataSet.swift in Sources */, + A7F8937FA0B184FB4A9CBF94AFD5C9CA /* IBarLineScatterCandleBubbleChartDataSet.swift in Sources */, + F48A2073BF27DD81DA781B5AEC15E10A /* IBubbleChartDataSet.swift in Sources */, + 4972D596D54D5CCEC57DFA1EAECEC630 /* ICandleChartDataSet.swift in Sources */, + 5830202DA5E8E5FA0734046FD00CA9AB /* IChartDataSet.swift in Sources */, + 644E05CE5F65D923C4FE3BE9BDC78B7D /* IFillFormatter.swift in Sources */, + E922EAB5357E2B0C01D49E9A3D6F3272 /* IHighlighter.swift in Sources */, + FF3FE753D8E3A0AFB85E4CB28425FBDB /* ILineChartDataSet.swift in Sources */, + 4163B8B1DA697452C9B9263EB3881F4F /* ILineRadarChartDataSet.swift in Sources */, + 31306D0B409E67CD2CA7D20932999D05 /* ILineScatterCandleRadarChartDataSet.swift in Sources */, + 1F05F6D0C5B42853B61057FF1D2EEBF4 /* IMarker.swift in Sources */, + 2C2C310BA513CB6FCC892407531A515F /* IndexAxisValueFormatter.swift in Sources */, + 989CB1FF8E0FD8DF5B1A0C9EC57CD91D /* IPieChartDataSet.swift in Sources */, + 3ACBEC5B851B694C829A666899BA0490 /* IRadarChartDataSet.swift in Sources */, + A63B3C9A2AAB3A8D5BF63A882225FFFA /* IScatterChartDataSet.swift in Sources */, + 420356FB05B461AD4BA9959E5371ACF4 /* IShapeRenderer.swift in Sources */, + 16D3DB873C209F7BF08A69B9B4433518 /* IValueFormatter.swift in Sources */, + 03C332CE48CE563BE34889A93661197B /* Legend.swift in Sources */, + 771FB69AC8E6605083E63FB27AC951A4 /* LegendEntry.swift in Sources */, + 84925CC6CD24D46DBC0800942AD1C306 /* LegendRenderer.swift in Sources */, + A4DF0869E33A835721E12663EB81D37B /* LineChartData.swift in Sources */, + 400D2652B78FA1A8C4060EB5E7A855EB /* LineChartDataProvider.swift in Sources */, + 9D7A80B2B72F4FBC01765B25B7B0033D /* LineChartDataSet.swift in Sources */, + 856FA8FD6609AC750670E2FA996BADF8 /* LineChartRenderer.swift in Sources */, + 2711C9950721F9F90A0F4D521C730669 /* LineChartView.swift in Sources */, + 87CACFF8D1DEB6F794AC8DDCE8D52721 /* LineRadarChartDataSet.swift in Sources */, + 96C0FF8A72036FF83A4752A02B811B5B /* LineRadarRenderer.swift in Sources */, + 60A61A5EA6BDBD5601299DDB5A52C14A /* LineScatterCandleRadarChartDataSet.swift in Sources */, + 7FD267EC050B1AF18FF090EA036FEAA9 /* LineScatterCandleRadarRenderer.swift in Sources */, + 0ED96EFE059D12B6AC01346B2F85ECDC /* MarkerImage.swift in Sources */, + FE3BC02AF9FEFFA71AE4E0D8A3FB2B39 /* MarkerView.swift in Sources */, + 386D90589762A4FD681E22DE927F86F5 /* MoveViewJob.swift in Sources */, + A23C15CFFE2F0E3EFBC92FE4E799A255 /* PieChartData.swift in Sources */, + D423F046852D73CC7407370136F924CE /* PieChartDataEntry.swift in Sources */, + 201D14A4C9331751467DB4BF157315B4 /* PieChartDataSet.swift in Sources */, + EBC9299FE403A45B246F74297CD8A05A /* PieChartRenderer.swift in Sources */, + BD919F30AE8401BD08F15505B8AE8ABE /* PieChartView.swift in Sources */, + 4D24FC0EF43B398C4F35E15A255C9DD4 /* PieHighlighter.swift in Sources */, + 86672ED0548E81E771A5A6C11239D9C2 /* PieRadarChartViewBase.swift in Sources */, + 778CFAB2FF431A7CA34821B18DCD332B /* PieRadarHighlighter.swift in Sources */, + 610605379D549B8246F4689CAE528114 /* Platform+Accessibility.swift in Sources */, + 31AD1217C2BD4F460EE4F7C577A9BEE7 /* Platform.swift in Sources */, + C662028048556D063A9AC1B784988B8D /* RadarChartData.swift in Sources */, + B9FA3D63FE523FF1E97CA50AEDDF1833 /* RadarChartDataEntry.swift in Sources */, + F1A0BACF2A146A439122863794F734EE /* RadarChartDataSet.swift in Sources */, + BE9064297027980C803A495B0BD36364 /* RadarChartRenderer.swift in Sources */, + 442177EFE00C04905F9911A2ECE5526F /* RadarChartView.swift in Sources */, + E83DD47D94C577B3D5F672C7A5C55467 /* RadarHighlighter.swift in Sources */, + 987C7F5C034715EB4A264175B8FA3AEB /* Range.swift in Sources */, + A35899B69536C89FD209D72189189429 /* Renderer.swift in Sources */, + 1418477303438487238188481990757F /* ScatterChartData.swift in Sources */, + 669421AC5F4FA4EC7D13F08575D53B6F /* ScatterChartDataProvider.swift in Sources */, + 6C5AA261DE2D6CA33DA0BC60C50BFF85 /* ScatterChartDataSet.swift in Sources */, + 377F167BDAB0482CE83004E98F086F82 /* ScatterChartRenderer.swift in Sources */, + 0A614755B0258F2C584D57BAF43245E0 /* ScatterChartView.swift in Sources */, + EF0752D7045F333EB6B017BABDC63984 /* SquareShapeRenderer.swift in Sources */, + 431DFD0E3CD1671726DC33F6650FE4C7 /* Transformer.swift in Sources */, + F3F4F80C0BAE1855B294ADAFC6BEC67E /* TransformerHorizontalBarChart.swift in Sources */, + 70E59FA2437A59807C900A9E381172E6 /* TriangleShapeRenderer.swift in Sources */, + 618F0C277CFA69A5433DAA11EB68538A /* ViewPortHandler.swift in Sources */, + 7F89B8FC19832264C0567C9BABC3654B /* ViewPortJob.swift in Sources */, + BE18FA232ADFD92A0E9299B254555FB9 /* XAxis.swift in Sources */, + 85F46AC0868623936E84FBD678B986EF /* XAxisRenderer.swift in Sources */, + 4D033F63E586719C6DD61DC0D16DAD5E /* XAxisRendererHorizontalBarChart.swift in Sources */, + 98371A8C65AF1373CA3887E187B16ABC /* XAxisRendererRadarChart.swift in Sources */, + B1D52A9C38BE10BE4229506B91103133 /* XShapeRenderer.swift in Sources */, + F08904E8835E4279192C40CA6474A13C /* YAxis.swift in Sources */, + C80AEEF00532797FF769CF482E568473 /* YAxisRenderer.swift in Sources */, + C81103311755CCE17B7373294BB2E1BF /* YAxisRendererHorizontalBarChart.swift in Sources */, + DE454B28B9AC9F7C42839AA55D7574D2 /* YAxisRendererRadarChart.swift in Sources */, + 2E2100236D2D416E636F93BD7C42EAAD /* ZoomViewJob.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C5A3EF26A67FD629FF2EA74A3E4C7CD1 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + F84691EFFFCE729C9642D3110EF4385D /* ALView+PureLayout.m in Sources */, + 4FAC92B47BCF4935FB5BE481B54A439D /* NSArray+PureLayout.m in Sources */, + 488FDC230E98EA6720F64014FD063FB3 /* NSLayoutConstraint+PureLayout.m in Sources */, + 1DC710267366A3FD3BE4FA152EFD6EE9 /* PureLayout-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C882EDC0ED816FC0E17E7FC9270FE8AB /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + C55224B2297E86CBC8C2CCFEE4D5EA18 /* Chameleon_.m in Sources */, + C7A221A39BAF88495510D99C56DC6C04 /* ChameleonConstants.m in Sources */, + 718F9CBBB203EDEC7BD84E7686D9B297 /* ChameleonFramework-dummy.m in Sources */, + F12837AAC469A75054A691FB555227B8 /* NSArray+Chameleon.m in Sources */, + 9410C7E4CBDFF736F5C45DFF733BA0B3 /* UIAppearance+Swift.m in Sources */, + 944245D934F12AB6FA8057041BF7E646 /* UIButton+Chameleon.m in Sources */, + 4933A386D37EC2D1D2BE8B99724F0962 /* UIColor+Chameleon.m in Sources */, + 62735AD816C256656776BB47B36E4002 /* UIColor+ChameleonPrivate.m in Sources */, + E9D7FAEC94CBACA0A7FFDE5B44965725 /* UIImage+ChameleonPrivate.m in Sources */, + 8DDA1DD5D3323898521157C9E0AF8435 /* UILabel+Chameleon.m in Sources */, + 5B3EAA6F7334F52A500509EA891D0B34 /* UINavigationController+Chameleon.m in Sources */, + 980F19CAA48A2AB6A2E72B0BB752FD7E /* UIView+ChameleonPrivate.m in Sources */, + 24A15054FA9AD80E158C00F36CD10E9B /* UIViewController+Chameleon.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DB1BB097ACB2650A2CBE06D550120AD4 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 558EED8054BE6E4B77C24D3640A82867 /* MZTimerLabel-dummy.m in Sources */, + 602A282381899FCDDEEDC76845F4C415 /* MZTimerLabel.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DF16A50C5C93C2A7DFC323A6E2D20B73 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 523BE7D997AF9E44B95AF4A696B37815 /* CAGradientLayer+IPGradients.m in Sources */, + 0C10CFAB9497E8E5D011C8AFFE4008C4 /* IP-UIKit-Wisdom-dummy.m in Sources */, + 6B080B5ED674FE19F2889ED71D8F6813 /* UIButton+IPUtils.m in Sources */, + C2B43086EC0847B7958DE4F5FBA75A22 /* UIColor+IPRandomColor.m in Sources */, + 279E4BCBF03C84B851A63B48DBFE6884 /* UIImage+ColorMaskedImage.m in Sources */, + BF0DDF8775FDCD678AB1CA55847BEDD5 /* UITableView+Utils.m in Sources */, + C63C0F6AE7087D02F2DD1AF741B84EFC /* UIView+Constraints.m in Sources */, + 755CC0A38757AE7AEACBF589C5CD0D31 /* UIView+IPAncestry.m in Sources */, + 58130F131C4B889050714D0D5F8A5BED /* UIView+IPFrameUtils.m in Sources */, + 206F95434CF9EB75353E74C4BB9C571B /* UIView+NibInitable.m in Sources */, + D2A6CCF8726A7F31EF4332EA84241192 /* UIViewController+Containment.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E815F39BFA635CCA79320783CD788B4E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 9E52A2333D730EDA05C5E745540674E4 /* UICircularProgressRing-dummy.m in Sources */, + 9B98E2F6281B5CE2B56FAAF47782CD73 /* UICircularProgressRing.swift in Sources */, + 832C622C9F35C48C02DEC2220EF91FB6 /* UICircularProgressRingDelegate.swift in Sources */, + 9AD317C36A6DDF98D1CD5A247F9DE367 /* UICircularProgressRingGradientPosition.swift in Sources */, + A0D713856DDD52B95F7C4365F059CD1E /* UICircularProgressRingLayer.swift in Sources */, + 0278661ACDCCBB9A7D56C0FFB3E431FB /* UICircularProgressRingStyle.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + F570AF41DB7E6E80A8FC1513AB29A2FE /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 73D6C6CCC90335B32B86829F7A492B90 /* XMLDictionary-dummy.m in Sources */, + 8FB3D4F962538219133464CD34058547 /* XMLDictionary.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + F847381E93F53CC0C5F247ED955AB292 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ABF95CBA02E302E08009102775B703F2 /* Pods-WirelessGecko-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 1628ECFBA6FD7A6D7FC101BA42B8CEAF /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = UICircularProgressRing; + target = 99E8E0D6846CC782E53B7D73C11ACDEA /* UICircularProgressRing */; + targetProxy = BB826E264CF976047CBAA5FB746D47FC /* PBXContainerItemProxy */; + }; + 1F4FCF75D804486929083B9BBC9D4290 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = PureLayout; + target = 212B86B3B83BCB71159494262747DFCF /* PureLayout */; + targetProxy = 5D4A0B9EA3E7783BC2BB0787D5709E96 /* PBXContainerItemProxy */; + }; + 1F85290DF2A38C1089137E36EA72635D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "ActionSheetPicker-3.0"; + target = 05B9852E4B188EF4EC93B1E3F0712B2E /* ActionSheetPicker-3.0 */; + targetProxy = 7C837EC14B9CAB3814A0E3D71E872F61 /* PBXContainerItemProxy */; + }; + 2BD1440D1529E34BCCF44DBE97204D41 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = WYPopoverController; + target = AEF4BF40039DBEDE68615E1A32E2E805 /* WYPopoverController */; + targetProxy = 873988AD012BB421C984D9F002F81375 /* PBXContainerItemProxy */; + }; + 307AF4C6F7D7DBBA2F924C6BD749F785 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = KVOController; + target = 5B03F2322DD9BCD22A8A37FD2E19849B /* KVOController */; + targetProxy = 58F9B8BEFF51945699F440DB027C2C7A /* PBXContainerItemProxy */; + }; + 31608157B7C435C2D2F1576DCCD26722 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = ChameleonFramework; + target = 4273171B8F85B95806C7A7AEE258783F /* ChameleonFramework */; + targetProxy = E175C78B42F5B8EE323175F3E7AA7FB9 /* PBXContainerItemProxy */; + }; + 331327299D31120D1E39CB80BD7B771E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "IP-UIKit-Wisdom"; + target = E715D783410216803ED82EC21CD5C31B /* IP-UIKit-Wisdom */; + targetProxy = 82B785194AFF67069223E549294CEFCE /* PBXContainerItemProxy */; + }; + 362F2BD139D14654E7E9AA5CC8B80591 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = ChameleonFramework; + target = 4273171B8F85B95806C7A7AEE258783F /* ChameleonFramework */; + targetProxy = E16148F780C67003B95D64D23C828559 /* PBXContainerItemProxy */; + }; + 38374D4A6FB1D1AE51823E961C0DDFF3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = KVOController; + target = 5B03F2322DD9BCD22A8A37FD2E19849B /* KVOController */; + targetProxy = 590CB6C0B8C316790FFACDBCBB241F9B /* PBXContainerItemProxy */; + }; + 3A30B3FE4DA6006A3B6EBC47878BF776 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Charts; + target = EBFD1DA8DB9C5E9C282BBCAD1778A64A /* Charts */; + targetProxy = 4CBBAB53C5F10A9FB624045976C15702 /* PBXContainerItemProxy */; + }; + 44FE209DD968B7EA36C9EECD2D93CBA1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Eddystone; + target = 8D721B7ADC82CCCBC060EAA131A0A40A /* Eddystone */; + targetProxy = C1D53C1DF89B8FE890E0A6AF60E1B95F /* PBXContainerItemProxy */; + }; + 61D0F0C641B54F991664B592317CAACF /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = ChameleonFramework; + target = 4273171B8F85B95806C7A7AEE258783F /* ChameleonFramework */; + targetProxy = 59EA880CC6611A4B1EC3710D4F1FEEFF /* PBXContainerItemProxy */; + }; + 67AEB7D5B7319B30FD1AEE79DA8B65B7 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Charts; + target = EBFD1DA8DB9C5E9C282BBCAD1778A64A /* Charts */; + targetProxy = D4598A2A1ACA0BAACBB5F59BF4E8655B /* PBXContainerItemProxy */; + }; + 67C516BEB56BBC4563B7BD32E3F437B6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Eddystone; + target = 8D721B7ADC82CCCBC060EAA131A0A40A /* Eddystone */; + targetProxy = 8418229DD880FC1765DD23B913A04D49 /* PBXContainerItemProxy */; + }; + 6A2D86558FD87AF11179C6B49AC1A493 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = UICircularProgressRing; + target = 99E8E0D6846CC782E53B7D73C11ACDEA /* UICircularProgressRing */; + targetProxy = FE83736314FFFCA50CCD6E11E03BDCCA /* PBXContainerItemProxy */; + }; + 78D6A27DF7B9B4851AE32E3590AE989E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = MZTimerLabel; + target = 5DA9D424D96F4D772D20C95ED50F5163 /* MZTimerLabel */; + targetProxy = 52B7B5FBB8B8568C1FE07E1753E01833 /* PBXContainerItemProxy */; + }; + 7A1D1648158A02C64EE37FB55D86592F /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = MZTimerLabel; + target = 5DA9D424D96F4D772D20C95ED50F5163 /* MZTimerLabel */; + targetProxy = 44A6874453B72EF4CF0C7B9638E1D13B /* PBXContainerItemProxy */; + }; + 8A7A01F9359F89E8F15E255DCE327413 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = WYPopoverController; + target = AEF4BF40039DBEDE68615E1A32E2E805 /* WYPopoverController */; + targetProxy = CE34B180FE67D0E5442E72663BFA4D10 /* PBXContainerItemProxy */; + }; + 8C7676A6F8701E301660D42005E35BD2 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Charts; + target = EBFD1DA8DB9C5E9C282BBCAD1778A64A /* Charts */; + targetProxy = 05CDBDD70C914ACD03F036471172EF25 /* PBXContainerItemProxy */; + }; + 8E7F5A759BCED603D1C66B2AD570E6DC /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = PureLayout; + target = 212B86B3B83BCB71159494262747DFCF /* PureLayout */; + targetProxy = C715AB70E2286971F58FB7BE2B4E2838 /* PBXContainerItemProxy */; + }; + 8F1A4F01A849D2EF25FF8B4AF2C68DC3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = SVProgressHUD; + target = E384B3C7B2878E9354E03BBC33901EA0 /* SVProgressHUD */; + targetProxy = 64B296C2BB7428DBED433726048E65DD /* PBXContainerItemProxy */; + }; + 911A989C20DFA5EE0380A247C84C5F0C /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = XMLDictionary; + target = 50C8BE3E50EE30CE69A6C1715D047E60 /* XMLDictionary */; + targetProxy = 44AF829F114F5BD47234D263B4EAB240 /* PBXContainerItemProxy */; + }; + 9578B8F51ADBA198790D05654E3CF49F /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = WYPopoverController; + target = AEF4BF40039DBEDE68615E1A32E2E805 /* WYPopoverController */; + targetProxy = 522366C4E5099B8A66E08AADD0680DD6 /* PBXContainerItemProxy */; + }; + 97052024D1AAE01C7BD0847B51307DC3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = KVOController; + target = 5B03F2322DD9BCD22A8A37FD2E19849B /* KVOController */; + targetProxy = A5F2769EF1110B78E66270702F5D7563 /* PBXContainerItemProxy */; + }; + 97707B05C62F2BC63BDEFCDA4FDF1399 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "ActionSheetPicker-3.0"; + target = 05B9852E4B188EF4EC93B1E3F0712B2E /* ActionSheetPicker-3.0 */; + targetProxy = 99DF5180C3163A766D4895990205331C /* PBXContainerItemProxy */; + }; + 99D8E66C28EB81DCA85D946A033B6DDC /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = SVProgressHUD; + target = E384B3C7B2878E9354E03BBC33901EA0 /* SVProgressHUD */; + targetProxy = F77856B5F0E5626B2F2CD27C5F42FC8B /* PBXContainerItemProxy */; + }; + 9C5716FCB164C5A938225E6352B305C3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "IP-UIKit-Wisdom"; + target = E715D783410216803ED82EC21CD5C31B /* IP-UIKit-Wisdom */; + targetProxy = 67CE2FA5E1438668ED773C446A65FAB5 /* PBXContainerItemProxy */; + }; + AC06D1E19C67FDA3958137C5A06E634B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = MZTimerLabel; + target = 5DA9D424D96F4D772D20C95ED50F5163 /* MZTimerLabel */; + targetProxy = 25E062511F4390B4257132C49EE53E4F /* PBXContainerItemProxy */; + }; + B1756DE869CCE608C096CE6EA633E5DF /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = PureLayout; + target = 212B86B3B83BCB71159494262747DFCF /* PureLayout */; + targetProxy = AC7E0B9063E818CE46D2BCC7FA52FC37 /* PBXContainerItemProxy */; + }; + B799EB5B2B14CC48FA6789D6C959BC1D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = XMLDictionary; + target = 50C8BE3E50EE30CE69A6C1715D047E60 /* XMLDictionary */; + targetProxy = F543B5BE201BDDFA99A50D89F635C002 /* PBXContainerItemProxy */; + }; + D354861A72BF938A67B52E5A0F5DE8FA /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "IP-UIKit-Wisdom"; + target = E715D783410216803ED82EC21CD5C31B /* IP-UIKit-Wisdom */; + targetProxy = 407678FCDA2391826312C39C873E2AD7 /* PBXContainerItemProxy */; + }; + DF401E4DF9F70B692EECF66D208D8C6C /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "ActionSheetPicker-3.0"; + target = 05B9852E4B188EF4EC93B1E3F0712B2E /* ActionSheetPicker-3.0 */; + targetProxy = CB80A012B789FDB0E22747FA4821598C /* PBXContainerItemProxy */; + }; + E869A0C85DC5B4212580A52FF957B853 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Eddystone; + target = 8D721B7ADC82CCCBC060EAA131A0A40A /* Eddystone */; + targetProxy = AA39FC7EDDB0B3734F3D8E7E48B9D487 /* PBXContainerItemProxy */; + }; + E93735055BFDB5736612D54EEC66BD16 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = UICircularProgressRing; + target = 99E8E0D6846CC782E53B7D73C11ACDEA /* UICircularProgressRing */; + targetProxy = 040DD17F67F5C6B36829805EACF08718 /* PBXContainerItemProxy */; + }; + EC364459FC580F99E6BD3AE2182449D7 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = XMLDictionary; + target = 50C8BE3E50EE30CE69A6C1715D047E60 /* XMLDictionary */; + targetProxy = 3BBE37EBD44CEEB1E429393BED020020 /* PBXContainerItemProxy */; + }; + F6ED5090C578B9A67084101FDD9CBF57 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = SVProgressHUD; + target = E384B3C7B2878E9354E03BBC33901EA0 /* SVProgressHUD */; + targetProxy = B712C713D53B0D09D2CD708B43686731 /* PBXContainerItemProxy */; + }; + FBC7CF501F6A8AE65EDF14D119E4202D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "Eddystone-Eddystone"; + target = 5FA4F2F40241D9CBE948E0161E4C428D /* Eddystone-Eddystone */; + targetProxy = 569A85FBF454A6E63613619791CBA011 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 0C70BB03EAEA8BF7DE6193FB372C5794 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 4A1C73A26B8BA66527D199ABCE9F3C98 /* WYPopoverController.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/WYPopoverController/WYPopoverController-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/WYPopoverController/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/WYPopoverController/WYPopoverController.modulemap"; + PRODUCT_MODULE_NAME = WYPopoverController; + PRODUCT_NAME = WYPopoverController; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 185F784C8BB119684F5378E2BE51F945 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = CDE4AFBEEB6BFB9C2FF99FE78615BFC4 /* MZTimerLabel.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/MZTimerLabel/MZTimerLabel-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/MZTimerLabel/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/MZTimerLabel/MZTimerLabel.modulemap"; + PRODUCT_MODULE_NAME = MZTimerLabel; + PRODUCT_NAME = MZTimerLabel; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 2990165BA5823B63B79C32E8B9C08AA2 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = ADDA572D256D8ED1E567B40D462692AD /* SVProgressHUD.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/SVProgressHUD/SVProgressHUD-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/SVProgressHUD/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/SVProgressHUD/SVProgressHUD.modulemap"; + PRODUCT_MODULE_NAME = SVProgressHUD; + PRODUCT_NAME = SVProgressHUD; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 2B3CEB17471EAECA3D399871872C0A9D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 4D9D9C5B78F513003B8393913329AC75 /* Eddystone.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = "iPhone Developer"; + CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/Eddystone"; + INFOPLIST_FILE = "Target Support Files/Eddystone/ResourceBundle-Eddystone-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + PRODUCT_NAME = Eddystone; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + WRAPPER_EXTENSION = bundle; + }; + name = Release; + }; + 3129494759BAD435FB6E3418F611EEAE /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 24F153C0771D8D8EBE02DE904B282195 /* Pods-WirelessGecko.debug.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-WirelessGecko/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.3; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-WirelessGecko/Pods-WirelessGecko.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 36467AB259B85AD9C02D3707BBECFAF8 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 827E476839A9B3D5C5DE6CE53EF74952 /* ChameleonFramework.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/ChameleonFramework/ChameleonFramework-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/ChameleonFramework/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/ChameleonFramework/ChameleonFramework.modulemap"; + PRODUCT_MODULE_NAME = ChameleonFramework; + PRODUCT_NAME = ChameleonFramework; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 3950BE7C54F5D99667F84433115428DC /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 4D9D9C5B78F513003B8393913329AC75 /* Eddystone.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/Eddystone/Eddystone-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Eddystone/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/Eddystone/Eddystone.modulemap"; + PRODUCT_MODULE_NAME = Eddystone; + PRODUCT_NAME = Eddystone; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 4A08D008B4A3BCC7BEC411E3E1690C6B /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = C4682DB57203991EA7CE1B2690A8FDFF /* ActionSheetPicker-3.0.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/ActionSheetPicker-3.0/ActionSheetPicker-3.0-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/ActionSheetPicker-3.0/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/ActionSheetPicker-3.0/ActionSheetPicker-3.0.modulemap"; + PRODUCT_MODULE_NAME = ActionSheetPicker_3_0; + PRODUCT_NAME = ActionSheetPicker_3_0; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 4C6D627814503AA41B06A4A09636EF78 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 4D9D9C5B78F513003B8393913329AC75 /* Eddystone.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = "iPhone Developer"; + CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/Eddystone"; + INFOPLIST_FILE = "Target Support Files/Eddystone/ResourceBundle-Eddystone-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + PRODUCT_NAME = Eddystone; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + WRAPPER_EXTENSION = bundle; + }; + name = Debug; + }; + 4CB1E56A4E0B59EC4AA81B493CE14B4D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 6DF6D9D9AB6E5A2673FE8D86E15CBFD8 /* PureLayout.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/PureLayout/PureLayout-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/PureLayout/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/PureLayout/PureLayout.modulemap"; + PRODUCT_MODULE_NAME = PureLayout; + PRODUCT_NAME = PureLayout; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 50646285DD9FD95AF390BDA3FB1948EA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGNING_ALLOWED = NO; + CODE_SIGNING_REQUIRED = NO; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "POD_CONFIGURATION_DEBUG=1", + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.3; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRIP_INSTALLED_PRODUCT = NO; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 4.2; + SYMROOT = "${SRCROOT}/../build"; + }; + name = Debug; + }; + 587908DD5943607F77E3059A68963E61 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 8663053901ADA8C9A0577FEA61654E57 /* UICircularProgressRing.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/UICircularProgressRing/UICircularProgressRing-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/UICircularProgressRing/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/UICircularProgressRing/UICircularProgressRing.modulemap"; + PRODUCT_MODULE_NAME = UICircularProgressRing; + PRODUCT_NAME = UICircularProgressRing; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 58DCB2BA7C34E84C00C38CEF18A96D11 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGNING_ALLOWED = NO; + CODE_SIGNING_REQUIRED = NO; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "POD_CONFIGURATION_RELEASE=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.3; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRIP_INSTALLED_PRODUCT = NO; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_VERSION = 4.2; + SYMROOT = "${SRCROOT}/../build"; + }; + name = Release; + }; + 658BDA65E85E04C1424296C7675C24B2 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 8663053901ADA8C9A0577FEA61654E57 /* UICircularProgressRing.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/UICircularProgressRing/UICircularProgressRing-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/UICircularProgressRing/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/UICircularProgressRing/UICircularProgressRing.modulemap"; + PRODUCT_MODULE_NAME = UICircularProgressRing; + PRODUCT_NAME = UICircularProgressRing; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 69AD54CCD195C5C0C3A15ABA7307721A /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 691E229FAC3EF29B4F989FB5BAF1999D /* Pods-WirelessGecko.release.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-WirelessGecko/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.3; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-WirelessGecko/Pods-WirelessGecko.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 73A51BD479988E05CA5507EE222D9817 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = BC4D91A05AAE23D52A352167C10F2973 /* Charts.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/Charts/Charts-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Charts/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/Charts/Charts.modulemap"; + PRODUCT_MODULE_NAME = Charts; + PRODUCT_NAME = Charts; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 73BEB23AFA8AA0378FC1B6E070165A8D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 55EEDB11AB6F96E6F97DC96F2C476230 /* IP-UIKit-Wisdom.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/IP-UIKit-Wisdom/IP-UIKit-Wisdom-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/IP-UIKit-Wisdom/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/IP-UIKit-Wisdom/IP-UIKit-Wisdom.modulemap"; + PRODUCT_MODULE_NAME = IP_UIKit_Wisdom; + PRODUCT_NAME = IP_UIKit_Wisdom; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 782F661BEC50F5BD932B5184B8F358F2 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = C4682DB57203991EA7CE1B2690A8FDFF /* ActionSheetPicker-3.0.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/ActionSheetPicker-3.0/ActionSheetPicker-3.0-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/ActionSheetPicker-3.0/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/ActionSheetPicker-3.0/ActionSheetPicker-3.0.modulemap"; + PRODUCT_MODULE_NAME = ActionSheetPicker_3_0; + PRODUCT_NAME = ActionSheetPicker_3_0; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 7892925DE8B0AE246622A008E069EC56 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = B9C2D281D2F7CFBA3E82DFF491399A30 /* Pods-BlueGeckoWithHomeKit.release.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-BlueGeckoWithHomeKit/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.3; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-BlueGeckoWithHomeKit/Pods-BlueGeckoWithHomeKit.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 89245DBB69A283D174A83672D4D8CD5C /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E3BBE24439621C9151D831BB4B15804F /* XMLDictionary.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/XMLDictionary/XMLDictionary-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/XMLDictionary/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/XMLDictionary/XMLDictionary.modulemap"; + PRODUCT_MODULE_NAME = XMLDictionary; + PRODUCT_NAME = XMLDictionary; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 9B1CB8581818FB034E9AB6A37E071E1E /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 4A1C73A26B8BA66527D199ABCE9F3C98 /* WYPopoverController.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/WYPopoverController/WYPopoverController-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/WYPopoverController/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/WYPopoverController/WYPopoverController.modulemap"; + PRODUCT_MODULE_NAME = WYPopoverController; + PRODUCT_NAME = WYPopoverController; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + A3588FB0E64093B88BE4AD48E84221A0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = ADDA572D256D8ED1E567B40D462692AD /* SVProgressHUD.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/SVProgressHUD/SVProgressHUD-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/SVProgressHUD/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/SVProgressHUD/SVProgressHUD.modulemap"; + PRODUCT_MODULE_NAME = SVProgressHUD; + PRODUCT_NAME = SVProgressHUD; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + B18134DE4C8078289EC81DF0787007B2 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = F899C4ACCAED413DAD887FDB3114531F /* Pods-BlueGecko.debug.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-BlueGecko/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.3; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-BlueGecko/Pods-BlueGecko.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + B87A6FAFADDE041AE8F59702AC9B4C32 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9F7F0B2C801D84E4DBCC848D00DC4F5B /* Pods-BlueGeckoWithHomeKit.debug.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-BlueGeckoWithHomeKit/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.3; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-BlueGeckoWithHomeKit/Pods-BlueGeckoWithHomeKit.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + BD6F33649C601265ABB538E7B1B220EE /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 3F6A9685BFC90D3A596AD7B760053227 /* Pods-BlueGecko.release.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-BlueGecko/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.3; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-BlueGecko/Pods-BlueGecko.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + BE5A01AA0AC239B978FBD290E0BA0E77 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = CDE4AFBEEB6BFB9C2FF99FE78615BFC4 /* MZTimerLabel.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/MZTimerLabel/MZTimerLabel-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/MZTimerLabel/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/MZTimerLabel/MZTimerLabel.modulemap"; + PRODUCT_MODULE_NAME = MZTimerLabel; + PRODUCT_NAME = MZTimerLabel; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + BF08B833E12A14ECFBEAE080F0DDEBE8 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 55EEDB11AB6F96E6F97DC96F2C476230 /* IP-UIKit-Wisdom.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/IP-UIKit-Wisdom/IP-UIKit-Wisdom-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/IP-UIKit-Wisdom/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/IP-UIKit-Wisdom/IP-UIKit-Wisdom.modulemap"; + PRODUCT_MODULE_NAME = IP_UIKit_Wisdom; + PRODUCT_NAME = IP_UIKit_Wisdom; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + C3966F3C59C997EDBF250CD795820FE9 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E3BBE24439621C9151D831BB4B15804F /* XMLDictionary.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/XMLDictionary/XMLDictionary-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/XMLDictionary/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/XMLDictionary/XMLDictionary.modulemap"; + PRODUCT_MODULE_NAME = XMLDictionary; + PRODUCT_NAME = XMLDictionary; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + CEEEB69EE90B32367E9E301F7106554E /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1E3597E096BD1541EFC48B34E4899601 /* KVOController.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/KVOController/KVOController-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/KVOController/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/KVOController/KVOController.modulemap"; + PRODUCT_MODULE_NAME = KVOController; + PRODUCT_NAME = KVOController; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + D6175E561FA2BD59AA46EE9DBD597E0F /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1E3597E096BD1541EFC48B34E4899601 /* KVOController.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/KVOController/KVOController-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/KVOController/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/KVOController/KVOController.modulemap"; + PRODUCT_MODULE_NAME = KVOController; + PRODUCT_NAME = KVOController; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + E2BD4F12C086AEFEA14ED9BEC9A43788 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 4D9D9C5B78F513003B8393913329AC75 /* Eddystone.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/Eddystone/Eddystone-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Eddystone/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/Eddystone/Eddystone.modulemap"; + PRODUCT_MODULE_NAME = Eddystone; + PRODUCT_NAME = Eddystone; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + F50EC3996C051BFA118EE70566CF0AB6 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 827E476839A9B3D5C5DE6CE53EF74952 /* ChameleonFramework.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/ChameleonFramework/ChameleonFramework-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/ChameleonFramework/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/ChameleonFramework/ChameleonFramework.modulemap"; + PRODUCT_MODULE_NAME = ChameleonFramework; + PRODUCT_NAME = ChameleonFramework; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + F7A2EDF87E8F025B9811E032339A2C4A /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 6DF6D9D9AB6E5A2673FE8D86E15CBFD8 /* PureLayout.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/PureLayout/PureLayout-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/PureLayout/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/PureLayout/PureLayout.modulemap"; + PRODUCT_MODULE_NAME = PureLayout; + PRODUCT_NAME = PureLayout; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + FAD725694C68A3176BA3F3A123EBCDA9 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = BC4D91A05AAE23D52A352167C10F2973 /* Charts.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/Charts/Charts-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Charts/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/Charts/Charts.modulemap"; + PRODUCT_MODULE_NAME = Charts; + PRODUCT_NAME = Charts; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 232465D02EE4BB98B5673A80AB4C5B0C /* Build configuration list for PBXNativeTarget "Charts" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 73A51BD479988E05CA5507EE222D9817 /* Debug */, + FAD725694C68A3176BA3F3A123EBCDA9 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 291A39B31F01BB2B0ADF4D6B9F952D2A /* Build configuration list for PBXNativeTarget "PureLayout" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4CB1E56A4E0B59EC4AA81B493CE14B4D /* Debug */, + F7A2EDF87E8F025B9811E032339A2C4A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 2C9C780415F74DD9F39BE8872C5650DA /* Build configuration list for PBXNativeTarget "Pods-BlueGeckoWithHomeKit" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B87A6FAFADDE041AE8F59702AC9B4C32 /* Debug */, + 7892925DE8B0AE246622A008E069EC56 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 50646285DD9FD95AF390BDA3FB1948EA /* Debug */, + 58DCB2BA7C34E84C00C38CEF18A96D11 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 398F9CB00B060EB64F66747820AA5DDE /* Build configuration list for PBXNativeTarget "Pods-BlueGecko" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B18134DE4C8078289EC81DF0787007B2 /* Debug */, + BD6F33649C601265ABB538E7B1B220EE /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4944B2FE6AD982ED2987052521780E16 /* Build configuration list for PBXNativeTarget "Eddystone" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3950BE7C54F5D99667F84433115428DC /* Debug */, + E2BD4F12C086AEFEA14ED9BEC9A43788 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4A2EAC09B8DFF5A4B349CDB5A08984FA /* Build configuration list for PBXNativeTarget "SVProgressHUD" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 2990165BA5823B63B79C32E8B9C08AA2 /* Debug */, + A3588FB0E64093B88BE4AD48E84221A0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 5B15DDC21CB08F831A6D2CF2828836DF /* Build configuration list for PBXNativeTarget "Pods-WirelessGecko" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3129494759BAD435FB6E3418F611EEAE /* Debug */, + 69AD54CCD195C5C0C3A15ABA7307721A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 651E09ACC296CD9A4D79FDD91EBB82BC /* Build configuration list for PBXNativeTarget "WYPopoverController" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 9B1CB8581818FB034E9AB6A37E071E1E /* Debug */, + 0C70BB03EAEA8BF7DE6193FB372C5794 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + A36326D57965E7621B61FEC00B1B4775 /* Build configuration list for PBXNativeTarget "MZTimerLabel" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + BE5A01AA0AC239B978FBD290E0BA0E77 /* Debug */, + 185F784C8BB119684F5378E2BE51F945 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + AD71D43FB0431C3180B7C19CD57E279B /* Build configuration list for PBXNativeTarget "IP-UIKit-Wisdom" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 73BEB23AFA8AA0378FC1B6E070165A8D /* Debug */, + BF08B833E12A14ECFBEAE080F0DDEBE8 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + AF8912DE519E16140B8D79115FE8B9DB /* Build configuration list for PBXNativeTarget "XMLDictionary" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 89245DBB69A283D174A83672D4D8CD5C /* Debug */, + C3966F3C59C997EDBF250CD795820FE9 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + B2542112051BCD04F474D595AAF717EE /* Build configuration list for PBXNativeTarget "UICircularProgressRing" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 658BDA65E85E04C1424296C7675C24B2 /* Debug */, + 587908DD5943607F77E3059A68963E61 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + B4616CC585387D9A6335E1A1A4776AEA /* Build configuration list for PBXNativeTarget "ChameleonFramework" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + F50EC3996C051BFA118EE70566CF0AB6 /* Debug */, + 36467AB259B85AD9C02D3707BBECFAF8 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + B834EE00D33BF8584CE5177AF20C74F5 /* Build configuration list for PBXNativeTarget "ActionSheetPicker-3.0" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4A08D008B4A3BCC7BEC411E3E1690C6B /* Debug */, + 782F661BEC50F5BD932B5184B8F358F2 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C33F2C7CA199F19B1C71AC1910CB0DD2 /* Build configuration list for PBXNativeTarget "KVOController" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D6175E561FA2BD59AA46EE9DBD597E0F /* Debug */, + CEEEB69EE90B32367E9E301F7106554E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + EDA758D09698B63034770DE3E00C2AA8 /* Build configuration list for PBXNativeTarget "Eddystone-Eddystone" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4C6D627814503AA41B06A4A09636EF78 /* Debug */, + 2B3CEB17471EAECA3D399871872C0A9D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = D41D8CD98F00B204E9800998ECF8427E /* Project object */; +} diff --git a/Pods/Pods.xcodeproj/xcshareddata/xcschemes/ActionSheetPicker-3.0.xcscheme b/Pods/Pods.xcodeproj/xcshareddata/xcschemes/ActionSheetPicker-3.0.xcscheme new file mode 100644 index 00000000..ab55abc3 --- /dev/null +++ b/Pods/Pods.xcodeproj/xcshareddata/xcschemes/ActionSheetPicker-3.0.xcscheme @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Pods/Pods.xcodeproj/xcshareddata/xcschemes/ChameleonFramework.xcscheme b/Pods/Pods.xcodeproj/xcshareddata/xcschemes/ChameleonFramework.xcscheme new file mode 100644 index 00000000..39a2b373 --- /dev/null +++ b/Pods/Pods.xcodeproj/xcshareddata/xcschemes/ChameleonFramework.xcscheme @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Pods/Pods.xcodeproj/xcshareddata/xcschemes/Charts.xcscheme b/Pods/Pods.xcodeproj/xcshareddata/xcschemes/Charts.xcscheme new file mode 100644 index 00000000..128133ca --- /dev/null +++ b/Pods/Pods.xcodeproj/xcshareddata/xcschemes/Charts.xcscheme @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Pods/Pods.xcodeproj/xcshareddata/xcschemes/Eddystone-Eddystone.xcscheme b/Pods/Pods.xcodeproj/xcshareddata/xcschemes/Eddystone-Eddystone.xcscheme new file mode 100644 index 00000000..976f2fcd --- /dev/null +++ b/Pods/Pods.xcodeproj/xcshareddata/xcschemes/Eddystone-Eddystone.xcscheme @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Pods/Pods.xcodeproj/xcshareddata/xcschemes/Eddystone.xcscheme b/Pods/Pods.xcodeproj/xcshareddata/xcschemes/Eddystone.xcscheme new file mode 100644 index 00000000..0dba7e8a --- /dev/null +++ b/Pods/Pods.xcodeproj/xcshareddata/xcschemes/Eddystone.xcscheme @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Pods/Pods.xcodeproj/xcshareddata/xcschemes/IP-UIKit-Wisdom.xcscheme b/Pods/Pods.xcodeproj/xcshareddata/xcschemes/IP-UIKit-Wisdom.xcscheme new file mode 100644 index 00000000..8ccc61e5 --- /dev/null +++ b/Pods/Pods.xcodeproj/xcshareddata/xcschemes/IP-UIKit-Wisdom.xcscheme @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Pods/Pods.xcodeproj/xcshareddata/xcschemes/KVOController.xcscheme b/Pods/Pods.xcodeproj/xcshareddata/xcschemes/KVOController.xcscheme new file mode 100644 index 00000000..48237d2d --- /dev/null +++ b/Pods/Pods.xcodeproj/xcshareddata/xcschemes/KVOController.xcscheme @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Pods/Pods.xcodeproj/xcshareddata/xcschemes/MZTimerLabel.xcscheme b/Pods/Pods.xcodeproj/xcshareddata/xcschemes/MZTimerLabel.xcscheme new file mode 100644 index 00000000..c1152660 --- /dev/null +++ b/Pods/Pods.xcodeproj/xcshareddata/xcschemes/MZTimerLabel.xcscheme @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Pods/Pods.xcodeproj/xcshareddata/xcschemes/Pods-BlueGecko.xcscheme b/Pods/Pods.xcodeproj/xcshareddata/xcschemes/Pods-BlueGecko.xcscheme new file mode 100644 index 00000000..d1f3911a --- /dev/null +++ b/Pods/Pods.xcodeproj/xcshareddata/xcschemes/Pods-BlueGecko.xcscheme @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Pods/Pods.xcodeproj/xcshareddata/xcschemes/Pods-BlueGeckoWithHomeKit.xcscheme b/Pods/Pods.xcodeproj/xcshareddata/xcschemes/Pods-BlueGeckoWithHomeKit.xcscheme new file mode 100644 index 00000000..1f4da211 --- /dev/null +++ b/Pods/Pods.xcodeproj/xcshareddata/xcschemes/Pods-BlueGeckoWithHomeKit.xcscheme @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Pods/Pods.xcodeproj/xcshareddata/xcschemes/Pods-WirelessGecko.xcscheme b/Pods/Pods.xcodeproj/xcshareddata/xcschemes/Pods-WirelessGecko.xcscheme new file mode 100644 index 00000000..9535c629 --- /dev/null +++ b/Pods/Pods.xcodeproj/xcshareddata/xcschemes/Pods-WirelessGecko.xcscheme @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Pods/Pods.xcodeproj/xcshareddata/xcschemes/PureLayout.xcscheme b/Pods/Pods.xcodeproj/xcshareddata/xcschemes/PureLayout.xcscheme new file mode 100644 index 00000000..3ab0b62e --- /dev/null +++ b/Pods/Pods.xcodeproj/xcshareddata/xcschemes/PureLayout.xcscheme @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Pods/Pods.xcodeproj/xcshareddata/xcschemes/SVProgressHUD.xcscheme b/Pods/Pods.xcodeproj/xcshareddata/xcschemes/SVProgressHUD.xcscheme new file mode 100644 index 00000000..8fc1816a --- /dev/null +++ b/Pods/Pods.xcodeproj/xcshareddata/xcschemes/SVProgressHUD.xcscheme @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Pods/Pods.xcodeproj/xcshareddata/xcschemes/UICircularProgressRing.xcscheme b/Pods/Pods.xcodeproj/xcshareddata/xcschemes/UICircularProgressRing.xcscheme new file mode 100644 index 00000000..976e8286 --- /dev/null +++ b/Pods/Pods.xcodeproj/xcshareddata/xcschemes/UICircularProgressRing.xcscheme @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Pods/Pods.xcodeproj/xcshareddata/xcschemes/WYPopoverController.xcscheme b/Pods/Pods.xcodeproj/xcshareddata/xcschemes/WYPopoverController.xcscheme new file mode 100644 index 00000000..93f47793 --- /dev/null +++ b/Pods/Pods.xcodeproj/xcshareddata/xcschemes/WYPopoverController.xcscheme @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Pods/Pods.xcodeproj/xcshareddata/xcschemes/XMLDictionary.xcscheme b/Pods/Pods.xcodeproj/xcshareddata/xcschemes/XMLDictionary.xcscheme new file mode 100644 index 00000000..41b62ae6 --- /dev/null +++ b/Pods/Pods.xcodeproj/xcshareddata/xcschemes/XMLDictionary.xcscheme @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Pods/PureLayout/LICENSE b/Pods/PureLayout/LICENSE new file mode 100755 index 00000000..5396bc0a --- /dev/null +++ b/Pods/PureLayout/LICENSE @@ -0,0 +1,9 @@ +This code is distributed under the terms and conditions of the MIT license. + +Copyright (c) 2014-2015 Tyler Fox + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/Pods/PureLayout/PureLayout/PureLayout/ALView+PureLayout.h b/Pods/PureLayout/PureLayout/PureLayout/ALView+PureLayout.h new file mode 100755 index 00000000..42ed6445 --- /dev/null +++ b/Pods/PureLayout/PureLayout/PureLayout/ALView+PureLayout.h @@ -0,0 +1,242 @@ +// +// ALView+PureLayout.h +// https://github.com/PureLayout/PureLayout +// +// Copyright (c) 2012 Richard Turton +// Copyright (c) 2013-2015 Tyler Fox +// +// This code is distributed under the terms and conditions of the MIT license. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +// + +#import "PureLayoutDefines.h" + + +PL__ASSUME_NONNULL_BEGIN + +#pragma mark ALView+PureLayout + +/** + A category on UIView/NSView that provides a simple yet powerful interface for creating Auto Layout constraints. + */ +@interface ALView (PureLayout) + + +#pragma mark Factory & Initializer Methods + +/** Creates and returns a new view that does not convert the autoresizing mask into constraints. */ ++ (instancetype)newAutoLayoutView; + +/** Initializes and returns a new view that does not convert the autoresizing mask into constraints. */ +- (instancetype)initForAutoLayout; + +/** Configures an existing view to not convert the autoresizing mask into constraints and returns the view. */ +- (instancetype)configureForAutoLayout; + + +#pragma mark Center & Align in Superview + +/** Centers the view in its superview. */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoCenterInSuperview; + +/** Aligns the view to the same axis of its superview. */ +- (NSLayoutConstraint *)autoAlignAxisToSuperviewAxis:(ALAxis)axis; + +#if PL__PureLayout_MinBaseSDK_iOS_8_0 + +/** Centers the view in its superview's margins. Available in iOS 8.0 and later. */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoCenterInSuperviewMargins; + +/** Aligns the view to the corresponding margin axis of its superview. Available in iOS 8.0 and later. */ +- (NSLayoutConstraint *)autoAlignAxisToSuperviewMarginAxis:(ALAxis)axis; + +#endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 */ + +#if TARGET_OS_IPHONE + +#pragma mark Pin Edges to SafeArea + +/** Pins the given edge of the view to the same edge of its superview anchor/edge. */ +- (NSLayoutConstraint *)API_AVAILABLE(ios(9.0), tvos(9.0))autoPinEdgeToSuperviewSafeArea:(ALEdge)edge; + +/** Pins the given edge of the view to the same edge of its superview anchor/edge with an inset. */ +- (NSLayoutConstraint *)API_AVAILABLE(ios(9.0), tvos(9.0))autoPinEdgeToSuperviewSafeArea:(ALEdge)edge withInset:(CGFloat)inset; + +/** Pins the given edge of the view to the same edge of its superview anchor/edge with an inset as a maximum or minimum. */ +- (NSLayoutConstraint *)API_AVAILABLE(ios(9.0), tvos(9.0))autoPinEdgeToSuperviewSafeArea:(ALEdge)edge withInset:(CGFloat)inset relation:(NSLayoutRelation)relation; + +/** Pins the edges of the view to the edges of its superview anchors/edge. */ +- (PL__NSArray_of(NSLayoutConstraint *) *)API_AVAILABLE(ios(9.0), tvos(9.0))autoPinEdgesToSuperviewSafeArea; + +/** Pins the edges of the view to the edges of its superview anchors/edges with the given edge insets. */ +- (PL__NSArray_of(NSLayoutConstraint *) *)API_AVAILABLE(ios(9.0), tvos(9.0))autoPinEdgesToSuperviewSafeAreaWithInsets:(ALEdgeInsets)insets; + +/** Pins 3 of the 4 edges of the view to the edges of its superview anchor/edge with the given edge insets, excluding one edge. */ +- (PL__NSArray_of(NSLayoutConstraint *) *)API_AVAILABLE(ios(9.0), tvos(9.0))autoPinEdgesToSuperviewSafeAreaWithInsets:(ALEdgeInsets)insets excludingEdge:(ALEdge)edge; + +#endif /* TARGET_OS_IPHONE */ + +#pragma mark Pin Edges to Superview + +/** Pins the given edge of the view to the same edge of its superview. */ +- (NSLayoutConstraint *)autoPinEdgeToSuperviewEdge:(ALEdge)edge; + +/** Pins the given edge of the view to the same edge of its superview with an inset. */ +- (NSLayoutConstraint *)autoPinEdgeToSuperviewEdge:(ALEdge)edge withInset:(CGFloat)inset; + +/** Pins the given edge of the view to the same edge of its superview with an inset as a maximum or minimum. */ +- (NSLayoutConstraint *)autoPinEdgeToSuperviewEdge:(ALEdge)edge withInset:(CGFloat)inset relation:(NSLayoutRelation)relation; + +/** Pins the edges of the view to the edges of its superview. */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoPinEdgesToSuperviewEdges; + +/** Pins the edges of the view to the edges of its superview with the given edge insets. */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoPinEdgesToSuperviewEdgesWithInsets:(ALEdgeInsets)insets; + +/** Pins 3 of the 4 edges of the view to the edges of its superview with the given edge insets, excluding one edge. */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoPinEdgesToSuperviewEdgesWithInsets:(ALEdgeInsets)insets excludingEdge:(ALEdge)edge; + +#if PL__PureLayout_MinBaseSDK_iOS_8_0 + +/** Pins the given edge of the view to the corresponding margin of its superview. Available in iOS 8.0 and later. */ +- (NSLayoutConstraint *)autoPinEdgeToSuperviewMargin:(ALEdge)edge; + +/** Pins the given edge of a view to the corresponding margin of its superview with an inset.*/ +- (NSLayoutConstraint *)autoPinEdgeToSuperviewMargin:(ALEdge)edge withInset:(CGFloat)inset; + +/** Pins the given edge of the view to the corresponding margin of its superview as a maximum or minimum. Available in iOS 8.0 and later. */ +- (NSLayoutConstraint *)autoPinEdgeToSuperviewMargin:(ALEdge)edge relation:(NSLayoutRelation)relation; + +/** Pins the edges of the view to the margins of its superview. Available in iOS 8.0 and later. */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoPinEdgesToSuperviewMargins; + +/** Pins the edges of the view to the margins of its superview with the given edge insets. Available in iOS 8.0 and later.*/ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoPinEdgesToSuperviewMarginsWithInsets:(ALEdgeInsets)insets; + +/** Pins 3 of the 4 edges of the view to the margins of its superview excluding one edge. Available in iOS 8.0 and later. */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoPinEdgesToSuperviewMarginsExcludingEdge:(ALEdge)edge; + +#endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 */ + + +#pragma mark Pin Edges + +/** Pins an edge of the view to a given edge of another view. */ +- (NSLayoutConstraint *)autoPinEdge:(ALEdge)edge toEdge:(ALEdge)toEdge ofView:(ALView *)otherView; + +/** Pins an edge of the view to a given edge of another view with an offset. */ +- (NSLayoutConstraint *)autoPinEdge:(ALEdge)edge toEdge:(ALEdge)toEdge ofView:(ALView *)otherView withOffset:(CGFloat)offset; + +/** Pins an edge of the view to a given edge of another view with an offset as a maximum or minimum. */ +- (NSLayoutConstraint *)autoPinEdge:(ALEdge)edge toEdge:(ALEdge)toEdge ofView:(ALView *)otherView withOffset:(CGFloat)offset relation:(NSLayoutRelation)relation; + + +#pragma mark Align Axes + +/** Aligns an axis of the view to the same axis of another view. */ +- (NSLayoutConstraint *)autoAlignAxis:(ALAxis)axis toSameAxisOfView:(ALView *)otherView; + +/** Aligns an axis of the view to the same axis of another view with an offset. */ +- (NSLayoutConstraint *)autoAlignAxis:(ALAxis)axis toSameAxisOfView:(ALView *)otherView withOffset:(CGFloat)offset; + +/** Aligns an axis of the view to the same axis of another view with a multiplier. */ +- (NSLayoutConstraint *)autoAlignAxis:(ALAxis)axis toSameAxisOfView:(ALView *)otherView withMultiplier:(CGFloat)multiplier; + + +#pragma mark Match Dimensions + +/** Matches a dimension of the view to a given dimension of another view. */ +- (NSLayoutConstraint *)autoMatchDimension:(ALDimension)dimension toDimension:(ALDimension)toDimension ofView:(ALView *)otherView; + +/** Matches a dimension of the view to a given dimension of another view with an offset. */ +- (NSLayoutConstraint *)autoMatchDimension:(ALDimension)dimension toDimension:(ALDimension)toDimension ofView:(ALView *)otherView withOffset:(CGFloat)offset; + +/** Matches a dimension of the view to a given dimension of another view with an offset as a maximum or minimum. */ +- (NSLayoutConstraint *)autoMatchDimension:(ALDimension)dimension toDimension:(ALDimension)toDimension ofView:(ALView *)otherView withOffset:(CGFloat)offset relation:(NSLayoutRelation)relation; + +/** Matches a dimension of the view to a multiple of a given dimension of another view. */ +- (NSLayoutConstraint *)autoMatchDimension:(ALDimension)dimension toDimension:(ALDimension)toDimension ofView:(ALView *)otherView withMultiplier:(CGFloat)multiplier; + +/** Matches a dimension of the view to a multiple of a given dimension of another view as a maximum or minimum. */ +- (NSLayoutConstraint *)autoMatchDimension:(ALDimension)dimension toDimension:(ALDimension)toDimension ofView:(ALView *)otherView withMultiplier:(CGFloat)multiplier relation:(NSLayoutRelation)relation; + + +#pragma mark Set Dimensions + +/** Sets the view to a specific size. */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoSetDimensionsToSize:(CGSize)size; + +/** Sets the given dimension of the view to a specific size. */ +- (NSLayoutConstraint *)autoSetDimension:(ALDimension)dimension toSize:(CGFloat)size; + +/** Sets the given dimension of the view to a specific size as a maximum or minimum. */ +- (NSLayoutConstraint *)autoSetDimension:(ALDimension)dimension toSize:(CGFloat)size relation:(NSLayoutRelation)relation; + + +#pragma mark Set Content Compression Resistance & Hugging + +/** Sets the priority of content compression resistance for an axis. + NOTE: This method must be called from within the block passed into the method +[NSLayoutConstraint autoSetPriority:forConstraints:] */ +- (void)autoSetContentCompressionResistancePriorityForAxis:(ALAxis)axis; + +/** Sets the priority of content hugging for an axis. + NOTE: This method must be called from within the block passed into the method +[NSLayoutConstraint autoSetPriority:forConstraints:] */ +- (void)autoSetContentHuggingPriorityForAxis:(ALAxis)axis; + + +#pragma mark Constrain Any Attributes + +/** Constrains an attribute of the view to a given attribute of another view. */ +- (NSLayoutConstraint *)autoConstrainAttribute:(ALAttribute)attribute toAttribute:(ALAttribute)toAttribute ofView:(ALView *)otherView; + +/** Constrains an attribute of the view to a given attribute of another view with an offset. */ +- (NSLayoutConstraint *)autoConstrainAttribute:(ALAttribute)attribute toAttribute:(ALAttribute)toAttribute ofView:(ALView *)otherView withOffset:(CGFloat)offset; + +/** Constrains an attribute of the view to a given attribute of another view with an offset as a maximum or minimum. */ +- (NSLayoutConstraint *)autoConstrainAttribute:(ALAttribute)attribute toAttribute:(ALAttribute)toAttribute ofView:(ALView *)otherView withOffset:(CGFloat)offset relation:(NSLayoutRelation)relation; + +/** Constrains an attribute of the view to a given attribute of another view with a multiplier. */ +- (NSLayoutConstraint *)autoConstrainAttribute:(ALAttribute)attribute toAttribute:(ALAttribute)toAttribute ofView:(ALView *)otherView withMultiplier:(CGFloat)multiplier; + +/** Constrains an attribute of the view to a given attribute of another view with a multiplier as a maximum or minimum. */ +- (NSLayoutConstraint *)autoConstrainAttribute:(ALAttribute)attribute toAttribute:(ALAttribute)toAttribute ofView:(ALView *)otherView withMultiplier:(CGFloat)multiplier relation:(NSLayoutRelation)relation; + + +#pragma mark Pin to Layout Guides (iOS only) + +#if TARGET_OS_IPHONE + +/** Pins the top edge of the view to the top layout guide of the given view controller with an inset. Available on iOS only. */ +- (NSLayoutConstraint *)autoPinToTopLayoutGuideOfViewController:(UIViewController *)viewController withInset:(CGFloat)inset; + +/** Pins the top edge of the view to the top layout guide of the given view controller with an inset as a maximum or minimum. Available on iOS only. */ +- (NSLayoutConstraint *)autoPinToTopLayoutGuideOfViewController:(UIViewController *)viewController withInset:(CGFloat)inset relation:(NSLayoutRelation)relation; + +/** Pins the bottom edge of the view to the bottom layout guide of the given view controller with an inset. Available on iOS only. */ +- (NSLayoutConstraint *)autoPinToBottomLayoutGuideOfViewController:(UIViewController *)viewController withInset:(CGFloat)inset; + +/** Pins the bottom edge of the view to the bottom layout guide of the given view controller with an inset as a maximum or minimum. Available on iOS only. */ +- (NSLayoutConstraint *)autoPinToBottomLayoutGuideOfViewController:(UIViewController *)viewController withInset:(CGFloat)inset relation:(NSLayoutRelation)relation; + +#endif /* TARGET_OS_IPHONE */ + +@end + +PL__ASSUME_NONNULL_END diff --git a/Pods/PureLayout/PureLayout/PureLayout/ALView+PureLayout.m b/Pods/PureLayout/PureLayout/PureLayout/ALView+PureLayout.m new file mode 100755 index 00000000..8e05f4c7 --- /dev/null +++ b/Pods/PureLayout/PureLayout/PureLayout/ALView+PureLayout.m @@ -0,0 +1,1146 @@ +// +// ALView+PureLayout.m +// https://github.com/PureLayout/PureLayout +// +// Copyright (c) 2012 Richard Turton +// Copyright (c) 2013-2015 Tyler Fox +// +// This code is distributed under the terms and conditions of the MIT license. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +// + +#import "ALView+PureLayout.h" +#import "NSLayoutConstraint+PureLayout.h" +#import "NSArray+PureLayout.h" +#import "PureLayout+Internal.h" + + +#pragma mark - ALView+PureLayout + +@implementation ALView (PureLayout) + + +#pragma mark Factory & Initializer Methods + +/** + Creates and returns a new view that does not convert the autoresizing mask into constraints. + */ ++ (instancetype)newAutoLayoutView +{ + ALView *view = [self new]; + view.translatesAutoresizingMaskIntoConstraints = NO; + return view; +} + +/** + Initializes and returns a new view that does not convert the autoresizing mask into constraints. + */ +- (instancetype)initForAutoLayout +{ + self = [self init]; + if (self) { + self.translatesAutoresizingMaskIntoConstraints = NO; + } + return self; +} + +/** + Configures an existing view to not convert the autoresizing mask into constraints and returns the view. + */ +- (instancetype)configureForAutoLayout +{ + self.translatesAutoresizingMaskIntoConstraints = NO; + return self; +} + + +#pragma mark Center in Superview + +/** + Centers the view in its superview. + + @return An array of constraints added. + */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoCenterInSuperview +{ + PL__NSMutableArray_of(NSLayoutConstraint *) *constraints = [NSMutableArray new]; + [constraints addObject:[self autoAlignAxisToSuperviewAxis:ALAxisHorizontal]]; + [constraints addObject:[self autoAlignAxisToSuperviewAxis:ALAxisVertical]]; + return constraints; +} + +/** + Aligns the view to the same axis of its superview. + + @param axis The axis of this view and of its superview to align. + @return The constraint added. + */ +- (NSLayoutConstraint *)autoAlignAxisToSuperviewAxis:(ALAxis)axis +{ + self.translatesAutoresizingMaskIntoConstraints = NO; + ALView *superview = self.superview; + NSAssert(superview, @"View's superview must not be nil.\nView: %@", self); + return [self autoConstrainAttribute:(ALAttribute)axis toAttribute:(ALAttribute)axis ofView:superview]; +} + +#if PL__PureLayout_MinBaseSDK_iOS_8_0 + +/** + Centers the view in its superview, taking into account the layout margins of both the view and its superview. + + @return An array of constraints added. + */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoCenterInSuperviewMargins +{ + PL__NSMutableArray_of(NSLayoutConstraint *) *constraints = [NSMutableArray new]; + [constraints addObject:[self autoAlignAxisToSuperviewMarginAxis:ALAxisHorizontal]]; + [constraints addObject:[self autoAlignAxisToSuperviewMarginAxis:ALAxisVertical]]; + return constraints; +} + +/** + Aligns the view to the corresponding margin axis of its superview. + + @param axis The axis of this view to align to the corresponding margin axis of its superview. + @return The constraint added. + */ +- (NSLayoutConstraint *)autoAlignAxisToSuperviewMarginAxis:(ALAxis)axis +{ + self.translatesAutoresizingMaskIntoConstraints = NO; + ALView *superview = self.superview; + NSAssert(superview, @"View's superview must not be nil.\nView: %@", self); + ALMarginAxis marginAxis = [NSLayoutConstraint al_marginAxisForAxis:axis]; + return [self autoConstrainAttribute:(ALAttribute)axis toAttribute:(ALAttribute)marginAxis ofView:superview]; +} + +#endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 */ + + +#pragma mark Pin Edges to SafeArea + +#if TARGET_OS_IPHONE + +/** + Pins the given edge of the view to the same edge of its superview anchor. + + @param edge The edge of this view and its superview to pin. + @return The constraint added. + */ +- (NSLayoutConstraint *)autoPinEdgeToSuperviewSafeArea:(ALEdge)edge +{ + return [self autoPinEdgeToSuperviewSafeArea:edge withInset:0.0]; +} + +/** + Pins the given edge of the view to the same edge of its superview anchor with an inset. + + @param edge The edge of this view and its superview to pin. + @param inset The amount to inset this view's edge from the superview's edge. + @return The constraint added. + */ +- (NSLayoutConstraint *)autoPinEdgeToSuperviewSafeArea:(ALEdge)edge withInset:(CGFloat)inset +{ + return [self autoPinEdgeToSuperviewSafeArea:edge withInset:inset relation:NSLayoutRelationEqual]; +} + +/** + Pins the given edge of the view to the same edge of its superview anchor/edge with an inset as a maximum or minimum. + + @param edge The edge of this view and its superview to pin. + @param inset The amount to inset this view's edge from the superview's edge. + @param relation Whether the inset should be at least, at most, or exactly equal to the given value. + @return The constraint added. + */ +- (NSLayoutConstraint *)autoPinEdgeToSuperviewSafeArea:(ALEdge)edge withInset:(CGFloat)inset relation:(NSLayoutRelation)relation +{ +#if PL__PureLayout_MinBaseSDK_iOS_9_0 + self.translatesAutoresizingMaskIntoConstraints = NO; + + ALView *superview = self.superview; + NSAssert(superview, @"View's superview must not be nil.\nView: %@", self); + NSLayoutConstraint *constraint = nil; + NSLayoutYAxisAnchor *topAnchor; + NSLayoutYAxisAnchor *bottomAnchor; + NSLayoutXAxisAnchor *leftAnchor; + NSLayoutXAxisAnchor *rightAnchor; + NSLayoutXAxisAnchor *leadingAnchor; + NSLayoutXAxisAnchor *trailingAnchor; + +#if PL__PureLayout_MinBaseSDK_iOS_11_0 // only iOS/tvOS SDK 11.0 has @available syntax introduced + if (@available(iOS 11.0, tvOS 11.0, *)) { + topAnchor = superview.safeAreaLayoutGuide.topAnchor; + bottomAnchor = superview.safeAreaLayoutGuide.bottomAnchor; + leftAnchor = superview.safeAreaLayoutGuide.leftAnchor; + rightAnchor = superview.safeAreaLayoutGuide.rightAnchor; + leadingAnchor = superview.safeAreaLayoutGuide.leadingAnchor; + trailingAnchor = superview.safeAreaLayoutGuide.trailingAnchor; + } else if (@available(iOS 9.0, *)) { + topAnchor = superview.topAnchor; + bottomAnchor = superview.bottomAnchor; + leftAnchor = superview.leftAnchor; + rightAnchor = superview.rightAnchor; + leadingAnchor = superview.leadingAnchor; + trailingAnchor = superview.trailingAnchor; + } else { // for targeting iOS 8 or below without anchor system + return [self autoPinEdgeToSuperviewEdge:edge withInset:inset relation:relation]; + } +#elif PL__PureLayout_MinBaseSDK_iOS_9_0 // fallback to older SDKs, when using Xcode 8.0, which only has iOS SDK 10.0 + if (PL__PureLayout_MinSysVer_iOS_9_0) { + topAnchor = superview.topAnchor; + bottomAnchor = superview.bottomAnchor; + leftAnchor = superview.leftAnchor; + rightAnchor = superview.rightAnchor; + leadingAnchor = superview.leadingAnchor; + trailingAnchor = superview.trailingAnchor; + } else { // for targeting iOS 8 or below without anchor system + return [self autoPinEdgeToSuperviewEdge:edge withInset:inset relation:relation]; + } +#endif + if (edge == ALEdgeBottom || edge == ALEdgeRight || edge == ALEdgeTrailing) { + // The bottom, right, and trailing insets (and relations, if an inequality) are inverted to become offsets + inset = -inset; + } + switch (edge) { + case ALEdgeLeft: + switch (relation) { + case NSLayoutRelationEqual: + constraint = [[self leftAnchor] constraintEqualToAnchor:leftAnchor constant:inset]; + break; + case NSLayoutRelationLessThanOrEqual: + constraint = [[self leftAnchor] constraintLessThanOrEqualToAnchor:leftAnchor constant:inset]; + break; + case NSLayoutRelationGreaterThanOrEqual: + constraint = [[self leftAnchor] constraintGreaterThanOrEqualToAnchor:leftAnchor constant:inset]; + break; + } + break; + case ALEdgeRight: + switch (relation) { + case NSLayoutRelationEqual: + constraint = [[self rightAnchor] constraintEqualToAnchor:rightAnchor constant:inset]; + break; + case NSLayoutRelationLessThanOrEqual: + constraint = [[self rightAnchor] constraintGreaterThanOrEqualToAnchor:rightAnchor constant:inset]; + break; + case NSLayoutRelationGreaterThanOrEqual: + constraint = [[self rightAnchor] constraintLessThanOrEqualToAnchor:rightAnchor constant:inset]; + break; + } + break; + case ALEdgeTop: + switch (relation) { + case NSLayoutRelationEqual: + constraint = [[self topAnchor] constraintEqualToAnchor:topAnchor constant:inset]; + break; + case NSLayoutRelationLessThanOrEqual: + constraint = [[self topAnchor] constraintLessThanOrEqualToAnchor:topAnchor constant:inset]; + break; + case NSLayoutRelationGreaterThanOrEqual: + constraint = [[self topAnchor] constraintGreaterThanOrEqualToAnchor:topAnchor constant:inset]; + break; + } + break; + case ALEdgeBottom: + switch (relation) { + case NSLayoutRelationEqual: + constraint = [[self bottomAnchor] constraintEqualToAnchor:bottomAnchor constant:inset]; + break; + case NSLayoutRelationLessThanOrEqual: + constraint = [[self bottomAnchor] constraintGreaterThanOrEqualToAnchor:bottomAnchor constant:inset]; + break; + case NSLayoutRelationGreaterThanOrEqual: + constraint = [[self bottomAnchor] constraintLessThanOrEqualToAnchor:bottomAnchor constant:inset]; + break; + } + break; + case ALEdgeLeading: + switch (relation) { + case NSLayoutRelationEqual: + constraint = [[self leadingAnchor] constraintEqualToAnchor:leadingAnchor constant:inset]; + break; + case NSLayoutRelationLessThanOrEqual: + constraint = [[self leadingAnchor] constraintLessThanOrEqualToAnchor:leadingAnchor constant:inset]; + break; + case NSLayoutRelationGreaterThanOrEqual: + constraint = [[self leadingAnchor] constraintGreaterThanOrEqualToAnchor:leadingAnchor constant:inset]; + break; + } + break; + case ALEdgeTrailing: + switch (relation) { + case NSLayoutRelationEqual: + constraint = [[self trailingAnchor] constraintEqualToAnchor:trailingAnchor constant:inset]; + break; + case NSLayoutRelationLessThanOrEqual: + constraint = [[self trailingAnchor] constraintGreaterThanOrEqualToAnchor:trailingAnchor constant:inset]; + break; + case NSLayoutRelationGreaterThanOrEqual: + constraint = [[self trailingAnchor] constraintLessThanOrEqualToAnchor:trailingAnchor constant:inset]; + break; + } + break; + } + constraint.active = YES; + return constraint; +#else + return [self autoPinEdgeToSuperviewEdge:edge withInset:inset relation:relation]; +#endif /* PL__PureLayout_MinBaseSDK_iOS_9_0 */ +} + +/** + Pins the edges of the view to the edges of its superview anchor. + + @return An array of constraints added, ordered counterclockwise from top. + */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoPinEdgesToSuperviewSafeArea +{ + return [self autoPinEdgesToSuperviewSafeAreaWithInsets:ALEdgeInsetsZero]; +} + +/** + Pins the edges of the view to the edges of its superview anchor with the given edge insets. + The insets.left corresponds to a leading edge constraint, and insets.right corresponds to a trailing edge constraint. + + @param insets The insets for this view's edges from its superview's edges. + @return An array of constraints added, ordered counterclockwise from top. + */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoPinEdgesToSuperviewSafeAreaWithInsets:(ALEdgeInsets)insets +{ + PL__NSMutableArray_of(NSLayoutConstraint *) *constraints = [NSMutableArray new]; + [constraints addObject:[self autoPinEdgeToSuperviewSafeArea:ALEdgeTop withInset:insets.top]]; + [constraints addObject:[self autoPinEdgeToSuperviewSafeArea:ALEdgeLeading withInset:insets.left]]; + [constraints addObject:[self autoPinEdgeToSuperviewSafeArea:ALEdgeBottom withInset:insets.bottom]]; + [constraints addObject:[self autoPinEdgeToSuperviewSafeArea:ALEdgeTrailing withInset:insets.right]]; + return constraints; +} + +/** + Pins 3 of the 4 edges of the view to the edges of its superview anchor with the given edge insets, excluding one edge. + The insets.left corresponds to a leading edge constraint, and insets.right corresponds to a trailing edge constraint. + + @param insets The insets for this view's edges from its superview's edges. The inset corresponding to the excluded edge + will be ignored. + @param edge The edge of this view to exclude in pinning to its superview anchor; this method will not apply any constraint to it. + @return An array of constraints added, ordered counterclockwise from top. + */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoPinEdgesToSuperviewSafeAreaWithInsets:(ALEdgeInsets)insets excludingEdge:(ALEdge)edge +{ + PL__NSMutableArray_of(NSLayoutConstraint *) *constraints = [NSMutableArray new]; + + if (edge != ALEdgeTop) { + [constraints addObject:[self autoPinEdgeToSuperviewSafeArea:ALEdgeTop withInset:insets.top]]; + } + if (edge != ALEdgeLeading && edge != ALEdgeLeft) { + [constraints addObject:[self autoPinEdgeToSuperviewSafeArea:ALEdgeLeading withInset:insets.left]]; + } + if (edge != ALEdgeBottom) { + [constraints addObject:[self autoPinEdgeToSuperviewSafeArea:ALEdgeBottom withInset:insets.bottom]]; + } + if (edge != ALEdgeTrailing && edge != ALEdgeRight) { + [constraints addObject:[self autoPinEdgeToSuperviewSafeArea:ALEdgeTrailing withInset:insets.right]]; + } + return constraints; +} + +#endif /* TARGET_OS_IPHONE */ + +#pragma mark Pin Edges to Superview + +/** + Pins the given edge of the view to the same edge of its superview. + + @param edge The edge of this view and its superview to pin. + @return The constraint added. + */ +- (NSLayoutConstraint *)autoPinEdgeToSuperviewEdge:(ALEdge)edge +{ + return [self autoPinEdgeToSuperviewEdge:edge withInset:0.0]; +} + +/** + Pins the given edge of the view to the same edge of its superview with an inset. + + @param edge The edge of this view and its superview to pin. + @param inset The amount to inset this view's edge from the superview's edge. + @return The constraint added. + */ +- (NSLayoutConstraint *)autoPinEdgeToSuperviewEdge:(ALEdge)edge withInset:(CGFloat)inset +{ + return [self autoPinEdgeToSuperviewEdge:edge withInset:inset relation:NSLayoutRelationEqual]; +} + +/** + Pins the given edge of the view to the same edge of its superview with an inset as a maximum or minimum. + + @param edge The edge of this view and its superview to pin. + @param inset The amount to inset this view's edge from the superview's edge. + @param relation Whether the inset should be at least, at most, or exactly equal to the given value. + @return The constraint added. + */ +- (NSLayoutConstraint *)autoPinEdgeToSuperviewEdge:(ALEdge)edge withInset:(CGFloat)inset relation:(NSLayoutRelation)relation +{ + self.translatesAutoresizingMaskIntoConstraints = NO; + ALView *superview = self.superview; + NSAssert(superview, @"View's superview must not be nil.\nView: %@", self); + if (edge == ALEdgeBottom || edge == ALEdgeRight || edge == ALEdgeTrailing) { + // The bottom, right, and trailing insets (and relations, if an inequality) are inverted to become offsets + inset = -inset; + if (relation == NSLayoutRelationLessThanOrEqual) { + relation = NSLayoutRelationGreaterThanOrEqual; + } else if (relation == NSLayoutRelationGreaterThanOrEqual) { + relation = NSLayoutRelationLessThanOrEqual; + } + } + return [self autoPinEdge:edge toEdge:edge ofView:superview withOffset:inset relation:relation]; +} + +/** + Pins the edges of the view to the edges of its superview. + + @return An array of constraints added, ordered counterclockwise from top. + */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoPinEdgesToSuperviewEdges +{ + return [self autoPinEdgesToSuperviewEdgesWithInsets:ALEdgeInsetsZero]; +} + +/** + Pins the edges of the view to the edges of its superview with the given edge insets. + The insets.left corresponds to a leading edge constraint, and insets.right corresponds to a trailing edge constraint. + + @param insets The insets for this view's edges from its superview's edges. + @return An array of constraints added, ordered counterclockwise from top. + */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoPinEdgesToSuperviewEdgesWithInsets:(ALEdgeInsets)insets +{ + PL__NSMutableArray_of(NSLayoutConstraint *) *constraints = [NSMutableArray new]; + [constraints addObject:[self autoPinEdgeToSuperviewEdge:ALEdgeTop withInset:insets.top]]; + [constraints addObject:[self autoPinEdgeToSuperviewEdge:ALEdgeLeading withInset:insets.left]]; + [constraints addObject:[self autoPinEdgeToSuperviewEdge:ALEdgeBottom withInset:insets.bottom]]; + [constraints addObject:[self autoPinEdgeToSuperviewEdge:ALEdgeTrailing withInset:insets.right]]; + return constraints; +} + +/** + Pins 3 of the 4 edges of the view to the edges of its superview with the given edge insets, excluding one edge. + The insets.left corresponds to a leading edge constraint, and insets.right corresponds to a trailing edge constraint. + + @param insets The insets for this view's edges from its superview's edges. The inset corresponding to the excluded edge + will be ignored. + @param edge The edge of this view to exclude in pinning to its superview; this method will not apply any constraint to it. + @return An array of constraints added, ordered counterclockwise from top. + */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoPinEdgesToSuperviewEdgesWithInsets:(ALEdgeInsets)insets excludingEdge:(ALEdge)edge +{ + PL__NSMutableArray_of(NSLayoutConstraint *) *constraints = [NSMutableArray new]; + switch (edge) { + case ALEdgeLeft: + [constraints addObject:[self autoPinEdgeToSuperviewEdge:ALEdgeTop withInset:insets.top]]; + [constraints addObject:[self autoPinEdgeToSuperviewEdge:ALEdgeBottom withInset:insets.bottom]]; + [constraints addObject:[self autoPinEdgeToSuperviewEdge:ALEdgeRight withInset:insets.right]]; + break; + case ALEdgeRight: + [constraints addObject:[self autoPinEdgeToSuperviewEdge:ALEdgeTop withInset:insets.top]]; + [constraints addObject:[self autoPinEdgeToSuperviewEdge:ALEdgeLeft withInset:insets.left]]; + [constraints addObject:[self autoPinEdgeToSuperviewEdge:ALEdgeBottom withInset:insets.bottom]]; + break; + case ALEdgeTop: + [constraints addObject:[self autoPinEdgeToSuperviewEdge:ALEdgeLeading withInset:insets.left]]; + [constraints addObject:[self autoPinEdgeToSuperviewEdge:ALEdgeBottom withInset:insets.bottom]]; + [constraints addObject:[self autoPinEdgeToSuperviewEdge:ALEdgeTrailing withInset:insets.right]]; + break; + case ALEdgeBottom: + [constraints addObject:[self autoPinEdgeToSuperviewEdge:ALEdgeTop withInset:insets.top]]; + [constraints addObject:[self autoPinEdgeToSuperviewEdge:ALEdgeLeading withInset:insets.left]]; + [constraints addObject:[self autoPinEdgeToSuperviewEdge:ALEdgeTrailing withInset:insets.right]]; + break; + case ALEdgeLeading: + [constraints addObject:[self autoPinEdgeToSuperviewEdge:ALEdgeTop withInset:insets.top]]; + [constraints addObject:[self autoPinEdgeToSuperviewEdge:ALEdgeBottom withInset:insets.bottom]]; + [constraints addObject:[self autoPinEdgeToSuperviewEdge:ALEdgeTrailing withInset:insets.right]]; + break; + case ALEdgeTrailing: + [constraints addObject:[self autoPinEdgeToSuperviewEdge:ALEdgeTop withInset:insets.top]]; + [constraints addObject:[self autoPinEdgeToSuperviewEdge:ALEdgeLeading withInset:insets.left]]; + [constraints addObject:[self autoPinEdgeToSuperviewEdge:ALEdgeBottom withInset:insets.bottom]]; + break; + } + return constraints; +} + +#if PL__PureLayout_MinBaseSDK_iOS_8_0 + +/** + Pins the given edge of the view to the corresponding margin of its superview. + + @param edge The edge of this view to pin to the corresponding margin of its superview. + @return The constraint added. + */ +- (NSLayoutConstraint *)autoPinEdgeToSuperviewMargin:(ALEdge)edge +{ + return [self autoPinEdgeToSuperviewMargin:edge relation:NSLayoutRelationEqual]; +} + +/** + Pins the given edge of the view to the corresponding margin of its superview with an inset. + + @param edge The edge of this view to pin to the corresponding margin of its superview. + @param @param inset The amount to inset this view's edge from the corresponding margin of its superview edge. + @return The constraint added. + */ +- (NSLayoutConstraint *)autoPinEdgeToSuperviewMargin:(ALEdge)edge withInset:(CGFloat)inset +{ + self.translatesAutoresizingMaskIntoConstraints = NO; + ALView *superview = self.superview; + NSAssert(superview, @"View's superview must not be nil.\nView: %@", self); + if (edge == ALEdgeBottom || edge == ALEdgeRight || edge == ALEdgeTrailing) { + // The bottom, right, and trailing insets (and relations, if an inequality) are inverted to become offsets + inset = -inset; + } + ALMargin margin = [NSLayoutConstraint al_marginForEdge:edge]; + return [self autoConstrainAttribute:(ALAttribute)edge toAttribute:(ALAttribute)margin ofView:superview withOffset:inset]; +} + +/** + Pins the given edge of the view to the corresponding margin of its superview as a maximum or minimum. + + @param edge The edge of this view to pin to the corresponding margin of its superview. + @param relation Whether the edge should be inset by at least, at most, or exactly the superview's margin. + @return The constraint added. + */ +- (NSLayoutConstraint *)autoPinEdgeToSuperviewMargin:(ALEdge)edge relation:(NSLayoutRelation)relation +{ + self.translatesAutoresizingMaskIntoConstraints = NO; + ALView *superview = self.superview; + NSAssert(superview, @"View's superview must not be nil.\nView: %@", self); + if (edge == ALEdgeBottom || edge == ALEdgeRight || edge == ALEdgeTrailing) { + // The bottom, right, and trailing relations are inverted + if (relation == NSLayoutRelationLessThanOrEqual) { + relation = NSLayoutRelationGreaterThanOrEqual; + } else if (relation == NSLayoutRelationGreaterThanOrEqual) { + relation = NSLayoutRelationLessThanOrEqual; + } + } + ALMargin margin = [NSLayoutConstraint al_marginForEdge:edge]; + return [self autoConstrainAttribute:(ALAttribute)edge toAttribute:(ALAttribute)margin ofView:superview withOffset:0.0 relation:relation]; +} + +/** + Pins the edges of the view to the margins of its superview. + + @return An array of constraints added, ordered counterclockwise from top. + */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoPinEdgesToSuperviewMargins +{ + return [self autoPinEdgesToSuperviewMarginsWithInsets:ALEdgeInsetsZero]; +} + +/** + Pins the edges of the view to the edges of its corresponding margins of its superview with the given edge insets. + The insets.left corresponds to a leading edge constraint, and insets.right corresponds to a trailing edge constraint. + + @param insets The insets for this view's edges from its corresponding margin of its superview. + @return An array of constraints added, ordered counterclockwise from top. + */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoPinEdgesToSuperviewMarginsWithInsets:(ALEdgeInsets)insets +{ + PL__NSMutableArray_of(NSLayoutConstraint *) *constraints = [NSMutableArray new]; + [constraints addObject:[self autoPinEdgeToSuperviewMargin:ALEdgeTop withInset:insets.top]]; + [constraints addObject:[self autoPinEdgeToSuperviewMargin:ALEdgeLeading withInset:insets.left]]; + [constraints addObject:[self autoPinEdgeToSuperviewMargin:ALEdgeBottom withInset:insets.bottom]]; + [constraints addObject:[self autoPinEdgeToSuperviewMargin:ALEdgeTrailing withInset:insets.right]]; + return constraints; +} + +/** + Pins 3 of the 4 edges of the view to the margins of its superview, excluding one edge. + + @param edge The edge of this view to exclude in pinning to its superview; this method will not apply any constraint to it. + @return An array of constraints added, ordered counterclockwise from top. + */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoPinEdgesToSuperviewMarginsExcludingEdge:(ALEdge)edge +{ + PL__NSMutableArray_of(NSLayoutConstraint *) *constraints = [NSMutableArray new]; + switch (edge) { + case ALEdgeLeft: + [constraints addObject:[self autoPinEdgeToSuperviewMargin:ALEdgeTop]]; + [constraints addObject:[self autoPinEdgeToSuperviewMargin:ALEdgeBottom]]; + [constraints addObject:[self autoPinEdgeToSuperviewMargin:ALEdgeRight]]; + break; + case ALEdgeRight: + [constraints addObject:[self autoPinEdgeToSuperviewMargin:ALEdgeTop]]; + [constraints addObject:[self autoPinEdgeToSuperviewMargin:ALEdgeLeft]]; + [constraints addObject:[self autoPinEdgeToSuperviewMargin:ALEdgeBottom]]; + break; + case ALEdgeTop: + [constraints addObject:[self autoPinEdgeToSuperviewMargin:ALEdgeLeading]]; + [constraints addObject:[self autoPinEdgeToSuperviewMargin:ALEdgeBottom]]; + [constraints addObject:[self autoPinEdgeToSuperviewMargin:ALEdgeTrailing]]; + break; + case ALEdgeBottom: + [constraints addObject:[self autoPinEdgeToSuperviewMargin:ALEdgeTop]]; + [constraints addObject:[self autoPinEdgeToSuperviewMargin:ALEdgeLeading]]; + [constraints addObject:[self autoPinEdgeToSuperviewMargin:ALEdgeTrailing]]; + break; + case ALEdgeLeading: + [constraints addObject:[self autoPinEdgeToSuperviewMargin:ALEdgeTop]]; + [constraints addObject:[self autoPinEdgeToSuperviewMargin:ALEdgeBottom]]; + [constraints addObject:[self autoPinEdgeToSuperviewMargin:ALEdgeTrailing]]; + break; + case ALEdgeTrailing: + [constraints addObject:[self autoPinEdgeToSuperviewMargin:ALEdgeTop]]; + [constraints addObject:[self autoPinEdgeToSuperviewMargin:ALEdgeLeading]]; + [constraints addObject:[self autoPinEdgeToSuperviewMargin:ALEdgeBottom]]; + break; + } + return constraints; +} + +#endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 */ + + +#pragma mark Pin Edges + +/** + Pins an edge of the view to a given edge of another view. + + @param edge The edge of this view to pin. + @param toEdge The edge of the other view to pin to. + @param otherView The other view to pin to. Must be in the same view hierarchy as this view. + @return The constraint added. + */ +- (NSLayoutConstraint *)autoPinEdge:(ALEdge)edge toEdge:(ALEdge)toEdge ofView:(ALView *)otherView +{ + return [self autoPinEdge:edge toEdge:toEdge ofView:otherView withOffset:0.0]; +} + +/** + Pins an edge of the view to a given edge of another view with an offset. + + @param edge The edge of this view to pin. + @param toEdge The edge of the other view to pin to. + @param otherView The other view to pin to. Must be in the same view hierarchy as this view. + @param offset The offset between the edge of this view and the edge of the other view. + @return The constraint added. + */ +- (NSLayoutConstraint *)autoPinEdge:(ALEdge)edge toEdge:(ALEdge)toEdge ofView:(ALView *)otherView withOffset:(CGFloat)offset +{ + return [self autoPinEdge:edge toEdge:toEdge ofView:otherView withOffset:offset relation:NSLayoutRelationEqual]; +} + +/** + Pins an edge of the view to a given edge of another view with an offset as a maximum or minimum. + + @param edge The edge of this view to pin. + @param toEdge The edge of the other view to pin to. + @param otherView The other view to pin to. Must be in the same view hierarchy as this view. + @param offset The offset between the edge of this view and the edge of the other view. + @param relation Whether the offset should be at least, at most, or exactly equal to the given value. + @return The constraint added. + */ +- (NSLayoutConstraint *)autoPinEdge:(ALEdge)edge toEdge:(ALEdge)toEdge ofView:(ALView *)otherView withOffset:(CGFloat)offset relation:(NSLayoutRelation)relation +{ + return [self autoConstrainAttribute:(ALAttribute)edge toAttribute:(ALAttribute)toEdge ofView:otherView withOffset:offset relation:relation]; +} + +#pragma mark Align Axes + +/** + Aligns an axis of the view to the same axis of another view. + + @param axis The axis of this view and the other view to align. + @param otherView The other view to align to. Must be in the same view hierarchy as this view. + @return The constraint added. + */ +- (NSLayoutConstraint *)autoAlignAxis:(ALAxis)axis toSameAxisOfView:(ALView *)otherView +{ + return [self autoAlignAxis:axis toSameAxisOfView:otherView withOffset:0.0]; +} + +/** + Aligns an axis of the view to the same axis of another view with an offset. + + @param axis The axis of this view and the other view to align. + @param otherView The other view to align to. Must be in the same view hierarchy as this view. + @param offset The offset between the axis of this view and the axis of the other view. + @return The constraint added. + */ +- (NSLayoutConstraint *)autoAlignAxis:(ALAxis)axis toSameAxisOfView:(ALView *)otherView withOffset:(CGFloat)offset +{ + return [self autoConstrainAttribute:(ALAttribute)axis toAttribute:(ALAttribute)axis ofView:otherView withOffset:offset]; +} + +/** + Aligns an axis of the view to the same axis of another view with a multiplier. + + @param axis The axis of this view and the other view to align. + @param otherView The other view to align to. Must be in the same view hierarchy as this view. + @param multiplier The multiplier between the axis of this view and the axis of the other view. + @return The constraint added. + */ +- (NSLayoutConstraint *)autoAlignAxis:(ALAxis)axis toSameAxisOfView:(ALView *)otherView withMultiplier:(CGFloat)multiplier +{ + return [self autoConstrainAttribute:(ALAttribute)axis toAttribute:(ALAttribute)axis ofView:otherView withMultiplier:multiplier]; +} + + +#pragma mark Match Dimensions + +/** + Matches a dimension of the view to a given dimension of another view. + + @param dimension The dimension of this view to pin. + @param toDimension The dimension of the other view to pin to. + @param otherView The other view to match to. Must be in the same view hierarchy as this view. + @return The constraint added. + */ +- (NSLayoutConstraint *)autoMatchDimension:(ALDimension)dimension toDimension:(ALDimension)toDimension ofView:(ALView *)otherView +{ + return [self autoMatchDimension:dimension toDimension:toDimension ofView:otherView withOffset:0.0]; +} + +/** + Matches a dimension of the view to a given dimension of another view with an offset. + + @param dimension The dimension of this view to pin. + @param toDimension The dimension of the other view to pin to. + @param otherView The other view to match to. Must be in the same view hierarchy as this view. + @param offset The offset between the dimension of this view and the dimension of the other view. + @return The constraint added. + */ +- (NSLayoutConstraint *)autoMatchDimension:(ALDimension)dimension toDimension:(ALDimension)toDimension ofView:(ALView *)otherView withOffset:(CGFloat)offset +{ + return [self autoMatchDimension:dimension toDimension:toDimension ofView:otherView withOffset:offset relation:NSLayoutRelationEqual]; +} + +/** + Matches a dimension of the view to a given dimension of another view with an offset as a maximum or minimum. + + @param dimension The dimension of this view to pin. + @param toDimension The dimension of the other view to pin to. + @param otherView The other view to match to. Must be in the same view hierarchy as this view. + @param offset The offset between the dimension of this view and the dimension of the other view. + @param relation Whether the offset should be at least, at most, or exactly equal to the given value. + @return The constraint added. + */ +- (NSLayoutConstraint *)autoMatchDimension:(ALDimension)dimension toDimension:(ALDimension)toDimension ofView:(ALView *)otherView withOffset:(CGFloat)offset relation:(NSLayoutRelation)relation +{ + return [self autoConstrainAttribute:(ALAttribute)dimension toAttribute:(ALAttribute)toDimension ofView:otherView withOffset:offset relation:relation]; +} + +/** + Matches a dimension of the view to a multiple of a given dimension of another view. + + @param dimension The dimension of this view to pin. + @param toDimension The dimension of the other view to pin to. + @param otherView The other view to match to. Must be in the same view hierarchy as this view. + @param multiplier The multiple of the other view's given dimension that this view's given dimension should be. + @return The constraint added. + */ +- (NSLayoutConstraint *)autoMatchDimension:(ALDimension)dimension toDimension:(ALDimension)toDimension ofView:(ALView *)otherView withMultiplier:(CGFloat)multiplier +{ + return [self autoMatchDimension:dimension toDimension:toDimension ofView:otherView withMultiplier:multiplier relation:NSLayoutRelationEqual]; +} + +/** + Matches a dimension of the view to a multiple of a given dimension of another view as a maximum or minimum. + + @param dimension The dimension of this view to pin. + @param toDimension The dimension of the other view to pin to. + @param otherView The other view to match to. Must be in the same view hierarchy as this view. + @param multiplier The multiple of the other view's given dimension that this view's given dimension should be. + @param relation Whether the multiple should be at least, at most, or exactly equal to the given value. + @return The constraint added. + */ +- (NSLayoutConstraint *)autoMatchDimension:(ALDimension)dimension toDimension:(ALDimension)toDimension ofView:(ALView *)otherView withMultiplier:(CGFloat)multiplier relation:(NSLayoutRelation)relation +{ + return [self autoConstrainAttribute:(ALAttribute)dimension toAttribute:(ALAttribute)toDimension ofView:otherView withMultiplier:multiplier relation:relation]; +} + + +#pragma mark Set Dimensions + +/** + Sets the view to a specific size. + + @param size The size to set this view's dimensions to. + @return An array of constraints added. + */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoSetDimensionsToSize:(CGSize)size +{ + PL__NSMutableArray_of(NSLayoutConstraint *) *constraints = [NSMutableArray new]; + [constraints addObject:[self autoSetDimension:ALDimensionWidth toSize:size.width]]; + [constraints addObject:[self autoSetDimension:ALDimensionHeight toSize:size.height]]; + return constraints; +} + +/** + Sets the given dimension of the view to a specific size. + + @param dimension The dimension of this view to set. + @param size The size to set the given dimension to. + @return The constraint added. + */ +- (NSLayoutConstraint *)autoSetDimension:(ALDimension)dimension toSize:(CGFloat)size +{ + return [self autoSetDimension:dimension toSize:size relation:NSLayoutRelationEqual]; +} + +/** + Sets the given dimension of the view to a specific size as a maximum or minimum. + + @param dimension The dimension of this view to set. + @param size The size to set the given dimension to. + @param relation Whether the size should be at least, at most, or exactly equal to the given value. + @return The constraint added. + */ +- (NSLayoutConstraint *)autoSetDimension:(ALDimension)dimension toSize:(CGFloat)size relation:(NSLayoutRelation)relation +{ + self.translatesAutoresizingMaskIntoConstraints = NO; + NSLayoutAttribute layoutAttribute = [NSLayoutConstraint al_layoutAttributeForAttribute:(ALAttribute)dimension]; + NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:self attribute:layoutAttribute relatedBy:relation toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:0.0 constant:size]; + [constraint autoInstall]; + return constraint; +} + + +#pragma mark Set Content Compression Resistance & Hugging + +/** + Sets the priority of content compression resistance for an axis. + NOTE: This method must be called from within the block passed into the method +[autoSetPriority:forConstraints:] + + @param axis The axis to set the content compression resistance priority for. + */ +- (void)autoSetContentCompressionResistancePriorityForAxis:(ALAxis)axis +{ + NSAssert([NSLayoutConstraint al_isExecutingPriorityConstraintsBlock], @"%@ should only be called from within the block passed into the method +[autoSetPriority:forConstraints:]", NSStringFromSelector(_cmd)); + if ([NSLayoutConstraint al_isExecutingPriorityConstraintsBlock]) { + self.translatesAutoresizingMaskIntoConstraints = NO; + ALLayoutConstraintAxis constraintAxis = [NSLayoutConstraint al_constraintAxisForAxis:axis]; +#if TARGET_OS_IPHONE + [self setContentCompressionResistancePriority:[NSLayoutConstraint al_currentGlobalConstraintPriority] forAxis:constraintAxis]; +#else + [self setContentCompressionResistancePriority:[NSLayoutConstraint al_currentGlobalConstraintPriority] forOrientation:constraintAxis]; +#endif /* TARGET_OS_IPHONE */ + } +} + +/** + Sets the priority of content hugging for an axis. + NOTE: This method must be called from within the block passed into the method +[autoSetPriority:forConstraints:] + + @param axis The axis to set the content hugging priority for. + */ +- (void)autoSetContentHuggingPriorityForAxis:(ALAxis)axis +{ + NSAssert([NSLayoutConstraint al_isExecutingPriorityConstraintsBlock], @"%@ should only be called from within the block passed into the method +[autoSetPriority:forConstraints:]", NSStringFromSelector(_cmd)); + if ([NSLayoutConstraint al_isExecutingPriorityConstraintsBlock]) { + self.translatesAutoresizingMaskIntoConstraints = NO; + ALLayoutConstraintAxis constraintAxis = [NSLayoutConstraint al_constraintAxisForAxis:axis]; +#if TARGET_OS_IPHONE + [self setContentHuggingPriority:[NSLayoutConstraint al_currentGlobalConstraintPriority] forAxis:constraintAxis]; +#else + [self setContentHuggingPriority:[NSLayoutConstraint al_currentGlobalConstraintPriority] forOrientation:constraintAxis]; +#endif /* TARGET_OS_IPHONE */ + } +} + + +#pragma mark Constrain Any Attributes + +/** + Constrains an attribute of the view to a given attribute of another view. + This method can be used to constrain different types of attributes across two views. + + @param attribute Any attribute of this view to constrain. + @param toAttribute Any attribute of the other view to constrain to. + @param otherView The other view to constrain to. Must be in the same view hierarchy as this view. + @return The constraint added. + */ +- (NSLayoutConstraint *)autoConstrainAttribute:(ALAttribute)attribute toAttribute:(ALAttribute)toAttribute ofView:(ALView *)otherView +{ + return [self autoConstrainAttribute:attribute toAttribute:toAttribute ofView:otherView withOffset:0.0]; +} + +/** + Constrains an attribute of the view to a given attribute of another view with an offset. + This method can be used to constrain different types of attributes across two views. + + @param attribute Any attribute of this view to constrain. + @param toAttribute Any attribute of the other view to constrain to. + @param otherView The other view to constrain to. Must be in the same view hierarchy as this view. + @param offset The offset between the attribute of this view and the attribute of the other view. + @return The constraint added. + */ +- (NSLayoutConstraint *)autoConstrainAttribute:(ALAttribute)attribute toAttribute:(ALAttribute)toAttribute ofView:(ALView *)otherView withOffset:(CGFloat)offset +{ + return [self autoConstrainAttribute:attribute toAttribute:toAttribute ofView:otherView withOffset:offset relation:NSLayoutRelationEqual]; +} + +/** + Constrains an attribute of the view to a given attribute of another view with an offset as a maximum or minimum. + This method can be used to constrain different types of attributes across two views. + + @param attribute Any attribute of this view to constrain. + @param toAttribute Any attribute of the other view to constrain to. + @param otherView The other view to constrain to. Must be in the same view hierarchy as this view. + @param offset The offset between the attribute of this view and the attribute of the other view. + @param relation Whether the offset should be at least, at most, or exactly equal to the given value. + @return The constraint added. + */ +- (NSLayoutConstraint *)autoConstrainAttribute:(ALAttribute)attribute toAttribute:(ALAttribute)toAttribute ofView:(ALView *)otherView withOffset:(CGFloat)offset relation:(NSLayoutRelation)relation +{ + self.translatesAutoresizingMaskIntoConstraints = NO; + NSLayoutAttribute layoutAttribute = [NSLayoutConstraint al_layoutAttributeForAttribute:attribute]; + NSLayoutAttribute toLayoutAttribute = [NSLayoutConstraint al_layoutAttributeForAttribute:toAttribute]; + NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:self attribute:layoutAttribute relatedBy:relation toItem:otherView attribute:toLayoutAttribute multiplier:1.0 constant:offset]; + [constraint autoInstall]; + return constraint; +} + +/** + Constrains an attribute of the view to a given attribute of another view with a multiplier. + This method can be used to constrain different types of attributes across two views. + + @param attribute Any attribute of this view to constrain. + @param toAttribute Any attribute of the other view to constrain to. + @param otherView The other view to constrain to. Must be in the same view hierarchy as this view. + @param multiplier The multiplier between the attribute of this view and the attribute of the other view. + @return The constraint added. + */ +- (NSLayoutConstraint *)autoConstrainAttribute:(ALAttribute)attribute toAttribute:(ALAttribute)toAttribute ofView:(ALView *)otherView withMultiplier:(CGFloat)multiplier +{ + return [self autoConstrainAttribute:attribute toAttribute:toAttribute ofView:otherView withMultiplier:multiplier relation:NSLayoutRelationEqual]; +} + +/** + Constrains an attribute of the view to a given attribute of another view with a multiplier as a maximum or minimum. + This method can be used to constrain different types of attributes across two views. + + @param attribute Any attribute of this view to constrain. + @param toAttribute Any attribute of the other view to constrain to. + @param otherView The other view to constrain to. Must be in the same view hierarchy as this view. + @param multiplier The multiplier between the attribute of this view and the attribute of the other view. + @param relation Whether the multiplier should be at least, at most, or exactly equal to the given value. + @return The constraint added. + */ +- (NSLayoutConstraint *)autoConstrainAttribute:(ALAttribute)attribute toAttribute:(ALAttribute)toAttribute ofView:(ALView *)otherView withMultiplier:(CGFloat)multiplier relation:(NSLayoutRelation)relation +{ + self.translatesAutoresizingMaskIntoConstraints = NO; + NSLayoutAttribute layoutAttribute = [NSLayoutConstraint al_layoutAttributeForAttribute:attribute]; + NSLayoutAttribute toLayoutAttribute = [NSLayoutConstraint al_layoutAttributeForAttribute:toAttribute]; + NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:self attribute:layoutAttribute relatedBy:relation toItem:otherView attribute:toLayoutAttribute multiplier:multiplier constant:0.0]; + [constraint autoInstall]; + return constraint; +} + + +#pragma mark Pin to Layout Guides + +#if TARGET_OS_IPHONE + +/** + Pins the top edge of the view to the top layout guide of the given view controller with an inset. + For compatibility with iOS 6 (where layout guides do not exist), this method will simply pin the top edge of + the view to the top edge of the given view controller's view with an inset. + + @param viewController The view controller whose topLayoutGuide should be used to pin to. + @param inset The amount to inset this view's top edge from the layout guide. + @return The constraint added. + */ +- (NSLayoutConstraint *)autoPinToTopLayoutGuideOfViewController:(UIViewController *)viewController withInset:(CGFloat)inset +{ + return [self autoPinToTopLayoutGuideOfViewController:viewController withInset:inset relation:NSLayoutRelationEqual]; +} + +- (NSLayoutConstraint *)autoPinToTopLayoutGuideOfViewController:(UIViewController *)viewController withInset:(CGFloat)inset relation:(NSLayoutRelation)relation +{ + if (PL__PureLayout_MinSysVer_iOS_7_0) { + self.translatesAutoresizingMaskIntoConstraints = NO; + NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeTop relatedBy:relation toItem:viewController.topLayoutGuide attribute:NSLayoutAttributeBottom multiplier:1.0 constant:inset]; + [viewController.view al_addConstraint:constraint]; // Can't use autoInstall because the layout guide is not a view + return constraint; + } else { + // iOS 6 fallback + return [self autoPinEdge:ALEdgeTop toEdge:ALEdgeTop ofView:viewController.view withOffset:inset relation:relation]; + } +} + +/** + Pins the bottom edge of the view to the bottom layout guide of the given view controller with an inset. + For compatibility with iOS 6 (where layout guides do not exist), this method will simply pin the bottom edge of + the view to the bottom edge of the given view controller's view with an inset. + + @param viewController The view controller whose bottomLayoutGuide should be used to pin to. + @param inset The amount to inset this view's bottom edge from the layout guide. + @return The constraint added. + */ +- (NSLayoutConstraint *)autoPinToBottomLayoutGuideOfViewController:(UIViewController *)viewController withInset:(CGFloat)inset +{ + return [self autoPinToBottomLayoutGuideOfViewController:viewController withInset:inset relation:NSLayoutRelationEqual]; +} + +- (NSLayoutConstraint *)autoPinToBottomLayoutGuideOfViewController:(UIViewController *)viewController withInset:(CGFloat)inset relation:(NSLayoutRelation)relation +{ + // The bottom inset (and relation, if an inequality) is inverted to become an offset + inset = -inset; + if (relation == NSLayoutRelationLessThanOrEqual) { + relation = NSLayoutRelationGreaterThanOrEqual; + } else if (relation == NSLayoutRelationGreaterThanOrEqual) { + relation = NSLayoutRelationLessThanOrEqual; + } + if (PL__PureLayout_MinSysVer_iOS_7_0) { + self.translatesAutoresizingMaskIntoConstraints = NO; + NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeBottom relatedBy:relation toItem:viewController.bottomLayoutGuide attribute:NSLayoutAttributeTop multiplier:1.0 constant:inset]; + [viewController.view al_addConstraint:constraint]; // Can't use autoInstall because the layout guide is not a view + return constraint; + } else { + // iOS 6 fallback + return [self autoPinEdge:ALEdgeBottom toEdge:ALEdgeBottom ofView:viewController.view withOffset:inset relation:relation]; + } +} + +#endif /* TARGET_OS_IPHONE */ + +#pragma mark Internal Methods + +/** + Adds the given constraint to this view after applying the global state to the constraint. + NOTE: This method is compatible with all versions of iOS, and should be used for older versions before the active + property on NSLayoutConstraint was introduced. + + This method should be the only one that calls the UIView/NSView addConstraint: method directly. + + @param constraint The constraint to set the global priority on and then add to this view. + */ +- (void)al_addConstraint:(NSLayoutConstraint *)constraint +{ + [NSLayoutConstraint al_applyGlobalStateToConstraint:constraint]; + if ([NSLayoutConstraint al_preventAutomaticConstraintInstallation]) { + [[NSLayoutConstraint al_currentArrayOfCreatedConstraints] addObject:constraint]; + } else { + [self addConstraint:constraint]; + } +} + +/** + Returns the common superview for this view and the given other view. + Raises an exception if this view and the other view do not share a common superview. + + @return The common superview for the two views. + */ +- (ALView *)al_commonSuperviewWithView:(ALView *)otherView +{ + ALView *commonSuperview = nil; + ALView *startView = self; + do { +#if TARGET_OS_IPHONE + if ([otherView isDescendantOfView:startView]) { + commonSuperview = startView; + } +#else + if ([otherView isDescendantOf:startView]) { + commonSuperview = startView; + } +#endif /* TARGET_OS_IPHONE */ + startView = startView.superview; + } while (startView && !commonSuperview); + NSAssert(commonSuperview, @"Can't constrain two views that do not share a common superview. Make sure that both views have been added into the same view hierarchy."); + return commonSuperview; +} + +/** + Aligns this view to another view with an alignment attribute. + + @param attribute The attribute to use to align the two views. + @param otherView The other view to align to. + @param axis The axis along which the views are distributed, used to validate the alignment attribute. + @return The constraint added. + */ +- (NSLayoutConstraint *)al_alignAttribute:(ALAttribute)attribute toView:(ALView *)otherView forAxis:(ALAxis)axis +{ + NSLayoutConstraint *constraint = nil; + switch (attribute) { + case ALAttributeVertical: + NSAssert(axis == ALAxisVertical, @"Cannot align views that are distributed horizontally with ALAttributeVertical."); + constraint = [self autoAlignAxis:ALAxisVertical toSameAxisOfView:otherView]; + break; + case ALAttributeHorizontal: + NSAssert(axis != ALAxisVertical, @"Cannot align views that are distributed vertically with ALAttributeHorizontal."); + constraint = [self autoAlignAxis:ALAxisHorizontal toSameAxisOfView:otherView]; + break; + case ALAttributeBaseline: // same value as ALAttributeLastBaseline + NSAssert(axis != ALAxisVertical, @"Cannot align views that are distributed vertically with ALAttributeBaseline."); + constraint = [self autoAlignAxis:ALAxisBaseline toSameAxisOfView:otherView]; + break; +#if PL__PureLayout_MinBaseSDK_iOS_8_0 + case ALAttributeFirstBaseline: + NSAssert(PL__PureLayout_MinSysVer_iOS_8_0, @"ALAttributeFirstBaseline is only supported on iOS 8.0 or higher."); + NSAssert(axis != ALAxisVertical, @"Cannot align views that are distributed vertically with ALAttributeFirstBaseline."); + constraint = [self autoAlignAxis:ALAxisFirstBaseline toSameAxisOfView:otherView]; + break; +#endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 */ + case ALAttributeTop: + NSAssert(axis != ALAxisVertical, @"Cannot align views that are distributed vertically with ALAttributeTop."); + constraint = [self autoPinEdge:ALEdgeTop toEdge:ALEdgeTop ofView:otherView]; + break; + case ALAttributeLeft: + NSAssert(axis == ALAxisVertical, @"Cannot align views that are distributed horizontally with ALAttributeLeft."); + constraint = [self autoPinEdge:ALEdgeLeft toEdge:ALEdgeLeft ofView:otherView]; + break; + case ALAttributeBottom: + NSAssert(axis != ALAxisVertical, @"Cannot align views that are distributed vertically with ALAttributeBottom."); + constraint = [self autoPinEdge:ALEdgeBottom toEdge:ALEdgeBottom ofView:otherView]; + break; + case ALAttributeRight: + NSAssert(axis == ALAxisVertical, @"Cannot align views that are distributed horizontally with ALAttributeRight."); + constraint = [self autoPinEdge:ALEdgeRight toEdge:ALEdgeRight ofView:otherView]; + break; + case ALAttributeLeading: + NSAssert(axis == ALAxisVertical, @"Cannot align views that are distributed horizontally with ALAttributeLeading."); + constraint = [self autoPinEdge:ALEdgeLeading toEdge:ALEdgeLeading ofView:otherView]; + break; + case ALAttributeTrailing: + NSAssert(axis == ALAxisVertical, @"Cannot align views that are distributed horizontally with ALAttributeTrailing."); + constraint = [self autoPinEdge:ALEdgeTrailing toEdge:ALEdgeTrailing ofView:otherView]; + break; + + // All of the below attributes are invalid as alignment options. Listing them explicitly (even though they just fall through to the default case) to avoid an incomplete switch statement warning from the compiler. + case ALAttributeWidth: + case ALAttributeHeight: +#if PL__PureLayout_MinBaseSDK_iOS_8_0 + case ALAttributeMarginLeft: + case ALAttributeMarginRight: + case ALAttributeMarginTop: + case ALAttributeMarginBottom: + case ALAttributeMarginLeading: + case ALAttributeMarginTrailing: + case ALAttributeMarginAxisVertical: + case ALAttributeMarginAxisHorizontal: +#endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 */ + default: + NSAssert(nil, @"Unsupported attribute for alignment."); + break; + } + return constraint; +} + +@end diff --git a/Pods/PureLayout/PureLayout/PureLayout/NSArray+PureLayout.h b/Pods/PureLayout/PureLayout/PureLayout/NSArray+PureLayout.h new file mode 100755 index 00000000..682ef1b4 --- /dev/null +++ b/Pods/PureLayout/PureLayout/PureLayout/NSArray+PureLayout.h @@ -0,0 +1,115 @@ +// +// NSArray+PureLayout.h +// https://github.com/PureLayout/PureLayout +// +// Copyright (c) 2012 Richard Turton +// Copyright (c) 2013-2015 Tyler Fox +// +// This code is distributed under the terms and conditions of the MIT license. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +// + +#import "PureLayoutDefines.h" + + +PL__ASSUME_NONNULL_BEGIN + +#pragma mark NSArray+PureLayout + +/** + A category on NSArray that provides a simple yet powerful interface to: + - Manage an array of Auto Layout constraints + - Apply constraints to an array of views + */ +@interface NSArray (PureLayout) + + +#pragma mark Array of Constraints + +/** Activates the constraints in this array. */ +- (void)autoInstallConstraints; + +/** Deactivates the constraints in this array. */ +- (void)autoRemoveConstraints; + +#if PL__PureLayout_MinBaseSDK_iOS_8_0 || PL__PureLayout_MinBaseSDK_OSX_10_10 + +/** Sets the string as the identifier for the constraints in this array. Available in iOS 7.0 and OS X 10.9 and later. */ +- (instancetype)autoIdentifyConstraints:(NSString *)identifier; + +#endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 || PL__PureLayout_MinBaseSDK_OSX_10_10 */ + + +#pragma mark Array of Views + +/** Aligns views in this array to one another along a given edge. */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoAlignViewsToEdge:(ALEdge)edge; + +/** Aligns views in this array to one another along a given axis. */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoAlignViewsToAxis:(ALAxis)axis; + +/** Matches a given dimension of all the views in this array. */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoMatchViewsDimension:(ALDimension)dimension; + +/** Sets the given dimension of all the views in this array to a given size. */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoSetViewsDimension:(ALDimension)dimension toSize:(CGFloat)size; + +/** Sets all of the views in this array to a given size. */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoSetViewsDimensionsToSize:(CGSize)size; + + +/** Distributes the views in this array equally along the selected axis in their superview. + Views will be the same size (variable) in the dimension along the axis and will have spacing (fixed) between them. */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoDistributeViewsAlongAxis:(ALAxis)axis + alignedTo:(ALAttribute)alignment + withFixedSpacing:(CGFloat)spacing; + +/** Distributes the views in this array equally along the selected axis in their superview. + Views will be the same size (variable) in the dimension along the axis and will have spacing (fixed) between them, with optional insets from the first and last views to their superview. */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoDistributeViewsAlongAxis:(ALAxis)axis + alignedTo:(ALAttribute)alignment + withFixedSpacing:(CGFloat)spacing + insetSpacing:(BOOL)shouldSpaceInsets; + +/** Distributes the views in this array equally along the selected axis in their superview. + Views will have spacing (fixed) between them, with optional insets from the first and last views to their superview, and optionally constrained to the same size in the dimension along the axis. */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoDistributeViewsAlongAxis:(ALAxis)axis + alignedTo:(ALAttribute)alignment + withFixedSpacing:(CGFloat)spacing + insetSpacing:(BOOL)shouldSpaceInsets + matchedSizes:(BOOL)shouldMatchSizes; + + +/** Distributes the views in this array equally along the selected axis in their superview. + Views will be the same size (fixed) in the dimension along the axis and will have spacing (variable) between them. */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoDistributeViewsAlongAxis:(ALAxis)axis + alignedTo:(ALAttribute)alignment + withFixedSize:(CGFloat)size; + +/** Distributes the views in this array equally along the selected axis in their superview. + Views will be the same size (fixed) in the dimension along the axis and will have spacing (variable) between them, with optional insets from the first and last views to their superview. */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoDistributeViewsAlongAxis:(ALAxis)axis + alignedTo:(ALAttribute)alignment + withFixedSize:(CGFloat)size + insetSpacing:(BOOL)shouldSpaceInsets; + +@end + +PL__ASSUME_NONNULL_END diff --git a/Pods/PureLayout/PureLayout/PureLayout/NSArray+PureLayout.m b/Pods/PureLayout/PureLayout/PureLayout/NSArray+PureLayout.m new file mode 100755 index 00000000..20106306 --- /dev/null +++ b/Pods/PureLayout/PureLayout/PureLayout/NSArray+PureLayout.m @@ -0,0 +1,505 @@ +// +// NSArray+PureLayout.m +// https://github.com/PureLayout/PureLayout +// +// Copyright (c) 2012 Richard Turton +// Copyright (c) 2013-2015 Tyler Fox +// +// This code is distributed under the terms and conditions of the MIT license. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +// + +#import "NSArray+PureLayout.h" +#import "ALView+PureLayout.h" +#import "NSLayoutConstraint+PureLayout.h" +#import "PureLayout+Internal.h" + + +#pragma mark - NSArray+PureLayout + +@implementation NSArray (PureLayout) + + +#pragma mark Array of Constraints + +/** + Activates the constraints in this array. + */ +- (void)autoInstallConstraints +{ +#if PL__PureLayout_MinBaseSDK_iOS_8_0 || PL__PureLayout_MinBaseSDK_OSX_10_10 + if ([NSLayoutConstraint respondsToSelector:@selector(activateConstraints:)]) { + for (id object in self) { + if ([object isKindOfClass:[NSLayoutConstraint class]]) { + [NSLayoutConstraint al_applyGlobalStateToConstraint:object]; + } + } + if ([NSLayoutConstraint al_preventAutomaticConstraintInstallation]) { + [[NSLayoutConstraint al_currentArrayOfCreatedConstraints] addObjectsFromArray:self]; + } else { + [NSLayoutConstraint activateConstraints:self]; + } + return; + } +#endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 || PL__PureLayout_MinBaseSDK_OSX_10_10 */ + + for (id object in self) { + if ([object isKindOfClass:[NSLayoutConstraint class]]) { + [((NSLayoutConstraint *)object) autoInstall]; + } + } +} + +/** + Deactivates the constraints in this array. + */ +- (void)autoRemoveConstraints +{ +#if PL__PureLayout_MinBaseSDK_iOS_8_0 || PL__PureLayout_MinBaseSDK_OSX_10_10 + if ([NSLayoutConstraint respondsToSelector:@selector(deactivateConstraints:)]) { + [NSLayoutConstraint deactivateConstraints:self]; + return; + } +#endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 || PL__PureLayout_MinBaseSDK_OSX_10_10 */ + + for (id object in self) { + if ([object isKindOfClass:[NSLayoutConstraint class]]) { + [((NSLayoutConstraint *)object) autoRemove]; + } + } +} + +#if PL__PureLayout_MinBaseSDK_iOS_8_0 || PL__PureLayout_MinBaseSDK_OSX_10_10 + +/** + Sets the string as the identifier for the constraints in this array. Available in iOS 7.0 and OS X 10.9 and later. + The identifier will be printed along with each constraint's description. + This is helpful to document the constraints' purpose and aid in debugging. + + @param identifier A string used to identify the constraints in this array. + @return This array. + */ +- (instancetype)autoIdentifyConstraints:(NSString *)identifier +{ + for (id object in self) { + if ([object isKindOfClass:[NSLayoutConstraint class]]) { + [((NSLayoutConstraint *)object) autoIdentify:identifier]; + } + } + return self; +} + +#endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 || PL__PureLayout_MinBaseSDK_OSX_10_10 */ + + +#pragma mark Array of Views + +/** + Aligns views in this array to one another along a given edge. + Note: This array must contain at least 2 views, and all views must share a common superview. + + @param edge The edge to which the views will be aligned. + @return An array of constraints added. + */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoAlignViewsToEdge:(ALEdge)edge +{ + NSAssert([self al_containsMinimumNumberOfViews:2], @"This array must contain at least 2 views."); + PL__NSMutableArray_of(NSLayoutConstraint *) *constraints = [NSMutableArray new]; + ALView *previousView = nil; + for (id object in self) { + if ([object isKindOfClass:[ALView class]]) { + ALView *view = (ALView *)object; + view.translatesAutoresizingMaskIntoConstraints = NO; + if (previousView) { + [constraints addObject:[view autoPinEdge:edge toEdge:edge ofView:previousView]]; + } + previousView = view; + } + } + return constraints; +} + +/** + Aligns views in this array to one another along a given axis. + Note: This array must contain at least 2 views, and all views must share a common superview. + + @param axis The axis to which the views will be aligned. + @return An array of constraints added. + */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoAlignViewsToAxis:(ALAxis)axis +{ + NSAssert([self al_containsMinimumNumberOfViews:2], @"This array must contain at least 2 views."); + PL__NSMutableArray_of(NSLayoutConstraint *) *constraints = [NSMutableArray new]; + ALView *previousView = nil; + for (id object in self) { + if ([object isKindOfClass:[ALView class]]) { + ALView *view = (ALView *)object; + view.translatesAutoresizingMaskIntoConstraints = NO; + if (previousView) { + [constraints addObject:[view autoAlignAxis:axis toSameAxisOfView:previousView]]; + } + previousView = view; + } + } + return constraints; +} + +/** + Matches a given dimension of all the views in this array. + Note: This array must contain at least 2 views, and all views must share a common superview. + + @param dimension The dimension to match for all of the views. + @return An array of constraints added. + */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoMatchViewsDimension:(ALDimension)dimension +{ + NSAssert([self al_containsMinimumNumberOfViews:2], @"This array must contain at least 2 views."); + PL__NSMutableArray_of(NSLayoutConstraint *) *constraints = [NSMutableArray new]; + ALView *previousView = nil; + for (id object in self) { + if ([object isKindOfClass:[ALView class]]) { + ALView *view = (ALView *)object; + view.translatesAutoresizingMaskIntoConstraints = NO; + if (previousView) { + [constraints addObject:[view autoMatchDimension:dimension toDimension:dimension ofView:previousView]]; + } + previousView = view; + } + } + return constraints; +} + +/** + Sets the given dimension of all the views in this array to a given size. + Note: This array must contain at least 1 view. + + @param dimension The dimension of each of the views to set. + @param size The size to set the given dimension of each view to. + @return An array of constraints added. + */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoSetViewsDimension:(ALDimension)dimension toSize:(CGFloat)size +{ + NSAssert([self al_containsMinimumNumberOfViews:1], @"This array must contain at least 1 view."); + PL__NSMutableArray_of(NSLayoutConstraint *) *constraints = [NSMutableArray new]; + for (id object in self) { + if ([object isKindOfClass:[ALView class]]) { + ALView *view = (ALView *)object; + view.translatesAutoresizingMaskIntoConstraints = NO; + [constraints addObject:[view autoSetDimension:dimension toSize:size]]; + } + } + return constraints; +} + +/** + Sets all of the views in this array to a given size. + Note: This array must contain at least 1 view. + + @param size The size to set each view's dimensions to. + @return An array of constraints added. + */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoSetViewsDimensionsToSize:(CGSize)size +{ + PL__NSMutableArray_of(NSLayoutConstraint *) *constraints = [NSMutableArray new]; + [constraints addObjectsFromArray:[self autoSetViewsDimension:ALDimensionWidth toSize:size.width]]; + [constraints addObjectsFromArray:[self autoSetViewsDimension:ALDimensionHeight toSize:size.height]]; + return constraints; +} + + +/** + Distributes the views in this array equally along the selected axis in their superview. + Views will be the same size (variable) in the dimension along the axis and will have spacing (fixed) between them, + including from the first and last views to their superview. + + @param axis The axis along which to distribute the views. + @param alignment The attribute to use to align all the views to one another. + @param spacing The fixed amount of spacing between each view. + @return An array of constraints added. + */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoDistributeViewsAlongAxis:(ALAxis)axis + alignedTo:(ALAttribute)alignment + withFixedSpacing:(CGFloat)spacing +{ + return [self autoDistributeViewsAlongAxis:axis + alignedTo:alignment + withFixedSpacing:spacing + insetSpacing:YES]; +} + +/** + Distributes the views in this array equally along the selected axis in their superview. + Views will be the same size (variable) in the dimension along the axis and will have spacing (fixed) between them. + The first and last views can optionally be inset from their superview by the same amount of spacing as between views. + + @param axis The axis along which to distribute the views. + @param alignment The attribute to use to align all the views to one another. + @param spacing The fixed amount of spacing between each view. + @param shouldSpaceInsets Whether the first and last views should be equally inset from their superview. + @return An array of constraints added. + */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoDistributeViewsAlongAxis:(ALAxis)axis + alignedTo:(ALAttribute)alignment + withFixedSpacing:(CGFloat)spacing + insetSpacing:(BOOL)shouldSpaceInsets +{ + return [self autoDistributeViewsAlongAxis:axis + alignedTo:alignment + withFixedSpacing:spacing + insetSpacing:shouldSpaceInsets + matchedSizes:YES]; +} + +/** + Distributes the views in this array equally along the selected axis in their superview. + Views will have fixed spacing between them, and can optionally be constrained to the same size in the dimension along the axis. + The first and last views can optionally be inset from their superview by the same amount of spacing as between views. + + @param axis The axis along which to distribute the views. + @param alignment The attribute to use to align all the views to one another. + @param spacing The fixed amount of spacing between each view. + @param shouldSpaceInsets Whether the first and last views should be equally inset from their superview. + @param shouldMatchSizes Whether all views will be constrained to be the same size in the dimension along the axis. + NOTE: All views must specify an intrinsic content size if passing NO, otherwise the layout will be ambiguous! + @return An array of constraints added. + */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoDistributeViewsAlongAxis:(ALAxis)axis + alignedTo:(ALAttribute)alignment + withFixedSpacing:(CGFloat)spacing + insetSpacing:(BOOL)shouldSpaceInsets + matchedSizes:(BOOL)shouldMatchSizes +{ + NSAssert([self al_containsMinimumNumberOfViews:1], @"This array must contain at least 1 view to distribute."); + ALDimension matchedDimension; + ALEdge firstEdge, lastEdge; + switch (axis) { + case ALAxisHorizontal: + case ALAxisBaseline: // same value as ALAxisLastBaseline +#if PL__PureLayout_MinBaseSDK_iOS_8_0 + case ALAxisFirstBaseline: +#endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 */ + matchedDimension = ALDimensionWidth; + firstEdge = ALEdgeLeading; + lastEdge = ALEdgeTrailing; + break; + case ALAxisVertical: + matchedDimension = ALDimensionHeight; + firstEdge = ALEdgeTop; + lastEdge = ALEdgeBottom; + break; + default: + NSAssert(nil, @"Not a valid ALAxis."); + return nil; + } + CGFloat leadingSpacing = shouldSpaceInsets ? spacing : 0.0; + CGFloat trailingSpacing = shouldSpaceInsets ? spacing : 0.0; + + PL__NSMutableArray_of(NSLayoutConstraint *) *constraints = [NSMutableArray new]; + ALView *previousView = nil; + for (id object in self) { + if ([object isKindOfClass:[ALView class]]) { + ALView *view = (ALView *)object; + view.translatesAutoresizingMaskIntoConstraints = NO; + if (previousView) { + // Second, Third, ... View + [constraints addObject:[view autoPinEdge:firstEdge toEdge:lastEdge ofView:previousView withOffset:spacing]]; + if (shouldMatchSizes) { + [constraints addObject:[view autoMatchDimension:matchedDimension toDimension:matchedDimension ofView:previousView]]; + } + [constraints addObject:[view al_alignAttribute:alignment toView:previousView forAxis:axis]]; + } + else { + // First view + [constraints addObject:[view autoPinEdgeToSuperviewEdge:firstEdge withInset:leadingSpacing]]; + } + previousView = view; + } + } + if (previousView) { + // Last View + [constraints addObject:[previousView autoPinEdgeToSuperviewEdge:lastEdge withInset:trailingSpacing]]; + } + return constraints; +} + +/** + Distributes the views in this array equally along the selected axis in their superview. + Views will be the same size (fixed) in the dimension along the axis and will have spacing (variable) between them, + including from the first and last views to their superview. + + @param axis The axis along which to distribute the views. + @param alignment The attribute to use to align all the views to one another. + @param size The fixed size of each view in the dimension along the given axis. + @return An array of constraints added. + */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoDistributeViewsAlongAxis:(ALAxis)axis + alignedTo:(ALAttribute)alignment + withFixedSize:(CGFloat)size +{ + return [self autoDistributeViewsAlongAxis:axis + alignedTo:alignment + withFixedSize:size + insetSpacing:YES]; +} + +/** + Distributes the views in this array equally along the selected axis in their superview. + Views will be the same size (fixed) in the dimension along the axis and will have spacing (variable) between them. + The first and last views can optionally be inset from their superview by the same amount of spacing as between views. + + @param axis The axis along which to distribute the views. + @param alignment The attribute to use to align all the views to one another. + @param size The fixed size of each view in the dimension along the given axis. + @param shouldSpaceInsets Whether the first and last views should be equally inset from their superview. + @return An array of constraints added. + */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoDistributeViewsAlongAxis:(ALAxis)axis + alignedTo:(ALAttribute)alignment + withFixedSize:(CGFloat)size + insetSpacing:(BOOL)shouldSpaceInsets +{ + NSAssert([self al_containsMinimumNumberOfViews:1], @"This array must contain at least 1 view to distribute."); + ALDimension fixedDimension; + NSLayoutAttribute attribute; + switch (axis) { + case ALAxisHorizontal: + case ALAxisBaseline: // same value as ALAxisLastBaseline +#if PL__PureLayout_MinBaseSDK_iOS_8_0 + case ALAxisFirstBaseline: +#endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 */ + fixedDimension = ALDimensionWidth; + attribute = NSLayoutAttributeCenterX; + break; + case ALAxisVertical: + fixedDimension = ALDimensionHeight; + attribute = NSLayoutAttributeCenterY; + break; + default: + NSAssert(nil, @"Not a valid ALAxis."); + return nil; + } +#if TARGET_OS_IPHONE +# if !defined(PURELAYOUT_APP_EXTENSIONS) + BOOL isRightToLeftLayout = [[UIApplication sharedApplication] userInterfaceLayoutDirection] == UIUserInterfaceLayoutDirectionRightToLeft; +# else + // App Extensions may not access -[UIApplication sharedApplication]; fall back to checking the bundle's preferred localization character direction + BOOL isRightToLeftLayout = [NSLocale characterDirectionForLanguage:[[NSBundle mainBundle] preferredLocalizations][0]] == NSLocaleLanguageDirectionRightToLeft; +# endif /* !defined(PURELAYOUT_APP_EXTENSIONS) */ +#else + BOOL isRightToLeftLayout = [[NSApplication sharedApplication] userInterfaceLayoutDirection] == NSUserInterfaceLayoutDirectionRightToLeft; +#endif /* TARGET_OS_IPHONE */ + BOOL shouldFlipOrder = isRightToLeftLayout && (axis != ALAxisVertical); // imitate the effect of leading/trailing when distributing horizontally + + PL__NSMutableArray_of(NSLayoutConstraint *) *constraints = [NSMutableArray new]; + PL__NSArray_of(ALView *) *views = [self al_copyViewsOnly]; + NSUInteger numberOfViews = [views count]; + ALView *commonSuperview = [views al_commonSuperviewOfViews]; + ALView *previousView = nil; + for (NSUInteger i = 0; i < numberOfViews; i++) { + ALView *view = shouldFlipOrder ? views[numberOfViews - i - 1] : views[i]; + view.translatesAutoresizingMaskIntoConstraints = NO; + [constraints addObject:[view autoSetDimension:fixedDimension toSize:size]]; + CGFloat multiplier, constant; + if (shouldSpaceInsets) { + multiplier = (i * 2.0 + 2.0) / (numberOfViews + 1.0); + constant = (multiplier - 1.0) * size / 2.0; + } else { + multiplier = (i * 2.0) / (numberOfViews - 1.0); + constant = (-multiplier + 1.0) * size / 2.0; + } + // If the multiplier is very close to 0, set it to the minimum value to prevent the second item in the constraint from being lost. Filed as rdar://19168380 + if (fabs(multiplier) < kMULTIPLIER_MIN_VALUE) { + multiplier = kMULTIPLIER_MIN_VALUE; + } + NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:view attribute:attribute relatedBy:NSLayoutRelationEqual toItem:commonSuperview attribute:attribute multiplier:multiplier constant:constant]; + [constraint autoInstall]; + [constraints addObject:constraint]; + if (previousView) { + [constraints addObject:[view al_alignAttribute:alignment toView:previousView forAxis:axis]]; + } + previousView = view; + } + return constraints; +} + +#pragma mark Internal Helper Methods + +/** + Returns the common superview for the views in this array. If there is only one view in the array, its superview will be returned. + Raises an exception if the views in this array do not share a common superview. + + @return The common superview for the views in this array. + */ +- (ALView *)al_commonSuperviewOfViews +{ + ALView *commonSuperview = nil; + ALView *previousView = nil; + for (id object in self) { + if ([object isKindOfClass:[ALView class]]) { + ALView *view = (ALView *)object; + if (previousView) { + commonSuperview = [view al_commonSuperviewWithView:commonSuperview]; + } else { + commonSuperview = view.superview; + } + previousView = view; + } + } + NSAssert(commonSuperview, @"Can't constrain views that do not share a common superview. Make sure that all the views in this array have been added into the same view hierarchy."); + return commonSuperview; +} + +/** + Determines whether this array contains a minimum number of views. + + @param minimumNumberOfViews The minimum number of views to check for. + @return YES if this array contains at least the minimum number of views, NO otherwise. + */ +- (BOOL)al_containsMinimumNumberOfViews:(NSUInteger)minimumNumberOfViews +{ + NSUInteger numberOfViews = 0; + for (id object in self) { + if ([object isKindOfClass:[ALView class]]) { + numberOfViews++; + if (numberOfViews >= minimumNumberOfViews) { + return YES; + } + } + } + return numberOfViews >= minimumNumberOfViews; +} + +/** + Creates a copy of this array containing only the view objects in it. + + @return A new array containing only the views that are in this array. + */ +- (PL__NSArray_of(ALView *) *)al_copyViewsOnly +{ + PL__NSMutableArray_of(ALView *) *viewsOnlyArray = [NSMutableArray arrayWithCapacity:[self count]]; + for (id object in self) { + if ([object isKindOfClass:[ALView class]]) { + [viewsOnlyArray addObject:object]; + } + } + return viewsOnlyArray; +} + +@end diff --git a/Pods/PureLayout/PureLayout/PureLayout/NSLayoutConstraint+PureLayout.h b/Pods/PureLayout/PureLayout/PureLayout/NSLayoutConstraint+PureLayout.h new file mode 100755 index 00000000..ae48ca0f --- /dev/null +++ b/Pods/PureLayout/PureLayout/PureLayout/NSLayoutConstraint+PureLayout.h @@ -0,0 +1,84 @@ +// +// NSLayoutConstraint+PureLayout.h +// https://github.com/PureLayout/PureLayout +// +// Copyright (c) 2013-2015 Tyler Fox +// +// This code is distributed under the terms and conditions of the MIT license. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +// + +#import "PureLayoutDefines.h" + + +PL__ASSUME_NONNULL_BEGIN + +#pragma mark NSLayoutConstraint+PureLayout + +/** + A category on NSLayoutConstraint that allows constraints to be easily installed & removed. + */ +@interface NSLayoutConstraint (PureLayout) + + +#pragma mark Batch Constraint Creation + +/** Creates all of the constraints in the block, then installs (activates) them all at once. + All constraints created from calls to the PureLayout API in the block are returned in a single array. + This may be more efficient than installing (activating) each constraint one-by-one. */ ++ (PL__NSArray_of(NSLayoutConstraint *) *)autoCreateAndInstallConstraints:(__attribute__((noescape)) ALConstraintsBlock)block; + +/** Creates all of the constraints in the block but prevents them from being automatically installed (activated). + All constraints created from calls to the PureLayout API in the block are returned in a single array. */ ++ (PL__NSArray_of(NSLayoutConstraint *) *)autoCreateConstraintsWithoutInstalling:(__attribute__((noescape)) ALConstraintsBlock)block; + + +#pragma mark Set Priority For Constraints + +/** Sets the constraint priority to the given value for all constraints created using the PureLayout API within the given constraints block. + NOTE: This method will have no effect (and will NOT set the priority) on constraints created or added without using the PureLayout API! */ ++ (void)autoSetPriority:(ALLayoutPriority)priority forConstraints:(__attribute__((noescape)) ALConstraintsBlock)block; + + +#pragma mark Identify Constraints + +#if PL__PureLayout_MinBaseSDK_iOS_8_0 || PL__PureLayout_MinBaseSDK_OSX_10_10 + +/** Sets the identifier for all constraints created using the PureLayout API within the given constraints block. + NOTE: This method will have no effect (and will NOT set the identifier) on constraints created or added without using the PureLayout API! */ ++ (void)autoSetIdentifier:(NSString *)identifier forConstraints:(__attribute__((noescape)) ALConstraintsBlock)block; + +/** Sets the string as the identifier for this constraint. Available in iOS 7.0 and OS X 10.9 and later. */ +- (instancetype)autoIdentify:(NSString *)identifier; + +#endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 || PL__PureLayout_MinBaseSDK_OSX_10_10 */ + + +#pragma mark Install & Remove Constraints + +/** Activates the the constraint. */ +- (void)autoInstall; + +/** Deactivates the constraint. */ +- (void)autoRemove; + +@end + +PL__ASSUME_NONNULL_END diff --git a/Pods/PureLayout/PureLayout/PureLayout/NSLayoutConstraint+PureLayout.m b/Pods/PureLayout/PureLayout/PureLayout/NSLayoutConstraint+PureLayout.m new file mode 100755 index 00000000..5738bc00 --- /dev/null +++ b/Pods/PureLayout/PureLayout/PureLayout/NSLayoutConstraint+PureLayout.m @@ -0,0 +1,552 @@ +// +// NSLayoutConstraint+PureLayout.m +// https://github.com/PureLayout/PureLayout +// +// Copyright (c) 2013-2015 Tyler Fox +// +// This code is distributed under the terms and conditions of the MIT license. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +// + +#import "NSLayoutConstraint+PureLayout.h" +#import "ALView+PureLayout.h" +#import "NSArray+PureLayout.h" +#import "PureLayout+Internal.h" + + +#pragma mark - NSLayoutConstraint+PureLayout + +@implementation NSLayoutConstraint (PureLayout) + +#pragma mark Batch Constraint Creation + +/** + A global variable that stores a stack of arrays of constraints created without being immediately installed. + When executing a constraints block passed into the +[autoCreateConstraintsWithoutInstalling:] method, a new + mutable array is pushed onto this stack, and all constraints created with PureLayout in the block are added + to this array. When the block finishes executing, the array is popped off this stack. Automatic constraint + installation is prevented if this stack contains at least 1 array. + + NOTE: Access to this variable is not synchronized (and should only be done on the main thread). + */ +static PL__NSMutableArray_of(PL__NSMutableArray_of(NSLayoutConstraint *) *) *_al_arraysOfCreatedConstraints = nil; + +/** + A global variable that is set to YES when installing a batch of constraints collected from a call to +[autoCreateAndInstallConstraints]. + When this flag is YES, constraints are installed immediately without checking for or adding to the +[al_currentArrayOfCreatedConstraints]. + This is necessary to properly handle nested calls to +[autoCreateAndInstallConstraints], where calls whose block contains other call(s) + should not return constraints from within the blocks of nested call(s). + */ +static BOOL _al_isInstallingCreatedConstraints = NO; + +/** + Accessor for the global state that stores arrays of constraints created without being installed. + */ ++ (PL__NSMutableArray_of(PL__NSMutableArray_of(NSLayoutConstraint *) *) *)al_arraysOfCreatedConstraints +{ + NSAssert([NSThread isMainThread], @"PureLayout is not thread safe, and must be used exclusively from the main thread."); + if (!_al_arraysOfCreatedConstraints) { + _al_arraysOfCreatedConstraints = [NSMutableArray new]; + } + return _al_arraysOfCreatedConstraints; +} + +/** + Accessor for the current mutable array of constraints created without being immediately installed. + */ ++ (PL__NSMutableArray_of(NSLayoutConstraint *) *)al_currentArrayOfCreatedConstraints +{ + return [[self al_arraysOfCreatedConstraints] lastObject]; +} + +/** + Accessor for the global state that determines whether automatic constraint installation should be prevented. + */ ++ (BOOL)al_preventAutomaticConstraintInstallation +{ + return (_al_isInstallingCreatedConstraints == NO) && ([[self al_arraysOfCreatedConstraints] count] > 0); +} + +/** + Creates all of the constraints in the block, then installs (activates) them all at once. + All constraints created from calls to the PureLayout API in the block are returned in a single array. + This may be more efficient than installing (activating) each constraint one-by-one. + + Note: calls to this method may be nested. The constraints returned from a call will NOT include constraints + created in nested calls; constraints are only returned from the inner-most call they are created within. + + @param block A block of method calls to the PureLayout API that create constraints. + @return An array of the constraints that were created from calls to the PureLayout API inside the block. + */ ++ (PL__NSArray_of(NSLayoutConstraint *) *)autoCreateAndInstallConstraints:(__attribute__((noescape)) ALConstraintsBlock)block +{ + NSArray *createdConstraints = [self autoCreateConstraintsWithoutInstalling:block]; + _al_isInstallingCreatedConstraints = YES; + [createdConstraints autoInstallConstraints]; + _al_isInstallingCreatedConstraints = NO; + return createdConstraints; +} + +/** + Creates all of the constraints in the block but prevents them from being automatically installed (activated). + All constraints created from calls to the PureLayout API in the block are returned in a single array. + + Note: calls to this method may be nested. The constraints returned from a call will NOT include constraints + created in nested calls; constraints are only returned from the inner-most call they are created within. + + @param block A block of method calls to the PureLayout API that create constraints. + @return An array of the constraints that were created from calls to the PureLayout API inside the block. + */ ++ (PL__NSArray_of(NSLayoutConstraint *) *)autoCreateConstraintsWithoutInstalling:(__attribute__((noescape)) ALConstraintsBlock)block +{ + NSAssert(block, @"The constraints block cannot be nil."); + NSArray *createdConstraints = nil; + if (block) { + [[self al_arraysOfCreatedConstraints] addObject:[NSMutableArray new]]; + block(); + createdConstraints = [self al_currentArrayOfCreatedConstraints]; + [[self al_arraysOfCreatedConstraints] removeLastObject]; + } + return createdConstraints; +} + + +#pragma mark Set Priority For Constraints + +/** + A global variable that stores a stack of layout priorities to set on constraints. + When executing a constraints block passed into the +[autoSetPriority:forConstraints:] method, the priority for + that call is pushed onto this stack, and when the block finishes executing, that priority is popped off this + stack. If this stack contains at least 1 priority, the priority at the top of the stack will be set for all + constraints created by this library (even if automatic constraint installation is being prevented). + NOTE: Access to this variable is not synchronized (and should only be done on the main thread). + */ +static PL__NSMutableArray_of(NSNumber *) *_al_globalConstraintPriorities = nil; + +/** + Accessor for the global stack of layout priorities. + */ ++ (PL__NSMutableArray_of(NSNumber *) *)al_globalConstraintPriorities +{ + NSAssert([NSThread isMainThread], @"PureLayout is not thread safe, and must be used exclusively from the main thread."); + if (!_al_globalConstraintPriorities) { + _al_globalConstraintPriorities = [NSMutableArray new]; + } + return _al_globalConstraintPriorities; +} + +/** + Returns the current layout priority to use for constraints. + When executing a constraints block passed into +[autoSetPriority:forConstraints:], this will return + the priority for the current block. Otherwise, the default Required priority is returned. + */ ++ (ALLayoutPriority)al_currentGlobalConstraintPriority +{ + PL__NSMutableArray_of(NSNumber *) *globalConstraintPriorities = [self al_globalConstraintPriorities]; + if ([globalConstraintPriorities count] == 0) { + return ALLayoutPriorityRequired; + } + return [[globalConstraintPriorities lastObject] floatValue]; +} + +/** + Accessor for the global state that determines if we're currently in the scope of a priority constraints block. + */ ++ (BOOL)al_isExecutingPriorityConstraintsBlock +{ + return [[self al_globalConstraintPriorities] count] > 0; +} + +/** + Sets the constraint priority to the given value for all constraints created using the PureLayout + API within the given constraints block. + + NOTE: This method will have no effect (and will NOT set the priority) on constraints created or added + without using the PureLayout API! + + @param priority The layout priority to be set on all constraints created in the constraints block. + @param block A block of method calls to the PureLayout API that create and install constraints. + */ ++ (void)autoSetPriority:(ALLayoutPriority)priority forConstraints:(__attribute__((noescape)) ALConstraintsBlock)block +{ + NSAssert(block, @"The constraints block cannot be nil."); + if (block) { + [[self al_globalConstraintPriorities] addObject:@(priority)]; + block(); + [[self al_globalConstraintPriorities] removeLastObject]; + } +} + + +#pragma mark Identify Constraints + +#if PL__PureLayout_MinBaseSDK_iOS_8_0 || PL__PureLayout_MinBaseSDK_OSX_10_10 + +/** + A global variable that stores a stack of identifier strings to set on constraints. + When executing a constraints block passed into the +[autoSetIdentifier:forConstraints:] method, the identifier for + that call is pushed onto this stack, and when the block finishes executing, that identifier is popped off this + stack. If this stack contains at least 1 identifier, the identifier at the top of the stack will be set for all + constraints created by this library (even if automatic constraint installation is being prevented). + NOTE: Access to this variable is not synchronized (and should only be done on the main thread). + */ +static PL__NSMutableArray_of(NSString *) *_al_globalConstraintIdentifiers = nil; + +/** + Accessor for the global state of constraint identifiers. + */ ++ (PL__NSMutableArray_of(NSString *) *)al_globalConstraintIdentifiers +{ + NSAssert([NSThread isMainThread], @"PureLayout is not thread safe, and must be used exclusively from the main thread."); + if (!_al_globalConstraintIdentifiers) { + _al_globalConstraintIdentifiers = [NSMutableArray new]; + } + return _al_globalConstraintIdentifiers; +} + +/** + Returns the current identifier string to use for constraints. + When executing a constraints block passed into +[autoSetIdentifier:forConstraints:], this will return + the identifier for the current block. Otherwise, nil is returned. + */ ++ (NSString *)al_currentGlobalConstraintIdentifier +{ + PL__NSMutableArray_of(NSString *) *globalConstraintIdentifiers = [self al_globalConstraintIdentifiers]; + if ([globalConstraintIdentifiers count] == 0) { + return nil; + } + return [globalConstraintIdentifiers lastObject]; +} + +/** + Sets the identifier for all constraints created using the PureLayout API within the given constraints block. + + NOTE: This method will have no effect (and will NOT set the identifier) on constraints created or added + without using the PureLayout API! + + @param identifier A string used to identify all constraints created in the constraints block. + @param block A block of method calls to the PureLayout API that create and install constraints. + */ ++ (void)autoSetIdentifier:(NSString *)identifier forConstraints:(__attribute__((noescape)) ALConstraintsBlock)block +{ + NSAssert(block, @"The constraints block cannot be nil."); + NSAssert(identifier, @"The identifier string cannot be nil."); + if (block) { + if (identifier) { + [[self al_globalConstraintIdentifiers] addObject:identifier]; + } + block(); + if (identifier) { + [[self al_globalConstraintIdentifiers] removeLastObject]; + } + } +} + +/** + Sets the string as the identifier for this constraint. Available in iOS 7.0 and OS X 10.9 and later. + The identifier will be printed along with the constraint's description. + This is helpful to document a constraint's purpose and aid in debugging. + + @param identifier A string used to identify this constraint. + @return This constraint. + */ +- (instancetype)autoIdentify:(NSString *)identifier +{ + if ([self respondsToSelector:@selector(setIdentifier:)]) { + self.identifier = identifier; + } + return self; +} + +#endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 || PL__PureLayout_MinBaseSDK_OSX_10_10 */ + + +#pragma mark Install & Remove Constraints + +/** + Activates the constraint. + */ +- (void)autoInstall +{ +#if PL__PureLayout_MinBaseSDK_iOS_8_0 || PL__PureLayout_MinBaseSDK_OSX_10_10 + if ([self respondsToSelector:@selector(setActive:)]) { + [NSLayoutConstraint al_applyGlobalStateToConstraint:self]; + if ([NSLayoutConstraint al_preventAutomaticConstraintInstallation]) { + [[NSLayoutConstraint al_currentArrayOfCreatedConstraints] addObject:self]; + } else { + self.active = YES; + } + return; + } +#endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 || PL__PureLayout_MinBaseSDK_OSX_10_10 */ + + NSAssert(self.firstItem || self.secondItem, @"Can't install a constraint with nil firstItem and secondItem."); + if (self.firstItem) { + if (self.secondItem) { + NSAssert([self.firstItem isKindOfClass:[ALView class]] && [self.secondItem isKindOfClass:[ALView class]], @"Can only automatically install a constraint if both items are views."); + ALView *commonSuperview = [self.firstItem al_commonSuperviewWithView:self.secondItem]; + [commonSuperview al_addConstraint:self]; + } else { + NSAssert([self.firstItem isKindOfClass:[ALView class]], @"Can only automatically install a constraint if the item is a view."); + [self.firstItem al_addConstraint:self]; + } + } else { + NSAssert([self.secondItem isKindOfClass:[ALView class]], @"Can only automatically install a constraint if the item is a view."); + [self.secondItem al_addConstraint:self]; + } +} + +/** + Deactivates the constraint. + */ +- (void)autoRemove +{ +#if PL__PureLayout_MinBaseSDK_iOS_8_0 || PL__PureLayout_MinBaseSDK_OSX_10_10 + if ([self respondsToSelector:@selector(setActive:)]) { + self.active = NO; + return; + } +#endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 || PL__PureLayout_MinBaseSDK_OSX_10_10 */ + + if (self.secondItem) { + ALView *commonSuperview = [self.firstItem al_commonSuperviewWithView:self.secondItem]; + while (commonSuperview) { + if ([commonSuperview.constraints containsObject:self]) { + [commonSuperview removeConstraint:self]; + return; + } + commonSuperview = commonSuperview.superview; + } + } + else { + [self.firstItem removeConstraint:self]; + return; + } + NSAssert(nil, @"Failed to remove constraint: %@", self); +} + + +#pragma mark Internal Methods + +/** + Applies the global constraint priority and identifier to the given constraint. + This should be done before installing all constraints. + + @param constraint The constraint to set the global priority and identifier on. + */ ++ (void)al_applyGlobalStateToConstraint:(NSLayoutConstraint *)constraint +{ + if ([NSLayoutConstraint al_isExecutingPriorityConstraintsBlock]) { + constraint.priority = [NSLayoutConstraint al_currentGlobalConstraintPriority]; + } +#if PL__PureLayout_MinBaseSDK_iOS_8_0 || PL__PureLayout_MinBaseSDK_OSX_10_10 + NSString *globalConstraintIdentifier = [NSLayoutConstraint al_currentGlobalConstraintIdentifier]; + if (globalConstraintIdentifier) { + [constraint autoIdentify:globalConstraintIdentifier]; + } +#endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 || PL__PureLayout_MinBaseSDK_OSX_10_10 */ +} + +/** + Returns the corresponding NSLayoutAttribute for the given ALAttribute. + + @return The layout attribute for the given ALAttribute. + */ ++ (NSLayoutAttribute)al_layoutAttributeForAttribute:(ALAttribute)attribute +{ + NSLayoutAttribute layoutAttribute = NSLayoutAttributeNotAnAttribute; + switch (attribute) { + case ALEdgeLeft: + layoutAttribute = NSLayoutAttributeLeft; + break; + case ALEdgeRight: + layoutAttribute = NSLayoutAttributeRight; + break; + case ALEdgeTop: + layoutAttribute = NSLayoutAttributeTop; + break; + case ALEdgeBottom: + layoutAttribute = NSLayoutAttributeBottom; + break; + case ALEdgeLeading: + layoutAttribute = NSLayoutAttributeLeading; + break; + case ALEdgeTrailing: + layoutAttribute = NSLayoutAttributeTrailing; + break; + case ALDimensionWidth: + layoutAttribute = NSLayoutAttributeWidth; + break; + case ALDimensionHeight: + layoutAttribute = NSLayoutAttributeHeight; + break; + case ALAxisVertical: + layoutAttribute = NSLayoutAttributeCenterX; + break; + case ALAxisHorizontal: + layoutAttribute = NSLayoutAttributeCenterY; + break; + case ALAxisBaseline: // same value as ALAxisLastBaseline + layoutAttribute = NSLayoutAttributeBaseline; + break; +#if PL__PureLayout_MinBaseSDK_iOS_8_0 + case ALAxisFirstBaseline: + NSAssert(PL__PureLayout_MinSysVer_iOS_8_0, @"ALAxisFirstBaseline is only supported on iOS 8.0 or higher."); + layoutAttribute = NSLayoutAttributeFirstBaseline; + break; + case ALMarginLeft: + NSAssert(PL__PureLayout_MinSysVer_iOS_8_0, @"ALEdgeLeftMargin is only supported on iOS 8.0 or higher."); + layoutAttribute = NSLayoutAttributeLeftMargin; + break; + case ALMarginRight: + NSAssert(PL__PureLayout_MinSysVer_iOS_8_0, @"ALEdgeRightMargin is only supported on iOS 8.0 or higher."); + layoutAttribute = NSLayoutAttributeRightMargin; + break; + case ALMarginTop: + NSAssert(PL__PureLayout_MinSysVer_iOS_8_0, @"ALEdgeTopMargin is only supported on iOS 8.0 or higher."); + layoutAttribute = NSLayoutAttributeTopMargin; + break; + case ALMarginBottom: + NSAssert(PL__PureLayout_MinSysVer_iOS_8_0, @"ALEdgeBottomMargin is only supported on iOS 8.0 or higher."); + layoutAttribute = NSLayoutAttributeBottomMargin; + break; + case ALMarginLeading: + NSAssert(PL__PureLayout_MinSysVer_iOS_8_0, @"ALEdgeLeadingMargin is only supported on iOS 8.0 or higher."); + layoutAttribute = NSLayoutAttributeLeadingMargin; + break; + case ALMarginTrailing: + NSAssert(PL__PureLayout_MinSysVer_iOS_8_0, @"ALEdgeTrailingMargin is only supported on iOS 8.0 or higher."); + layoutAttribute = NSLayoutAttributeTrailingMargin; + break; + case ALMarginAxisVertical: + NSAssert(PL__PureLayout_MinSysVer_iOS_8_0, @"ALAxisVerticalMargin is only supported on iOS 8.0 or higher."); + layoutAttribute = NSLayoutAttributeCenterXWithinMargins; + break; + case ALMarginAxisHorizontal: + NSAssert(PL__PureLayout_MinSysVer_iOS_8_0, @"ALAxisHorizontalMargin is only supported on iOS 8.0 or higher."); + layoutAttribute = NSLayoutAttributeCenterYWithinMargins; + break; +#endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 */ + default: + NSAssert(nil, @"Not a valid ALAttribute."); + break; + } + return layoutAttribute; +} + +/** + Returns the corresponding ALLayoutConstraintAxis for the given ALAxis. + + @return The constraint axis for the given axis. + */ ++ (ALLayoutConstraintAxis)al_constraintAxisForAxis:(ALAxis)axis +{ + ALLayoutConstraintAxis constraintAxis; + switch (axis) { + case ALAxisVertical: + constraintAxis = ALLayoutConstraintAxisVertical; + break; + case ALAxisHorizontal: + case ALAxisBaseline: // same value as ALAxisLastBaseline +#if PL__PureLayout_MinBaseSDK_iOS_8_0 + case ALAxisFirstBaseline: +#endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 */ + constraintAxis = ALLayoutConstraintAxisHorizontal; + break; + default: + NSAssert(nil, @"Not a valid ALAxis."); + constraintAxis = ALLayoutConstraintAxisHorizontal; // default to an arbitrary value to satisfy the compiler + break; + } + return constraintAxis; +} + +#if PL__PureLayout_MinBaseSDK_iOS_8_0 + +/** + Returns the corresponding margin for the given edge. + + @param edge The edge to convert to the corresponding margin. + @return The margin for the given edge. + */ ++ (ALMargin)al_marginForEdge:(ALEdge)edge +{ + NSAssert(PL__PureLayout_MinSysVer_iOS_8_0, @"Margin attributes are only supported on iOS 8.0 or higher."); + ALMargin margin; + switch (edge) { + case ALEdgeLeft: + margin = ALMarginLeft; + break; + case ALEdgeRight: + margin = ALMarginRight; + break; + case ALEdgeTop: + margin = ALMarginTop; + break; + case ALEdgeBottom: + margin = ALMarginBottom; + break; + case ALEdgeLeading: + margin = ALMarginLeading; + break; + case ALEdgeTrailing: + margin = ALMarginTrailing; + break; + default: + NSAssert(nil, @"Not a valid ALEdge."); + margin = ALMarginLeft; // default to an arbitrary value to satisfy the compiler + break; + } + return margin; +} + +/** + Returns the corresponding margin axis for the given axis. + + @param axis The axis to convert to the corresponding margin axis. + @return The margin axis for the given axis. + */ ++ (ALMarginAxis)al_marginAxisForAxis:(ALAxis)axis +{ + NSAssert(PL__PureLayout_MinSysVer_iOS_8_0, @"Margin attributes are only supported on iOS 8.0 or higher."); + ALMarginAxis marginAxis; + switch (axis) { + case ALAxisVertical: + marginAxis = ALMarginAxisVertical; + break; + case ALAxisHorizontal: + marginAxis = ALMarginAxisHorizontal; + break; + case ALAxisBaseline: + case ALAxisFirstBaseline: + NSAssert(nil, @"The baseline axis attributes do not have corresponding margin axis attributes."); + marginAxis = ALMarginAxisVertical; // default to an arbitrary value to satisfy the compiler + break; + default: + NSAssert(nil, @"Not a valid ALAxis."); + marginAxis = ALMarginAxisVertical; // default to an arbitrary value to satisfy the compiler + break; + } + return marginAxis; +} + +#endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 */ + +@end diff --git a/Pods/PureLayout/PureLayout/PureLayout/PureLayout+Internal.h b/Pods/PureLayout/PureLayout/PureLayout/PureLayout+Internal.h new file mode 100644 index 00000000..15c2eeb7 --- /dev/null +++ b/Pods/PureLayout/PureLayout/PureLayout/PureLayout+Internal.h @@ -0,0 +1,87 @@ +// +// PureLayout+Internal.h +// https://github.com/PureLayout/PureLayout +// +// Copyright (c) 2014-2015 Tyler Fox +// +// This code is distributed under the terms and conditions of the MIT license. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +// + +#import "PureLayoutDefines.h" + + +// Using generics with NSMutableArray is so common in the internal implementation of PureLayout that it gets a dedicated preprocessor macro for better readability. +#define PL__NSMutableArray_of(type) PL__GENERICS(NSMutableArray, type) + +PL__ASSUME_NONNULL_BEGIN + +/** A constant that represents the smallest valid positive value for the multiplier of a constraint, + since a value of 0 will cause the second item to be lost in the internal auto layout engine. */ +static const CGFloat kMULTIPLIER_MIN_VALUE = (CGFloat)0.00001; // very small floating point numbers (e.g. CGFLOAT_MIN) can cause problems + + +/** + A category that exposes the internal (private) helper methods of the ALView+PureLayout category. + */ +@interface ALView (PureLayoutInternal) + +- (void)al_addConstraint:(NSLayoutConstraint *)constraint; +- (ALView *)al_commonSuperviewWithView:(ALView *)otherView; +- (NSLayoutConstraint *)al_alignAttribute:(ALAttribute)attribute toView:(ALView *)otherView forAxis:(ALAxis)axis; + +@end + + +/** + A category that exposes the internal (private) helper methods of the NSArray+PureLayout category. + */ +@interface NSArray (PureLayoutInternal) + +- (ALView *)al_commonSuperviewOfViews; +- (BOOL)al_containsMinimumNumberOfViews:(NSUInteger)minimumNumberOfViews; +- (PL__NSArray_of(ALView *) *)al_copyViewsOnly; + +@end + + +/** + A category that exposes the internal (private) helper methods of the NSLayoutConstraint+PureLayout category. + */ +@interface NSLayoutConstraint (PureLayoutInternal) + ++ (BOOL)al_preventAutomaticConstraintInstallation; ++ (PL__NSMutableArray_of(NSLayoutConstraint *) *)al_currentArrayOfCreatedConstraints; ++ (BOOL)al_isExecutingPriorityConstraintsBlock; ++ (ALLayoutPriority)al_currentGlobalConstraintPriority; +#if PL__PureLayout_MinBaseSDK_iOS_8_0 || PL__PureLayout_MinBaseSDK_OSX_10_10 ++ (nullable NSString *)al_currentGlobalConstraintIdentifier; +#endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 || PL__PureLayout_MinBaseSDK_OSX_10_10 */ ++ (void)al_applyGlobalStateToConstraint:(NSLayoutConstraint *)constraint; ++ (NSLayoutAttribute)al_layoutAttributeForAttribute:(ALAttribute)attribute; ++ (ALLayoutConstraintAxis)al_constraintAxisForAxis:(ALAxis)axis; +#if PL__PureLayout_MinBaseSDK_iOS_8_0 ++ (ALMargin)al_marginForEdge:(ALEdge)edge; ++ (ALMarginAxis)al_marginAxisForAxis:(ALAxis)axis; +#endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 */ + +@end + +PL__ASSUME_NONNULL_END diff --git a/Pods/PureLayout/PureLayout/PureLayout/PureLayout.h b/Pods/PureLayout/PureLayout/PureLayout/PureLayout.h new file mode 100755 index 00000000..ab615d32 --- /dev/null +++ b/Pods/PureLayout/PureLayout/PureLayout/PureLayout.h @@ -0,0 +1,43 @@ +// +// PureLayout.h +// https://github.com/PureLayout/PureLayout +// +// Copyright (c) 2014-2015 Tyler Fox +// +// This code is distributed under the terms and conditions of the MIT license. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +// + +#ifndef PureLayout_h +#define PureLayout_h + +#import + +//! Project version number for PureLayout. +FOUNDATION_EXPORT double PureLayoutVersionNumber; + +//! Project version string for PureLayout. +FOUNDATION_EXPORT const unsigned char PureLayoutVersionString[]; + +#import "ALView+PureLayout.h" +#import "NSArray+PureLayout.h" +#import "NSLayoutConstraint+PureLayout.h" + +#endif /* PureLayout_h */ diff --git a/Pods/PureLayout/PureLayout/PureLayout/PureLayoutDefines.h b/Pods/PureLayout/PureLayout/PureLayout/PureLayoutDefines.h new file mode 100755 index 00000000..7f740969 --- /dev/null +++ b/Pods/PureLayout/PureLayout/PureLayout/PureLayoutDefines.h @@ -0,0 +1,228 @@ +// +// PureLayoutDefines.h +// https://github.com/PureLayout/PureLayout +// +// Copyright (c) 2014-2015 Tyler Fox +// +// This code is distributed under the terms and conditions of the MIT license. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +// + +#ifndef PureLayoutDefines_h +#define PureLayoutDefines_h + +#import +// check the code in - +// Define some preprocessor macros to check for a minimum Base SDK. These are used to prevent compile-time errors in older versions of Xcode. +#define PL__PureLayout_MinBaseSDK_iOS_8_0 (TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_7_1) +#define PL__PureLayout_MinBaseSDK_iOS_9_0 (TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_8_4) +#define PL__PureLayout_MinBaseSDK_iOS_11_0 (TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_10_3) +#define PL__PureLayout_MinBaseSDK_OSX_10_10 (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MAX_ALLOWED > __MAC_10_9) + +// Define some preprocessor macros to check for a minimum System Version. These are used to prevent runtime crashes on older versions of iOS/OS X. +#define PL__PureLayout_MinSysVer_iOS_7_0 (TARGET_OS_IPHONE && floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) +#define PL__PureLayout_MinSysVer_iOS_8_0 (TARGET_OS_IPHONE && floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_7_1) +#define PL__PureLayout_MinSysVer_iOS_9_0 (TARGET_OS_IPHONE && floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_8_x_Max) +#define PL__PureLayout_MinSysVer_iOS_10_0 (TARGET_OS_IPHONE && floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_9_x_Max) +#define PL__PureLayout_MinSysVer_OSX_10_9 (!TARGET_OS_IPHONE && floor(NSFoundationVersionNumber) > NSFoundationVersionNumber10_8_4) + +// Define some preprocessor macros that allow nullability annotations to be adopted in a backwards-compatible manner. +#if __has_feature(nullability) +# define PL__ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN +# define PL__ASSUME_NONNULL_END NS_ASSUME_NONNULL_END +#else +# define PL__ASSUME_NONNULL_BEGIN +# define PL__ASSUME_NONNULL_END +#endif + +// Define some preprocessor macros that allow generics to be adopted in a backwards-compatible manner. +#if __has_feature(objc_generics) +# define PL__GENERICS(class, ...) class<__VA_ARGS__> +#else +# define PL__GENERICS(class, ...) class +#endif + +// Using generics with NSArray is so common in PureLayout that it gets a dedicated preprocessor macro for better readability. +#define PL__NSArray_of(type) PL__GENERICS(NSArray, type) + +// Define generic AL-prefixed macros for the types/constants/etc that have slight naming variations across iOS and OS X, which allows the same code to be platform-independent. +#if TARGET_OS_IPHONE || TARGET_OS_TV +# import +# define ALView UIView +# define ALEdgeInsets UIEdgeInsets +# define ALEdgeInsetsZero UIEdgeInsetsZero +# define ALEdgeInsetsMake UIEdgeInsetsMake +# define ALLayoutConstraintAxis UILayoutConstraintAxis +# define ALLayoutConstraintOrientation ALLayoutConstraintAxis +# define ALLayoutConstraintAxisHorizontal UILayoutConstraintAxisHorizontal +# define ALLayoutConstraintAxisVertical UILayoutConstraintAxisVertical +# define ALLayoutConstraintOrientationHorizontal ALLayoutConstraintAxisHorizontal +# define ALLayoutConstraintOrientationVertical ALLayoutConstraintAxisVertical +# define ALLayoutPriority UILayoutPriority +# define ALLayoutPriorityRequired UILayoutPriorityRequired +# define ALLayoutPriorityDefaultHigh UILayoutPriorityDefaultHigh +# define ALLayoutPriorityDefaultLow UILayoutPriorityDefaultLow +# define ALLayoutPriorityFittingSizeLevel UILayoutPriorityFittingSizeLevel +# define ALLayoutPriorityFittingSizeCompression ALLayoutPriorityFittingSizeLevel +#else +# import +# define ALView NSView +# define ALEdgeInsets NSEdgeInsets +# define ALEdgeInsetsZero NSEdgeInsetsMake(0, 0, 0, 0) +# define ALEdgeInsetsMake NSEdgeInsetsMake +# define ALLayoutConstraintOrientation NSLayoutConstraintOrientation +# define ALLayoutConstraintAxis ALLayoutConstraintOrientation +# define ALLayoutConstraintOrientationHorizontal NSLayoutConstraintOrientationHorizontal +# define ALLayoutConstraintOrientationVertical NSLayoutConstraintOrientationVertical +# define ALLayoutConstraintAxisHorizontal ALLayoutConstraintOrientationHorizontal +# define ALLayoutConstraintAxisVertical ALLayoutConstraintOrientationVertical +# define ALLayoutPriority NSLayoutPriority +# define ALLayoutPriorityRequired NSLayoutPriorityRequired +# define ALLayoutPriorityDefaultHigh NSLayoutPriorityDefaultHigh +# define ALLayoutPriorityDefaultLow NSLayoutPriorityDefaultLow +# define ALLayoutPriorityFittingSizeCompression NSLayoutPriorityFittingSizeCompression +# define ALLayoutPriorityFittingSizeLevel ALLayoutPriorityFittingSizeCompression +#endif /* TARGET_OS_IPHONE */ + + +#pragma mark PureLayout Attributes + +/** Constants that represent edges of a view. */ +typedef NS_ENUM(NSInteger, ALEdge) { + /** The left edge of the view. */ + ALEdgeLeft = NSLayoutAttributeLeft, + /** The right edge of the view. */ + ALEdgeRight = NSLayoutAttributeRight, + /** The top edge of the view. */ + ALEdgeTop = NSLayoutAttributeTop, + /** The bottom edge of the view. */ + ALEdgeBottom = NSLayoutAttributeBottom, + /** The leading edge of the view (left edge for left-to-right languages like English, right edge for right-to-left languages like Arabic). */ + ALEdgeLeading = NSLayoutAttributeLeading, + /** The trailing edge of the view (right edge for left-to-right languages like English, left edge for right-to-left languages like Arabic). */ + ALEdgeTrailing = NSLayoutAttributeTrailing +}; + +/** Constants that represent dimensions of a view. */ +typedef NS_ENUM(NSInteger, ALDimension) { + /** The width of the view. */ + ALDimensionWidth = NSLayoutAttributeWidth, + /** The height of the view. */ + ALDimensionHeight = NSLayoutAttributeHeight +}; + +/** Constants that represent axes of a view. */ +typedef NS_ENUM(NSInteger, ALAxis) { + /** A vertical line equidistant from the view's left and right edges. */ + ALAxisVertical = NSLayoutAttributeCenterX, + /** A horizontal line equidistant from the view's top and bottom edges. */ + ALAxisHorizontal = NSLayoutAttributeCenterY, + + /** A horizontal line at the baseline of the last line of text in the view. (For views that do not draw text, will be equivalent to ALEdgeBottom.) Same as ALAxisLastBaseline. */ + ALAxisBaseline = NSLayoutAttributeBaseline, + /** A horizontal line at the baseline of the last line of text in the view. (For views that do not draw text, will be equivalent to ALEdgeBottom.) */ + ALAxisLastBaseline = ALAxisBaseline, + #if PL__PureLayout_MinBaseSDK_iOS_8_0 + /** A horizontal line at the baseline of the first line of text in a view. (For views that do not draw text, will be equivalent to ALEdgeTop.) Available in iOS 8.0 and later. */ + ALAxisFirstBaseline = NSLayoutAttributeFirstBaseline + #endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 */ +}; + +#if PL__PureLayout_MinBaseSDK_iOS_8_0 + +/** Constants that represent layout margins of a view. Available in iOS 8.0 and later. */ +typedef NS_ENUM(NSInteger, ALMargin) { + /** The left margin of the view, based on the view's layoutMargins left inset. */ + ALMarginLeft = NSLayoutAttributeLeftMargin, + /** The right margin of the view, based on the view's layoutMargins right inset. */ + ALMarginRight = NSLayoutAttributeRightMargin, + /** The top margin of the view, based on the view's layoutMargins top inset. */ + ALMarginTop = NSLayoutAttributeTopMargin, + /** The bottom margin of the view, based on the view's layoutMargins bottom inset. */ + ALMarginBottom = NSLayoutAttributeBottomMargin, + /** The leading margin of the view, based on the view's layoutMargins left/right (depending on language direction) inset. */ + ALMarginLeading = NSLayoutAttributeLeadingMargin, + /** The trailing margin of the view, based on the view's layoutMargins left/right (depending on language direction) inset. */ + ALMarginTrailing = NSLayoutAttributeTrailingMargin +}; + +/** Constants that represent axes of the layout margins of a view. Available in iOS 8.0 and later. */ +typedef NS_ENUM(NSInteger, ALMarginAxis) { + /** A vertical line equidistant from the view's left and right margins. */ + ALMarginAxisVertical = NSLayoutAttributeCenterXWithinMargins, + /** A horizontal line equidistant from the view's top and bottom margins. */ + ALMarginAxisHorizontal = NSLayoutAttributeCenterYWithinMargins +}; + +#endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 */ + +/** An attribute of a view that can be used in auto layout constraints. These constants are identical to the more specific enum types: + ALEdge, ALAxis, ALDimension, ALMargin, ALMarginAxis. It is safe to cast a more specific enum type to the ALAttribute type. */ +typedef NS_ENUM(NSInteger, ALAttribute) { + /** The left edge of the view. */ + ALAttributeLeft = ALEdgeLeft, + /** The right edge of the view. */ + ALAttributeRight = ALEdgeRight, + /** The top edge of the view. */ + ALAttributeTop = ALEdgeTop, + /** The bottom edge of the view. */ + ALAttributeBottom = ALEdgeBottom, + /** The leading edge of the view (left edge for left-to-right languages like English, right edge for right-to-left languages like Arabic). */ + ALAttributeLeading = ALEdgeLeading, + /** The trailing edge of the view (right edge for left-to-right languages like English, left edge for right-to-left languages like Arabic). */ + ALAttributeTrailing = ALEdgeTrailing, + /** The width of the view. */ + ALAttributeWidth = ALDimensionWidth, + /** The height of the view. */ + ALAttributeHeight = ALDimensionHeight, + /** A vertical line equidistant from the view's left and right edges. */ + ALAttributeVertical = ALAxisVertical, + /** A horizontal line equidistant from the view's top and bottom edges. */ + ALAttributeHorizontal = ALAxisHorizontal, + /** A horizontal line at the baseline of the last line of text in the view. (For views that do not draw text, will be equivalent to ALEdgeBottom.) Same as ALAxisLastBaseline. */ + ALAttributeBaseline = ALAxisBaseline, + /** A horizontal line at the baseline of the last line of text in the view. (For views that do not draw text, will be equivalent to ALEdgeBottom.) */ + ALAttributeLastBaseline = ALAxisLastBaseline, +#if PL__PureLayout_MinBaseSDK_iOS_8_0 + /** A horizontal line at the baseline of the first line of text in a view. (For views that do not draw text, will be equivalent to ALEdgeTop.) Available in iOS 8.0 and later. */ + ALAttributeFirstBaseline = ALAxisFirstBaseline, + /** The left margin of the view, based on the view's layoutMargins left inset. */ + ALAttributeMarginLeft = ALMarginLeft, + /** The right margin of the view, based on the view's layoutMargins right inset. */ + ALAttributeMarginRight = ALMarginRight, + /** The top margin of the view, based on the view's layoutMargins top inset. */ + ALAttributeMarginTop = ALMarginTop, + /** The bottom margin of the view, based on the view's layoutMargins bottom inset. */ + ALAttributeMarginBottom = ALMarginBottom, + /** The leading margin of the view, based on the view's layoutMargins left/right (depending on language direction) inset. */ + ALAttributeMarginLeading = ALMarginLeading, + /** The trailing margin of the view, based on the view's layoutMargins left/right (depending on language direction) inset. */ + ALAttributeMarginTrailing = ALMarginTrailing, + /** A vertical line equidistant from the view's left and right margins. */ + ALAttributeMarginAxisVertical = ALMarginAxisVertical, + /** A horizontal line equidistant from the view's top and bottom margins. */ + ALAttributeMarginAxisHorizontal = ALMarginAxisHorizontal +#endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 */ +}; + +/** A block containing method calls to the PureLayout API. Takes no arguments and has no return value. */ +typedef void(^ALConstraintsBlock)(void); + +#endif /* PureLayoutDefines_h */ diff --git a/Pods/PureLayout/README.md b/Pods/PureLayout/README.md new file mode 100644 index 00000000..99220743 --- /dev/null +++ b/Pods/PureLayout/README.md @@ -0,0 +1,239 @@ +# [![PureLayout](https://github.com/PureLayout/PureLayout/blob/master/Images/PureLayout.png?raw=true)](#) +[![Build Status](https://travis-ci.org/PureLayout/PureLayout.svg?branch=master)](https://travis-ci.org/PureLayout/PureLayout) [![Version](http://img.shields.io/cocoapods/v/PureLayout.svg?style=flat)](http://cocoapods.org/pods/PureLayout) [![Platform](http://img.shields.io/cocoapods/p/PureLayout.svg?style=flat)](http://cocoapods.org/pods/PureLayout) [![License](http://img.shields.io/cocoapods/l/PureLayout.svg?style=flat)](LICENSE) + +The ultimate API for iOS & OS X Auto Layout — impressively simple, immensely powerful. PureLayout extends `UIView`/`NSView`, `NSArray`, and `NSLayoutConstraint` with a comprehensive Auto Layout API that is modeled after Apple's own frameworks. PureLayout is a cross-platform Objective-C library that works (and looks!) great in Swift. It is fully backwards-compatible with all versions of iOS and OS X that support Auto Layout. + +Writing Auto Layout code from scratch isn't easy. PureLayout provides a fully capable and developer-friendly interface for Auto Layout. It is designed for clarity and simplicity, and takes inspiration from the AutoLayout UI options available in Interface Builder while delivering far more flexibility. The API is also highly efficient, as it adds only a thin layer of third party code and is engineered for maximum performance. + +### Table of Contents + 1. [Setup](#setup) + 1. [API Cheat Sheet](#api-cheat-sheet) + 1. [Usage](#usage) + * [Sample Code](#sample-code-swift) + * [Example Apps](#example-apps) + 1. [PureLayout vs. the rest](#purelayout-vs-the-rest) + 1. [Problems, Suggestions, Pull Requests?](#problems-suggestions-pull-requests) + +## Setup +### Compatibility +The current release of PureLayout supports all versions of iOS and OS X since the introduction of Auto Layout on each platform, in both Swift and Objective-C, with a single codebase! + +* Xcode + * Language Support: **Swift** *(any version)*, **Objective-C** + * Fully Compatible With: **Xcode 7.0** + * Minimum Supported Version: **Xcode 5.0** +* iOS + * Fully Compatible With: **iOS 9.0** + * Minimum Deployment Target: **iOS 6.0** +* OS X + * Fully Compatible With: **OS X 10.11** + * Minimum Deployment Target: **OS X 10.7** + +### Using [CocoaPods](http://cocoapods.org) +1. Add the pod `PureLayout` to your [Podfile](http://guides.cocoapods.org/using/the-podfile.html). + + ```ruby + pod 'PureLayout' + ``` + +1. Run `pod install` from Terminal, then open your app's `.xcworkspace` file to launch Xcode. +1. Import the `PureLayout.h` umbrella header. + * With `use_frameworks!` in your Podfile + * Swift: `import PureLayout` + * Objective-C: `#import ` (or with Modules enabled: `@import PureLayout;`) + * Without `use_frameworks!` in your Podfile + * Swift: Add `#import "PureLayout.h"` to your bridging header. + * Objective-C: `#import "PureLayout.h"` + +That's it - now go write some beautiful Auto Layout code! + +### Using [Carthage](https://github.com/Carthage/Carthage) +1. Add the `PureLayout/PureLayout` project to your [Cartfile](https://github.com/Carthage/Carthage/blob/master/Documentation/Artifacts.md#cartfile). + + ```ogdl + github "PureLayout/PureLayout" + ``` + +1. Run `carthage update`, then follow the [additional steps required](https://github.com/Carthage/Carthage#adding-frameworks-to-an-application) to add the framework into your project. +1. Import the PureLayout framework/module. + * Swift: `import PureLayout` + * Objective-C: `#import ` (or with Modules enabled: `@import PureLayout;`) + +That's it - now go write some beautiful Auto Layout code! + +### Manually from GitHub +1. Download the source files in the [PureLayout subdirectory](PureLayout/PureLayout). +1. Add the source files to your Xcode project. +1. Import the `PureLayout.h` header. + * Swift: Add `#import "PureLayout.h"` to your bridging header. + * Objective-C: `#import "PureLayout.h"` + +That's it - now go write some beautiful Auto Layout code! + +### App Extensions +To use PureLayout in an App Extension, you need to do a bit of extra configuration to prevent usage of unavailable APIs. [Click here](https://github.com/PureLayout/PureLayout/wiki/App-Extensions) for more info. + +### Releases +Releases are tagged in the git commit history using [semantic versioning](http://semver.org). Check out the [releases and release notes](https://github.com/PureLayout/PureLayout/releases) for each version. + +## API Cheat Sheet +This is just a handy overview of the core API methods. Explore the [header files](PureLayout/PureLayout) for the full API, and find the complete documentation above the implementation of each method in the corresponding .m file. A couple of notes: + +* All of the public API methods are namespaced with the prefix `auto...`, which also makes it easy for Xcode to autocomplete as you type. +* Methods that create constraints also automatically install (activate) the constraint(s), then return the new constraint(s) for you to optionally store for later adjustment or removal. +* Many methods below also have a variant which includes a `relation:` parameter to make the constraint an inequality. + +### Attributes + +PureLayout defines view attributes that are used to create auto layout constraints. Here is an [illustration of the most common attributes](Images/PureLayout-CommonAttributes.png). + +There are 5 specific attribute types, which are used throughout most of the API: + +* `ALEdge` +* `ALDimension` +* `ALAxis` +* `ALMargin` *available in iOS 8.0 and higher only* +* `ALMarginAxis` *available in iOS 8.0 and higher only* + +Additionally, there is one generic attribute type, `ALAttribute`, which is effectively a union of all the specific types. You can think of this as the "supertype" of all of the specific attribute types, which means that it is always safe to cast a specific type to the generic `ALAttribute` type. (Note that the reverse is not true -- casting a generic ALAttribute to a specific attribute type is unsafe!) + +### [`UIView`/`NSView`](PureLayout/PureLayout/ALView%2BPureLayout.h) +``` +- autoSetContent(CompressionResistance|Hugging)PriorityForAxis: +- autoCenterInSuperview(Margins) // Margins variant iOS 8.0+ only +- autoAlignAxisToSuperview(Margin)Axis: // Margin variant iOS 8.0+ only +- autoPinEdgeToSuperview(Edge:|Margin:)(withInset:) // Margin variant iOS 8.0+ only +- autoPinEdgesToSuperview(Edges|Margins)(WithInsets:)(excludingEdge:) // Margins variant iOS 8.0+ only +- autoPinEdge:toEdge:ofView:(withOffset:) +- autoAlignAxis:toSameAxisOfView:(withOffset:|withMultiplier:) +- autoMatchDimension:toDimension:ofView:(withOffset:|withMultiplier:) +- autoSetDimension(s)ToSize: +- autoConstrainAttribute:toAttribute:ofView:(withOffset:|withMultiplier:) +- autoPinTo(Top|Bottom)LayoutGuideOfViewController:withInset: // iOS only +- autoPinEdgeToSuperviewSafeArea: // iOS 11.0+ only +- autoPinEdgeToSuperviewSafeArea:withInset: // iOS 11.0+ only +``` + +### [`NSArray`](PureLayout/PureLayout/NSArray%2BPureLayout.h) +``` +// Arrays of Constraints +- autoInstallConstraints +- autoRemoveConstraints +- autoIdentifyConstraints: // iOS 7.0+, OS X 10.9+ only + +// Arrays of Views +- autoAlignViewsToEdge: +- autoAlignViewsToAxis: +- autoMatchViewsDimension: +- autoSetViewsDimension:toSize: +- autoSetViewsDimensionsToSize: +- autoDistributeViewsAlongAxis:alignedTo:withFixedSpacing:(insetSpacing:)(matchedSizes:) +- autoDistributeViewsAlongAxis:alignedTo:withFixedSize:(insetSpacing:) +``` + +### [`NSLayoutConstraint`](PureLayout/PureLayout/NSLayoutConstraint%2BPureLayout.h) +``` ++ autoCreateAndInstallConstraints: ++ autoCreateConstraintsWithoutInstalling: ++ autoSetPriority:forConstraints: ++ autoSetIdentifier:forConstraints: // iOS 7.0+, OS X 10.9+ only +- autoIdentify: // iOS 7.0+, OS X 10.9+ only +- autoInstall +- autoRemove +``` + +## Usage +### Sample Code (Swift) +PureLayout dramatically simplifies writing Auto Layout code. Let's take a quick look at some examples, using PureLayout from Swift. + +Initialize the view using PureLayout initializer: + +```swift +let view1 = UIView(forAutoLayout: ()) +``` + +If you need to use a different initializer (e.g. in `UIView` subclass), you can also use `configureForAutoLayout`: + +``` +view1.configureForAutoLayout() // alternative to UIView.init(forAutoLayout: ()) +``` + +Here's a constraint between two views created (and automatically activated) using PureLayout: + +```swift +view1.autoPinEdge(.top, toEdge: .bottom, ofView: view2) +``` + +Without PureLayout, here's the equivalent code you'd have to write using Apple's Foundation API directly: + +```swift +NSLayoutConstraint(item: view1, attribute: .top, relatedBy: .equal, toItem: view2, attribute: .bottom, multiplier: 1.0, constant: 0.0).active = true +``` + +Many APIs of PureLayout create multiple constraints for you under the hood, letting you write highly readable layout code: + +```swift +// 2 constraints created & activated in one line! +logoImageView.autoCenterInSuperview() + +// 4 constraints created & activated in one line! +textContentView.autoPinEdgesToSuperviewEdges(with insets: UIEdgeInsets(top: 20.0, left: 5.0, bottom: 10.0, right: 5.0)) +``` + +PureLayout always returns the constraints it creates so you have full control: + +```swift +let constraint = skinnyView.autoMatchDimension(.height, toDimension: .width, ofView: tallView) +``` + +PureLayout supports safearea with iOS 11.0+: + +```swift +view2.autoPinEdge(toSuperviewSafeArea: .top) +``` + +PureLayout supports all Auto Layout features including inequalities, priorities, layout margins, identifiers, and much more. It's a comprehensive, developer-friendly way to use Auto Layout. + +Check out the example apps below for many more demos of PureLayout in use. + +### Example Apps +Open the project included in the repository (requires Xcode 6 or higher). It contains [iOS](PureLayout/Example-iOS) (`Example-iOS` scheme) and [OS X](PureLayout/Example-Mac) (`Example-Mac` scheme) demos of the library being used in various scenarios. The demos in the iOS example app make a great introductory tutorial to PureLayout -- run each demo, review the code used to implement it, then practice by making some changes of your own to the demo code. + +Each demo in the iOS example app has a Swift and Objective-C version. **To compile & run the Swift demos, you must use Xcode 7.0 or higher (Swift 2.0) and choose the `Example-iOS-Xcode7` scheme.** When you run the example app, you can easily switch between using the Swift and Objective-C versions of the demos. To see the constraints in action while running the iOS demos, try using different device simulators, rotating the device to different orientations, as well as toggling the taller in-call status bar in the iOS Simulator. + +On OS X, while running the app, press any key to cycle through the demos. You can resize the window to see the constraints in action. + +### Tips and Tricks +Check out some [Tips and Tricks](https://github.com/PureLayout/PureLayout/wiki/Tips-and-Tricks) to keep in mind when using the API. + +## PureLayout vs. the rest +There are quite a few different ways to implement Auto Layout. Here is a quick overview of the available options: + +* Apple [NSLayoutConstraint SDK API](https://developer.apple.com/library/ios/documentation/AppKit/Reference/NSLayoutConstraint_Class/index.html#//apple_ref/occ/clm/NSLayoutConstraint/constraintWithItem:attribute:relatedBy:toItem:attribute:multiplier:constant:) + * Pros: Raw power + * Cons: Extremely verbose; tedious to write; difficult to read +* Apple [Visual Format Language](https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/AutolayoutPG/VisualFormatLanguage.html) + * Pros: Concise; convenient + * Cons: Doesn't support some use cases; lacks compile-time checking and safety; must learn syntax; hard to debug +* Apple Interface Builder + * Pros: Visual; interactive; provides compile-time layout checking + * Cons: Difficult for complex layouts; cannot dynamically set constraints at runtime; encourages hardcoded magic numbers; not always WYSIWYG +* Apple [NSLayoutAnchor SDK API](https://developer.apple.com/library/prerelease/ios/documentation/AppKit/Reference/NSLayoutAnchor_ClassReference/index.html) + * Pros: Clean, readable, and type-safe API for creating individual constraints + * Cons: Only available in iOS 9.0 and OS X 10.11 and higher; requires manually activating each constraint; no API for creating multiple constraints at once +* **PureLayout** + * Pros: Compatible with Objective-C and Swift codebases; consistent with Cocoa API style; cross-platform API and implementation shared across iOS and OS X; fully backwards-compatible to iOS 6 & OS X 10.7; easy to use; type-safe; efficient + * Cons: Not the most concise expression of layout code +* High-level Auto Layout Libraries/DSLs ([Cartography](https://github.com/robb/Cartography), [SnapKit](https://github.com/SnapKit/SnapKit), [KeepLayout](https://github.com/iMartinKiss/KeepLayout)) + * Pros: Very clean, concise, and convenient + * Cons: Unique API style is foreign to Apple's APIs; mixed compatibility with Objective-C & Swift; greater dependency on third party code + +PureLayout takes a balanced approach to Auto Layout that makes it well suited for any project. + +## Problems, Suggestions, Pull Requests? +Please open a [new Issue here](https://github.com/PureLayout/PureLayout/issues/new) if you run into a problem specific to PureLayout, have a feature request, or want to share a comment. Note that general Auto Layout questions should be asked on [Stack Overflow](http://stackoverflow.com). + +Pull requests are encouraged and greatly appreciated! Please try to maintain consistency with the existing code style. If you're considering taking on significant changes or additions to the project, please communicate in advance by opening a new Issue. This allows everyone to get onboard with upcoming changes, ensures that changes align with the project's design philosophy, and avoids duplicated work. + +## Meta +Originally designed & built by Tyler Fox ([@smileyborg](https://github.com/smileyborg)). Currently maintained by Mickey Reiss ([@mickeyreiss](https://github.com/mickeyreiss)). Distributed with the MIT license. diff --git a/Pods/SVProgressHUD/LICENSE b/Pods/SVProgressHUD/LICENSE new file mode 100644 index 00000000..f8c911ba --- /dev/null +++ b/Pods/SVProgressHUD/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2011-2018 Sam Vermette, Tobias Tiemerding and contributors. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Pods/SVProgressHUD/README.md b/Pods/SVProgressHUD/README.md new file mode 100644 index 00000000..a9ce9e0d --- /dev/null +++ b/Pods/SVProgressHUD/README.md @@ -0,0 +1,218 @@ +# SVProgressHUD + +![Pod Version](https://img.shields.io/cocoapods/v/SVProgressHUD.svg?style=flat) +![Pod Platform](https://img.shields.io/cocoapods/p/SVProgressHUD.svg?style=flat) +![Pod License](https://img.shields.io/cocoapods/l/SVProgressHUD.svg?style=flat) +[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-green.svg?style=flat)](https://github.com/Carthage/Carthage) +[![CocoaPods compatible](https://img.shields.io/badge/CocoaPods-compatible-green.svg?style=flat)](https://cocoapods.org) + +`SVProgressHUD` is a clean and easy-to-use HUD meant to display the progress of an ongoing task on iOS and tvOS. + +![SVProgressHUD](http://f.cl.ly/items/2G1F1Z0M0k0h2U3V1p39/SVProgressHUD.gif) + +## Demo + +Try `SVProgressHUD` on [Appetize.io](https://appetize.io/app/p8r2cvy8kq74x7q7tjqf5gyatr). + +## Installation + +### From CocoaPods + +[CocoaPods](http://cocoapods.org) is a dependency manager for Objective-C, which automates and simplifies the process of using 3rd-party libraries like `SVProgressHUD` in your projects. First, add the following line to your [Podfile](http://guides.cocoapods.org/using/using-cocoapods.html): + +```ruby +pod 'SVProgressHUD' +``` + +If you want to use the latest features of `SVProgressHUD` use normal external source dependencies. + +```ruby +pod 'SVProgressHUD', :git => 'https://github.com/SVProgressHUD/SVProgressHUD.git' +``` + +This pulls from the `master` branch directly. + +Second, install `SVProgressHUD` into your project: + +```ruby +pod install +``` + +### Carthage + +[Carthage](https://github.com/Carthage/Carthage) is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks. To integrate `SVProgressHUD` into your Xcode project using Carthage, specify it in your `Cartfile`: + +```ogdl +github "SVProgressHUD/SVProgressHUD" +``` + +Run `carthage bootstrap` to build the framework in your repository's Carthage directory. You can then include it in your target's `carthage copy-frameworks` build phase. For more information on this, please see [Carthage's documentation](https://github.com/carthage/carthage#if-youre-building-for-ios-tvos-or-watchos). + +### Manually + +* Drag the `SVProgressHUD/SVProgressHUD` folder into your project. +* Take care that `SVProgressHUD.bundle` is added to `Targets->Build Phases->Copy Bundle Resources`. +* Add the **QuartzCore** framework to your project. + +## Swift + +Even though `SVProgressHUD` is written in Objective-C, it can be used in Swift with no hassle. If you use [CocoaPods](http://cocoapods.org) add the following line to your [Podfile](http://guides.cocoapods.org/using/using-cocoapods.html): + +```ruby +use_frameworks! +``` + +If you added `SVProgressHUD` manually, just add a [bridging header](https://developer.apple.com/library/content/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html) file to your project with the `SVProgressHUD` header included. + +## Usage + +(see sample Xcode project in `/Demo`) + +`SVProgressHUD` is created as a singleton (i.e. it doesn't need to be explicitly allocated and instantiated; you directly call `[SVProgressHUD method]`). + +**Use `SVProgressHUD` wisely! Only use it if you absolutely need to perform a task before taking the user forward. Bad use case examples: pull to refresh, infinite scrolling, sending message.** + +Using `SVProgressHUD` in your app will usually look as simple as this (using Grand Central Dispatch): + +```objective-c +[SVProgressHUD show]; +dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + // time-consuming task + dispatch_async(dispatch_get_main_queue(), ^{ + [SVProgressHUD dismiss]; + }); +}); +``` + +### Showing the HUD + +You can show the status of indeterminate tasks using one of the following: + +```objective-c ++ (void)show; ++ (void)showWithStatus:(NSString*)string; +``` + +If you'd like the HUD to reflect the progress of a task, use one of these: + +```objective-c ++ (void)showProgress:(CGFloat)progress; ++ (void)showProgress:(CGFloat)progress status:(NSString*)status; +``` + +### Dismissing the HUD + +The HUD can be dismissed using: + +```objective-c ++ (void)dismiss; ++ (void)dismissWithDelay:(NSTimeInterval)delay; +``` + +If you'd like to stack HUDs, you can balance out every show call using: + +``` ++ (void)popActivity; +``` + +The HUD will get dismissed once the popActivity calls will match the number of show calls. + +Or show a confirmation glyph before before getting dismissed a little bit later. The display time depends on `minimumDismissTimeInterval` and the length of the given string. + +```objective-c ++ (void)showInfoWithStatus:(NSString*)string; ++ (void)showSuccessWithStatus:(NSString*)string; ++ (void)showErrorWithStatus:(NSString*)string; ++ (void)showImage:(UIImage*)image status:(NSString*)string; +``` + +## Customization + +`SVProgressHUD` can be customized via the following methods: + +```objective-c ++ (void)setDefaultStyle:(SVProgressHUDStyle)style; // default is SVProgressHUDStyleLight ++ (void)setDefaultMaskType:(SVProgressHUDMaskType)maskType; // default is SVProgressHUDMaskTypeNone ++ (void)setDefaultAnimationType:(SVProgressHUDAnimationType)type; // default is SVProgressHUDAnimationTypeFlat ++ (void)setContainerView:(UIView*)containerView; // default is window level ++ (void)setMinimumSize:(CGSize)minimumSize; // default is CGSizeZero, can be used to avoid resizing ++ (void)setRingThickness:(CGFloat)width; // default is 2 pt ++ (void)setRingRadius:(CGFloat)radius; // default is 18 pt ++ (void)setRingNoTextRadius:(CGFloat)radius; // default is 24 pt ++ (void)setCornerRadius:(CGFloat)cornerRadius; // default is 14 pt ++ (void)setBorderColor:(nonnull UIColor*)color; // default is nil ++ (void)setBorderWidth:(CGFloat)width; // default is 0 ++ (void)setFont:(UIFont*)font; // default is [UIFont preferredFontForTextStyle:UIFontTextStyleSubheadline] ++ (void)setForegroundColor:(UIColor*)color; // default is [UIColor blackColor], only used for SVProgressHUDStyleCustom ++ (void)setBackgroundColor:(UIColor*)color; // default is [UIColor whiteColor], only used for SVProgressHUDStyleCustom ++ (void)setBackgroundLayerColor:(UIColor*)color; // default is [UIColor colorWithWhite:0 alpha:0.4], only used for SVProgressHUDMaskTypeCustom ++ (void)setImageViewSize:(CGSize)size; // default is 28x28 pt ++ (void)setShouldTintImages:(BOOL)shouldTintImages; // default is YES ++ (void)setInfoImage:(UIImage*)image; // default is the bundled info image provided by Freepik ++ (void)setSuccessImage:(UIImage*)image; // default is bundled success image from Freepik ++ (void)setErrorImage:(UIImage*)image; // default is bundled error image from Freepik ++ (void)setViewForExtension:(UIView*)view; // default is nil, only used if #define SV_APP_EXTENSIONS is set ++ (void)setGraceTimeInterval:(NSTimeInterval)interval; // default is 0 seconds ++ (void)setMinimumDismissTimeInterval:(NSTimeInterval)interval; // default is 5.0 seconds ++ (void)setMaximumDismissTimeInterval:(NSTimeInterval)interval; // default is CGFLOAT_MAX ++ (void)setFadeInAnimationDuration:(NSTimeInterval)duration; // default is 0.15 seconds ++ (void)setFadeOutAnimationDuration:(NSTimeInterval)duration; // default is 0.15 seconds ++ (void)setMaxSupportedWindowLevel:(UIWindowLevel)windowLevel; // default is UIWindowLevelNormal ++ (void)setHapticsEnabled:(BOOL)hapticsEnabled; // default is NO +``` + +Additionally `SVProgressHUD` supports the `UIAppearance` protocol for most of the above methods. + +### Hint + +As standard `SVProgressHUD` offers two preconfigured styles: + +* `SVProgressHUDStyleLight`: White background with black spinner and text +* `SVProgressHUDStyleDark`: Black background with white spinner and text + +If you want to use custom colors use `setForegroundColor` and `setBackgroundColor:`. These implicitly set the HUD's style to `SVProgressHUDStyleCustom`. + +## Haptic Feedback + +For users with newer devices (starting with the iPhone 7), `SVProgressHUD` can automatically trigger haptic feedback depending on which HUD is being displayed. The feedback maps as follows: + +* `showSuccessWithStatus:` <-> `UINotificationFeedbackTypeSuccess` +* `showInfoWithStatus:` <-> `UINotificationFeedbackTypeWarning` +* `showErrorWithStatus:` <-> `UINotificationFeedbackTypeError` + +To enable this functionality, use `setHapticsEnabled:`. + +Users with devices prior to iPhone 7 will have no change in functionality. + +## Notifications + +`SVProgressHUD` posts four notifications via `NSNotificationCenter` in response to being shown/dismissed: +* `SVProgressHUDWillAppearNotification` when the show animation starts +* `SVProgressHUDDidAppearNotification` when the show animation completes +* `SVProgressHUDWillDisappearNotification` when the dismiss animation starts +* `SVProgressHUDDidDisappearNotification` when the dismiss animation completes + +Each notification passes a `userInfo` dictionary holding the HUD's status string (if any), retrievable via `SVProgressHUDStatusUserInfoKey`. + +`SVProgressHUD` also posts `SVProgressHUDDidReceiveTouchEventNotification` when users touch on the overall screen or `SVProgressHUDDidTouchDownInsideNotification` when a user touches on the HUD directly. For this notifications `userInfo` is not passed but the object parameter contains the `UIEvent` that related to the touch. + +## App Extensions + +When using `SVProgressHUD` in an App Extension, `#define SV_APP_EXTENSIONS` to avoid using unavailable APIs. Additionally call `setViewForExtension:` from your extensions view controller with `self.view`. + +## Contributing to this project + +If you have feature requests or bug reports, feel free to help out by sending pull requests or by [creating new issues](https://github.com/SVProgressHUD/SVProgressHUD/issues/new). Please take a moment to +review the guidelines written by [Nicolas Gallagher](https://github.com/necolas): + +* [Bug reports](https://github.com/necolas/issue-guidelines/blob/master/CONTRIBUTING.md#bugs) +* [Feature requests](https://github.com/necolas/issue-guidelines/blob/master/CONTRIBUTING.md#features) +* [Pull requests](https://github.com/necolas/issue-guidelines/blob/master/CONTRIBUTING.md#pull-requests) + +## License + +`SVProgressHUD` is distributed under the terms and conditions of the [MIT license](https://github.com/SVProgressHUD/SVProgressHUD/blob/master/LICENSE.txt). The success, error and info icons are made by [Freepik](http://www.freepik.com) from [Flaticon](http://www.flaticon.com) and are licensed under [Creative Commons BY 3.0](http://creativecommons.org/licenses/by/3.0/). + +## Credits + +`SVProgressHUD` is brought to you by [Sam Vermette](http://samvermette.com), [Tobias Tiemerding](http://tiemerding.com) and [contributors to the project](https://github.com/SVProgressHUD/SVProgressHUD/contributors). If you're using `SVProgressHUD` in your project, attribution would be very appreciated. diff --git a/Pods/SVProgressHUD/SVProgressHUD/SVIndefiniteAnimatedView.h b/Pods/SVProgressHUD/SVProgressHUD/SVIndefiniteAnimatedView.h new file mode 100644 index 00000000..b624dd0b --- /dev/null +++ b/Pods/SVProgressHUD/SVProgressHUD/SVIndefiniteAnimatedView.h @@ -0,0 +1,17 @@ +// +// SVIndefiniteAnimatedView.h +// SVProgressHUD, https://github.com/SVProgressHUD/SVProgressHUD +// +// Copyright (c) 2014-2018 Guillaume Campagna. All rights reserved. +// + +#import + +@interface SVIndefiniteAnimatedView : UIView + +@property (nonatomic, assign) CGFloat strokeThickness; +@property (nonatomic, assign) CGFloat radius; +@property (nonatomic, strong) UIColor *strokeColor; + +@end + diff --git a/Pods/SVProgressHUD/SVProgressHUD/SVIndefiniteAnimatedView.m b/Pods/SVProgressHUD/SVProgressHUD/SVIndefiniteAnimatedView.m new file mode 100644 index 00000000..09a38d0b --- /dev/null +++ b/Pods/SVProgressHUD/SVProgressHUD/SVIndefiniteAnimatedView.m @@ -0,0 +1,137 @@ +// +// SVIndefiniteAnimatedView.m +// SVProgressHUD, https://github.com/SVProgressHUD/SVProgressHUD +// +// Copyright (c) 2014-2018 Guillaume Campagna. All rights reserved. +// + +#import "SVIndefiniteAnimatedView.h" +#import "SVProgressHUD.h" + +@interface SVIndefiniteAnimatedView () + +@property (nonatomic, strong) CAShapeLayer *indefiniteAnimatedLayer; + +@end + +@implementation SVIndefiniteAnimatedView + +- (void)willMoveToSuperview:(UIView*)newSuperview { + if (newSuperview) { + [self layoutAnimatedLayer]; + } else { + [_indefiniteAnimatedLayer removeFromSuperlayer]; + _indefiniteAnimatedLayer = nil; + } +} + +- (void)layoutAnimatedLayer { + CALayer *layer = self.indefiniteAnimatedLayer; + [self.layer addSublayer:layer]; + + CGFloat widthDiff = CGRectGetWidth(self.bounds) - CGRectGetWidth(layer.bounds); + CGFloat heightDiff = CGRectGetHeight(self.bounds) - CGRectGetHeight(layer.bounds); + layer.position = CGPointMake(CGRectGetWidth(self.bounds) - CGRectGetWidth(layer.bounds) / 2 - widthDiff / 2, CGRectGetHeight(self.bounds) - CGRectGetHeight(layer.bounds) / 2 - heightDiff / 2); +} + +- (CAShapeLayer*)indefiniteAnimatedLayer { + if(!_indefiniteAnimatedLayer) { + CGPoint arcCenter = CGPointMake(self.radius+self.strokeThickness/2+5, self.radius+self.strokeThickness/2+5); + UIBezierPath* smoothedPath = [UIBezierPath bezierPathWithArcCenter:arcCenter radius:self.radius startAngle:(CGFloat) (M_PI*3/2) endAngle:(CGFloat) (M_PI/2+M_PI*5) clockwise:YES]; + + _indefiniteAnimatedLayer = [CAShapeLayer layer]; + _indefiniteAnimatedLayer.contentsScale = [[UIScreen mainScreen] scale]; + _indefiniteAnimatedLayer.frame = CGRectMake(0.0f, 0.0f, arcCenter.x*2, arcCenter.y*2); + _indefiniteAnimatedLayer.fillColor = [UIColor clearColor].CGColor; + _indefiniteAnimatedLayer.strokeColor = self.strokeColor.CGColor; + _indefiniteAnimatedLayer.lineWidth = self.strokeThickness; + _indefiniteAnimatedLayer.lineCap = kCALineCapRound; + _indefiniteAnimatedLayer.lineJoin = kCALineJoinBevel; + _indefiniteAnimatedLayer.path = smoothedPath.CGPath; + + CALayer *maskLayer = [CALayer layer]; + + NSBundle *bundle = [NSBundle bundleForClass:[SVProgressHUD class]]; + NSURL *url = [bundle URLForResource:@"SVProgressHUD" withExtension:@"bundle"]; + NSBundle *imageBundle = [NSBundle bundleWithURL:url]; + + NSString *path = [imageBundle pathForResource:@"angle-mask" ofType:@"png"]; + + maskLayer.contents = (__bridge id)[[UIImage imageWithContentsOfFile:path] CGImage]; + maskLayer.frame = _indefiniteAnimatedLayer.bounds; + _indefiniteAnimatedLayer.mask = maskLayer; + + NSTimeInterval animationDuration = 1; + CAMediaTimingFunction *linearCurve = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]; + + CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"]; + animation.fromValue = (id) 0; + animation.toValue = @(M_PI*2); + animation.duration = animationDuration; + animation.timingFunction = linearCurve; + animation.removedOnCompletion = NO; + animation.repeatCount = INFINITY; + animation.fillMode = kCAFillModeForwards; + animation.autoreverses = NO; + [_indefiniteAnimatedLayer.mask addAnimation:animation forKey:@"rotate"]; + + CAAnimationGroup *animationGroup = [CAAnimationGroup animation]; + animationGroup.duration = animationDuration; + animationGroup.repeatCount = INFINITY; + animationGroup.removedOnCompletion = NO; + animationGroup.timingFunction = linearCurve; + + CABasicAnimation *strokeStartAnimation = [CABasicAnimation animationWithKeyPath:@"strokeStart"]; + strokeStartAnimation.fromValue = @0.015; + strokeStartAnimation.toValue = @0.515; + + CABasicAnimation *strokeEndAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"]; + strokeEndAnimation.fromValue = @0.485; + strokeEndAnimation.toValue = @0.985; + + animationGroup.animations = @[strokeStartAnimation, strokeEndAnimation]; + [_indefiniteAnimatedLayer addAnimation:animationGroup forKey:@"progress"]; + + } + return _indefiniteAnimatedLayer; +} + +- (void)setFrame:(CGRect)frame { + if(!CGRectEqualToRect(frame, super.frame)) { + [super setFrame:frame]; + + if(self.superview) { + [self layoutAnimatedLayer]; + } + } + +} + +- (void)setRadius:(CGFloat)radius { + if(radius != _radius) { + _radius = radius; + + [_indefiniteAnimatedLayer removeFromSuperlayer]; + _indefiniteAnimatedLayer = nil; + + if(self.superview) { + [self layoutAnimatedLayer]; + } + } +} + +- (void)setStrokeColor:(UIColor*)strokeColor { + _strokeColor = strokeColor; + _indefiniteAnimatedLayer.strokeColor = strokeColor.CGColor; +} + +- (void)setStrokeThickness:(CGFloat)strokeThickness { + _strokeThickness = strokeThickness; + _indefiniteAnimatedLayer.lineWidth = _strokeThickness; +} + +- (CGSize)sizeThatFits:(CGSize)size { + return CGSizeMake((self.radius+self.strokeThickness/2+5)*2, (self.radius+self.strokeThickness/2+5)*2); +} + +@end diff --git a/Pods/SVProgressHUD/SVProgressHUD/SVProgressAnimatedView.h b/Pods/SVProgressHUD/SVProgressHUD/SVProgressAnimatedView.h new file mode 100644 index 00000000..6de23b43 --- /dev/null +++ b/Pods/SVProgressHUD/SVProgressHUD/SVProgressAnimatedView.h @@ -0,0 +1,17 @@ +// +// SVProgressAnimatedView.h +// SVProgressHUD, https://github.com/SVProgressHUD/SVProgressHUD +// +// Copyright (c) 2017-2018 Tobias Tiemerding. All rights reserved. +// + +#import + +@interface SVProgressAnimatedView : UIView + +@property (nonatomic, assign) CGFloat radius; +@property (nonatomic, assign) CGFloat strokeThickness; +@property (nonatomic, strong) UIColor *strokeColor; +@property (nonatomic, assign) CGFloat strokeEnd; + +@end diff --git a/Pods/SVProgressHUD/SVProgressHUD/SVProgressAnimatedView.m b/Pods/SVProgressHUD/SVProgressHUD/SVProgressAnimatedView.m new file mode 100644 index 00000000..a347c85d --- /dev/null +++ b/Pods/SVProgressHUD/SVProgressHUD/SVProgressAnimatedView.m @@ -0,0 +1,96 @@ +// +// SVProgressAnimatedView.m +// SVProgressHUD, https://github.com/SVProgressHUD/SVProgressHUD +// +// Copyright (c) 2017-2018 Tobias Tiemerding. All rights reserved. +// + +#import "SVProgressAnimatedView.h" + +@interface SVProgressAnimatedView () + +@property (nonatomic, strong) CAShapeLayer *ringAnimatedLayer; + +@end + +@implementation SVProgressAnimatedView + +- (void)willMoveToSuperview:(UIView*)newSuperview { + if (newSuperview) { + [self layoutAnimatedLayer]; + } else { + [_ringAnimatedLayer removeFromSuperlayer]; + _ringAnimatedLayer = nil; + } +} + +- (void)layoutAnimatedLayer { + CALayer *layer = self.ringAnimatedLayer; + [self.layer addSublayer:layer]; + + CGFloat widthDiff = CGRectGetWidth(self.bounds) - CGRectGetWidth(layer.bounds); + CGFloat heightDiff = CGRectGetHeight(self.bounds) - CGRectGetHeight(layer.bounds); + layer.position = CGPointMake(CGRectGetWidth(self.bounds) - CGRectGetWidth(layer.bounds) / 2 - widthDiff / 2, CGRectGetHeight(self.bounds) - CGRectGetHeight(layer.bounds) / 2 - heightDiff / 2); +} + +- (CAShapeLayer*)ringAnimatedLayer { + if(!_ringAnimatedLayer) { + CGPoint arcCenter = CGPointMake(self.radius+self.strokeThickness/2+5, self.radius+self.strokeThickness/2+5); + UIBezierPath* smoothedPath = [UIBezierPath bezierPathWithArcCenter:arcCenter radius:self.radius startAngle:(CGFloat)-M_PI_2 endAngle:(CGFloat) (M_PI + M_PI_2) clockwise:YES]; + + _ringAnimatedLayer = [CAShapeLayer layer]; + _ringAnimatedLayer.contentsScale = [[UIScreen mainScreen] scale]; + _ringAnimatedLayer.frame = CGRectMake(0.0f, 0.0f, arcCenter.x*2, arcCenter.y*2); + _ringAnimatedLayer.fillColor = [UIColor clearColor].CGColor; + _ringAnimatedLayer.strokeColor = self.strokeColor.CGColor; + _ringAnimatedLayer.lineWidth = self.strokeThickness; + _ringAnimatedLayer.lineCap = kCALineCapRound; + _ringAnimatedLayer.lineJoin = kCALineJoinBevel; + _ringAnimatedLayer.path = smoothedPath.CGPath; + } + return _ringAnimatedLayer; +} + +- (void)setFrame:(CGRect)frame { + if(!CGRectEqualToRect(frame, super.frame)) { + [super setFrame:frame]; + + if(self.superview) { + [self layoutAnimatedLayer]; + } + } +} + +- (void)setRadius:(CGFloat)radius { + if(radius != _radius) { + _radius = radius; + + [_ringAnimatedLayer removeFromSuperlayer]; + _ringAnimatedLayer = nil; + + if(self.superview) { + [self layoutAnimatedLayer]; + } + } +} + +- (void)setStrokeColor:(UIColor*)strokeColor { + _strokeColor = strokeColor; + _ringAnimatedLayer.strokeColor = strokeColor.CGColor; +} + +- (void)setStrokeThickness:(CGFloat)strokeThickness { + _strokeThickness = strokeThickness; + _ringAnimatedLayer.lineWidth = _strokeThickness; +} + +- (void)setStrokeEnd:(CGFloat)strokeEnd { + _strokeEnd = strokeEnd; + _ringAnimatedLayer.strokeEnd = _strokeEnd; +} + +- (CGSize)sizeThatFits:(CGSize)size { + return CGSizeMake((self.radius+self.strokeThickness/2+5)*2, (self.radius+self.strokeThickness/2+5)*2); +} + +@end diff --git a/Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.bundle/angle-mask.png b/Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.bundle/angle-mask.png new file mode 100644 index 0000000000000000000000000000000000000000..0150a03f535237397e5c16fbd4e96f79886889e0 GIT binary patch literal 1845 zcmV-52g>+~P)?Y5Wzn1U?G1701yYx!s6Oq#x>prVMm=a4v)>}Y)( zM3?vNL$ae)iEOPl7DBdDD^1^QJBxIyTg{~)X%@?KSe{&-OFmbOv$%1hO``&7JSne+hQz+Y=u&gJdv0YKtf8M$mfd_$ruiaC`%Lh z+!sSe02o3tP(blSJ{u;IJfr-Mx4DzOH+YT>68UV9NLU#-k0JcYpj!Svkx!8k7rD)F z1(5MoTJ#%~g1~ZI9k3Z#-HG3sRSN91>64lQ#u5ZT7GM%eK}L-DSTO=21G3L?vCoNo z%#19L0l?RHl6U2qaIt?BFw#7{y#1A(!K*={AyJ4+~H`wUl%b3DX=Xg0Ephp3`W4% zbWv^T;o=5}9Y%3ma>`bFkh_5GU*zW|tvU8w}u`HoY-m2)+vX z2F0`3>%B&!Q67R0d*JJ)*ZqYd3QHd-y*Xol>NChP32Fn55%0I@HD8PvLb(I9O8S$_N>fIz$5qV<;JKb0U?)!2~$0aq4?>wP2A4B|UMVC*pQt4sdZ^x}d~t?_=o>b=_8)QmU89@AU07{xjX3POJ55b$Mr24r_X0__p;J;0$Z4VodEs zNBUcTOo(5m@$c#Gq}J+$Pm4qPOTvS=r8@LKc?}Yg4Fu_ z9)oOfU>@$X>ACp$*lZmcb*$=OP3>R(JrVw%+P`&Q>y-&pyfcRPS&(O?u^cn7J~yk4 z4mp|Hv5xfb)c%?Jk&bJvL#$T(h;iivyK8zzW5}8-!bd~QdGtgIQk0|4C`eDlGwB%k zR>3%cJRPPm%%W2O(kaI?10bD|<+2_@o(c*&W2`&EAT#B}88f81Cz4ZOE=W++8N>7N zOlqtm_dGn4oHB$w$q@Ls{R4)0A|28(hUgGW#2`q4U5Fu1u#@wcM=$aL#4s~r0GT$62-Ajm#4+TdHQdv)c-dFP#q!An~*pv4TA)l?q5XQhgAQA|2 z?5TCnAP;~9hYOM+1Rtyb!o{w;2@&N1nRqTR+e(rLQ@A(XwIGj#GJxcaJd=Vf$RnU2 zD5#Er!jL_HD@HxE@v=_ z33jI?l%`uG4s1ce6JtPIR_J_!3Sx`QAVki|35-c71-W_f;AMnD1ViW@3}B47=nFy& zWd|z<#Q^3oz!T9;0VC(E2G_8f5fVy4AgDMK!KOk8tSHTciv30`bmfU~GJKDBc_PE# zksCG`phtoNM34gk00E=-f{YW%OFmC%d6^FqxgHon!EYOq7dlf4k|zSuZxtfAixasn jO$6o~vM95Mta|72R_?8} zTa>WE@>@SWuyqfFd8k$``VWsjdr&=U4KR#S!V!oU5|3rjT1{{_s$lqZN*ujHtVlff zNA3O@jC;AiW)(QbKr~2vgWR^KhHH6MTfir_2KkhKP-Bz2w}JTSB)N4D#1={ZuC04~ zFzw&oiKf1E1mcTiy}gqMa=iuyTvS9)PTa#AaHpfUJ=x;H5DTPrLH* z?AAb9W}5O+kWU)5f}Ts`4WzAJOl{&Gh);L!RZ9isW7<6Hy77LfvOc*dwZT6otO&oM zP6i%Qe0=C>7zU8V4{zK6V`@S~PMm0J(14IsjSIuG%aS z2E^l4n%h)kBQRr%xjR#_Rey<`JI;Q>+1j1{4*lwx9 zimzoGJr=hXp+U0fup}G951VC( zULBf+3#+|SOO+ge$f`)#MQa1(dQ<`(G5oMehO|*fDFZ?^DXv>3V1|51PO@58R@wy% z4yapJT;Mb-$jxgrET6^F0BNNamkhbtAVaiZEQ=VLze0P{I%LRAs4Vj{EZbhJ2jZ_4 zk3&|847sVEWwi)$Y%2$(4I1rit2)d2!0{vp-yr9fFf@8zOTeo#dtdbz z9K4Wd7Y+x~28!+|31C`#APfi}B)DNsFWG@`P&7$m>Ouw}mhn3`lH*|1xA)gWVNciL z$xYFaU^k54-&YtGqYqt_^ZRyC>dYhFU9{0(_&ZhhYAj0wqqKZFAU^h`!9o2^pd*mh zDbfl?9mrZx+*C3EX*E32niabxxIL2|hr{1=2=doyy+#>Os@MvN$Zrk_H;5pGI_+m6`Uw>-4u4Tj(Psn!nsV zERSug5wcT%msAJW7~*3RZm;Hm1cQO)uCt9HsFEIt6$)luczv}l5N#1`(@4g$-T^@P z9m2I{hZabSEV0CT!Lr^_t3!7@-A5bflKbmKdvFT2taln%mT#P6y6{nwCfeOCOH`I+ zsk5*+XBIT59;1tPj~c6BS${+Cs;slpqj%P>>V}0`nccQ@!*_Uvdmvc1ZZ|E9U6q%1 zL%{H~E%PrR%q{EfEH5jRnrW4g)UV+{SjFVFSPiQRqX$yFgM(?6kL1;6QlYTGB_PIeXj$tBjNgVZKzKy>qb!>{$oZ?AsCJ^ z5C(}(A)bbnu&f(Zb+kD)qQ#NBwgK;_MdE!7B(vfJkorS>YAxivk(&9WmU~0ow_JB| z8KSALihanNggRO%1W%6T&oYqwBWr2WN+EzsjzBom@_&K)tsD5Bc#_m&-NUXHrvbf@yc3@$?5WpWpy!u32ZV*94RrME zt2&rdAM%D-AC`Wk6zVCvT3#yw$v?JaTXiHn3|J#U{+b}AskVGmWT}tTVvo0PpnKsO z(I<#SBL^Tw3Av^T)*hDiF^=)^Et}%4m`1DxuhFjNKr~KoJJ5343NA^Ec$S$t;V7LI&wGTc%Ih?hGdfkvY~Kj^`V^T zmR2~(Uy^qL#AVh9Qu?N$q(E!{Ou1;sOJ1!$koCL*!s)|iT?mvslC%moNieDVmMSfN zT%xn8$|_HR=&g&J2Xm%XGOGc`rT`~zTpGhN%yR47g1nZOkIA~Y5_taG=4Bw81dKA8 z5|H#SEBN#suvHDA{u=xMn|YQ0M_#oQN#ht_Duby3$!o-CUInje3P}BF_<|T!Ng9Y0 zY-+OrvPlBjWG7m+1i{sT8C6Lm-A#YS<)j|5U{m1I38E>hnlArY5>ZMg^QJHl1XTwx z5<%B?4nz-!x3AjY^~o2!{eq8wo+Y<#3dL_aKkzt5Ft9s#xA|2>Na|#%+gIMa(kZf; z02wZwEw)UptDYce-%$>6W~Gv|tXCBZ(PRswld@@zmwfm-OKeLa$s3kl8;Y#RE96fV zayt1TXL!|55z1*~u8XtDr2)>6BxQY+(gQl1N^emqAlirPMlM{lm`;(oGR_WPo2&0j zjpT4}O&|k7xq>+$nwQWHCTlfU%CrU?J%sZSl(Q_5+NcC6ZQ1xH74k>@gK3v62jjeD zT&Bqs$*}zAS3u53h*J8z4*%dnv5SCiC8{DBtY9KhRw}8>L4syggOm zipd8^Youx2^wzc4$b<52`BwM+zC(TlN&PR7TBd;GLi}F78vlLgtMM`Xfy7476DOCB z|Mp+o?(2^HyZhC=8{PLihwH~%hI`hY@!t5vCm_FD1$cs8k0YJ6f%La|GMnH_CRjS=knhU$LHOpJ&^tO z{yt+MOQpoZyYTviB#_@WARX1VH2oQiIJSp{zv#Zc?38i4`}ak6>Ed8omnV(nki;UC zX!u0NRqTPp2D*r#9&(zP$9Iq8m>owTce}5PP8DBvU$?t|ce-nL4;tB??iG{Pl}?rj zyi@&Wht@O5Z&ov;{Kt&h#F(mMH_^xTWLXynBzI0YE>4!UooHmYP)W?bZXHNNQ=0;b z4%#Tc`LZg?+8Eo_7|0RH#TAYvklo^W@;a%fN{cce4nTh0*qHF(MsW1i)c~YNa(9BG z2eO?hM1zFYipk8DKy=l3Ee7l1jpOL`G1kb@x-KXBNSjt22^#iMxiZCj1bMkh&6NKr zC1p(OpgfT66_U#qplIwxFWe4pnU~-$t5e00I!v}b$!GcjTJ&VfWS z%8~s7udM2Uo(D2s{uGQQ5I)$;6_-ULG1VBpXdIqnR+Te>2m(o`NE%EINM0iX^(3+S z8MPXjDCEVJt*WLCDFTU;MXmvf$w}6(kRbKWy|Hx#`MIhK_kppT?$#`8sgig&4{Lim zu-jis*;UQ5Qt!zJ3en9EKrCj(MR^JZ10-!-v6vk=kR=vPysM3C4+QNrbh&{wgIL)+ z#}TtYVz$1jmA$-1_~R$BG+g|da%70>1Ff)1bF8ICVj?F}$x+t_(y^mZ^wX|52Eyis zZ+_H(l#%3sFgUCliSYVVu>|>P}2|7d($*mw1M>Hqefp)d-a)0}%c2 zu=WgA3IKS ztreCe7iw1t_%xavie2HAJS#2bG`I)C9+>63^Yq8l1$$}X)5*aGdU_Yqb?wx_-aU}@ z?JAF>9_%?RJc@Fku1yi6Z3TJW0Y<3;sTaH{7y`n`0l}b1wJk((XcZEdq5izF)U9cw zmLRxcabQq&)VdHB2eRW93@pfV4LWlz4h+k#dO3FwrsTB;yQ*{VfoKju;ULl<4b_Mg z7Pk&$zC~btq<16R{5RIi-sfClU}0YG)wytwh4MHm6@s*fHicwD{aFGAo*p=oa-Ah0 zjJkgE&nl2Y>NuEFg=BgGLxU6^|YyB&x= z(6wDV1Z4mcSE#R0gE9Q$B# z)T*qyZOPR4`gk_l0sdBj#1`Iyo2wF)mIiAYSY>S z!7D7ZA=D|PY+7OlBJPG&FMR34RzaRNXoDXrVx}dPMdX19T<+Qoi#M%>Wj#%t;Nxjn zxM^Wfv@k4&r8BMKY6p4BJl(b7(Bz1~Kt!1z-bmnZ?}2cJ#o>_bhh%a@z#^8{27)7k zpHKs1)~P?G)JEw|L~;P{fkYbNh|p)s?VPkuf;{Ow->u`QA<0L(sDX$w&g(YiRs3FA z){_nM14|Gt*rl@MrCUU}2``o$t~qi95}V`)8|r8QEEEt?7rS_v`{hVySwEz-f#DFi zLSa%wz`eh0R$dJuetex-SLuQ9`BCdtu{sMuBE(+LnG}jcQ)6kG!*~Q@8<3|pYeL6hyaU<0KwGJHbLOla1X@8 zvRK<<&ShkyUSON5pQp&%mD#es?^^O|3ty!86=?r2-w&VeYKmTm(zge49XPbMg(L%) z8&NqwgfUD#-g++G)Q1HdmwyuRUbP?@oNzMfp|595n2nX+6wYGeb5%iVb_OH z`?)SNbQ%>zd0_Opa!aluX!W>%XAm3F@c)8(;UMDyfEegFh zG%aDZ7dZl9dl1iwmVkS#FOYWm5s8&c^dfs8x|6Hz$3%SXtBp;yI~I~X$>A|49E{ht z&`CRO;Gf9>Ne`q24g^DaK^Pc*+Ni%{`{CQdaPcuW9KOcIqG_cK53?eW?16A2cOC~5 zl#$%R0?{5hkAinyy5s6s8S73rS4Wf_<;FT914WaTJ-yn}T;b6`{v6~hT#Jls*zyOf+Kzwkprv>R@ z=z-`u4=)&1Bu5}D4)i$L8ph?X36Fx8?a)UV@`wq?bwF7Yh!qBnB*??&3ae$cbzMOG zsw=Y6>VdRr4t4s-{iQ<-s`*Gn_in^3&oKu|w` P00000NkvXXu0mjfxROtc literal 0 HcmV?d00001 diff --git a/Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.bundle/angle-mask@3x.png b/Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.bundle/angle-mask@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..d07f3ce67e8076297b61e9b559f955d28938c2bf GIT binary patch literal 8319 zcmV-_Ab{VAP)Wk zIB_DXdeP3aGt=GGm+5@x#L1J9H97r9n*Ym#%cCRsm#nuS_pe{d0Y3-#ePCTubCA=| zh7U1%NDt7MgYZ0pW&wxhT%T`u|Y?@qx+CzZlO^QCx!MHv{yWFU1X0-q^2#Z{}sfET_+|CS0%-mTLej z!i9we5C^ch54nc7ic)}lwXfW}3|4Zi&*-#XFHFw|SbWF;K2Bgop%shSHGy?KUQ2ZJ z87x1vBD~etU`2T?;n7pDm@~j=ox+dS*k=t`mMKMEQM*W^J_pMyTv*SEa33*W$?J@= z@ZB8ivyj|sEuDIPz}lXLALLk{ZYmPpHe~tgUa_BrALdw}rgX(|1p%REG!WO|=12Lx+#3fkQUILjzcX>p1C}Z&|76MsL zp9F15-G*ju8La22B;JALx7*n_VUHX#9az_bm{(KHU5@pMtGkLXfu6&c!x7qkNo>Xq zpU{oFtvJTvq#vH_SpK3BbMDoef)(A)hw7JY*et11zM|I}pRsReKe);7?J(t&lrTBA6Icb4Y#F>y|)Kh9gTxH^!pSl_MfD*V)8=rm1tOJ%q5Z}Ta(R>27 z6IfeA%e%;|16EAI-T+opu&fWbog(OmSPsBx+XYcf!5l1~S)p$cv<~Su!19>Gdi$)w ztnedR3G^$1F+<4(%O7*^f@oZX{?P4j%mR z@HMT0m1q(ALvji9+9%8!&h3EZ>%F|%mc_He52aZubynzA1d)M_0V`Use3VO^zfZx^ zKg@QDpk@H^0nH&eZ)b*RI-}o*p|e6;lI0B)AFQfYg>yBLOReZFAn*%Vi z`z-(MVWQUL$KkU=Z-1pfLi*?#x>p2XzO6LStne|R1a38C$RwrGg5~jw*7I55tnjgT zR=93{#ncB>FS1c}_!_#cm~=KPd>m-q+5HPVh42N-LqTo54*_e1kEINf+!g~ZzaiZQ zSUla*%^Im4q#vkDAa9c@->^#u3%h?d=?&ZQaV@>P0tsh@A3%3x%?nYq;?zP9*1Cm} z(Wyo0ApL-D-96C4jqI{-QK*}QZs#AoI7Q$VLY&MM^^m?*wGP&H%)3t++yYo@m%||Q{zy;)8BH^BWzc7+WneL$C9WK@8fU6Y zI*;h)eLaVT4z_e~Go)00c&*{G#OD1G$-J-QusnxZ1C|%cYr8Cid4Ghbt44?A*%%`o z%s8;DcvC+hV{`X~d4J#0VR3sJnDf9jz>1zD z`fa2TFp|@Im4p1xJi|l_DNdJ5%aUWWQl0d#g_p$h0#d|f-GSA(X_eE1u+<9H5-V7! zUh!2cK6k%2@9$~-z6)IOYJ~uh!=A}gwOnI{vw43Hz3WEoJ43B}z*_2qgFkSl!s1gZPkjg?jrO4E~rzyRYNXXEG?;h&IDvVXNZi|LIPCjuIK$-S`p-S zzH0hVS7du#X6+=p*Jbg!-k`+)*6^jX%UAJUtSqq`$ z77bVkY!>Ze7DI+{Uj(G@Kqzqyynb$IoeN@MWQWJJW91u;f=O0RKN0KHS_a;V77BnI zEFZYAF0E+e-ni}v7ASXN1|C66UI^#k*}>Amg*dH<6bpqaPZf*nu{`(c$d+z(P>ruY zUCtfl!7yvBQc4WG*Zv%m$NGtj$MWxTuv>P$)?`rk7&bnttAXaReq3b_dq6f^9JCM& zFt9jf5y2{E-?LP??!oHZ90HdoT6U<$U`4^@>#&GW9Rt!I%MLWag+&kgAuzGj$X`-<#Ml+pN{TdxucJ*R7EbjJHxlZMJDNG<iHRZ*XH!L(qlz+!P`rr4lfBBS&b!6v#?U=+2KC$SZ`xQZXhV-=vA(S zpsgb;_x07R=wNhs?Hnxa1Np-x2}tG3H#(Kkfu&VH$uf^NAYChMuX?PvO&&`-ZRMp| zN%2C#^6**~`_49eG0 zNdtuTwa9%i3(uGnayO;wh}d8GZ=-7If)}1=jk=ZaGB_@TvJz=8hgj1LBfla!tTR{; zmBfwsb`#GjgMCD96i_kCA?L(Jyk%wqB}=d(@M6L>Duz9@#+T$^X%(z>jkOSBOF2}e zdSEeY7Ur%rnA|9# zLY>wc=@rXgJ@Z&U65k;fFIzFxhoQa8ZLsvph0P0@GeSS4@}**dcQ-8ccy>D2utLG& zqs8uMuq@puiD-c(no<&+mfpN0**lKa7%V$ly4)Q#?`(H9fGwwgl~zq+U}|kwmiIVF z(2`*_1xte#rdZ5E$nLfhv2q5>;A z=iH^*xuImA&8Vo=u(?qj+n*=uJQgw^B=5S>l91EC41^71m~|2nj$+B3)#cYdSnYd` z+?JPO@scaN7~X>=Kiu2ObAyL*;@*O)_1%r&n5;7KXoBVGtt>$0I#?=uW&q5B*BGv` z)9NYK^tuMb+%A~<+tSL zRF-I#1SkzyZPl{q6)Rpqjk=nU6Ij@TU@t}sm<%tyX35aHX@Yg5!V1+ZPFoDtS7jif z4wlilIR&VQW=SH4I$SlNZUnfsEWA8wK=q2@s#xPK0?U8ah&isl-|EBFMysw$H&wuD z$M$B1`ehuf1X4PxY~?Vgf3nq5XH$>&Kj?~KuLz!@y6HgHE{I4Wl)z>4RMycO9D4~C z{?N>oMy=bj`tX>NLz0$inXt@nPD5N>34m= zMqsryi?bf+KjTxC!hclB-Fn7ezLGdntvXn#Q~qu)z`Ch|b<OJt6nzhua2ea?ake!`YU$1)ZO0yf#>Z5{2QUezIh2nNn9!f|;)4I!A zD%FF#kDF(oFEy)$l`ag`z?4@Vo52J8Jw*nisye!WJ(?rdis2cn6HE^$a6M>(HCn=v zL<;&vnP3k!dgLQmYrF_f!mG9Q%jopdZOzd-WAyMDSPv(t)%2!XohUKw{*z=6ZF+>V^IPhcmQpE*w_xFR>zFf_DbxgdiI%-S20u z57amAKEHUcTMsJpLFwGju235v9T`}g5?STrN?h3d^HQ~rdiCNSt6xsPbPw0Vg}<7o z>mxUXzxHj9#tL92b>J zyW{`E$L;>(%k5KGV>1XM){pTin_0!|FDDwO6Un z)Bo(D`p^C6&-a(Uy1RaN2iE!H^3k+9R<8cnI~c4I^cZD$ZK-}eA(duO9X_7!KMr7h zk$#^3caPQ2_un1BI$VD`W(wA&a+S`jVEu%fLlFb3YyiFjm%I7b(#7ib4xlIdk6-MS z>WlsV&-dRwxhsZG?=`E1R_Vf33_sD<$L1caC@C!t_bNhtYH8Hcrk}7ndaEN?U+q7h z>{aR)`;Ra7|G(T{`sz-zZtssO)sk3uUPbUq@t=J&g)^tW-blIQ6uS0sm8PSbtJQ9% zSGV`2@W~xoU*2Q&Ahy1=J}FtJ7@o4Au#)uVz@Cz`9*17J`;myGqbI z5086JKUkpzVrkCE?v72m9IKOFO*QLS5}(fWs$LAoXh}_d0pFR3F&Ze=58R*1;tPsG zsfwro&gX4yux_8B_4Ju)J)Nl4(`Q)ScEFm?IVD9=lYSM4cbs&;8dwqLPwN>p2E8@^ zt49k{)7}DW4%gHBYg%CK7LS}R7JnpJ7t`360F5e3u>NXwD=vSdWI@6>SXic3Q?#SP03$?0&wW}yrX}pTjE0=^4h4gNdQPY6M4C*u@UesDO@>caSICofcw4P3s>vra^ z=JUc`^>OR5Y3aUh?Yt2$jV=Lf8!W!v(@AxKZMv)o_Vub(4$ohoRJtrWrA0ao&YD8ULzyNcTwcJ7nYUk1(ZG*WG~ z>b-EGg;q_mmSD{xTk2ICt<;4}kC*NpV|p(!W__?Yvk69&pjE38SaY;?gJQV50BbiW zgu4r@Mqpv8sfzp=1R&gmpu<9;L@h^+<9YV5&HWCn_dEnpw6<_kkWuvFNvk=t>j=`;)U3F&w^;{l(He%<0R+`;<@9HpwCe3Qk2fDo6%ck^)hYwE zsy$XB&kc(}+c#k6mtgr@b*8h@=~cQI-j-gKDmZPVc9ln{Yn3#C*J@Ur+Y%CT0*hnT zQDf_ALx#ZUs4v=AoK;tpOAt!@i6^Ev%#!0eCjtlEX6C^M{a@X!aXA2MjNtlm$w zzS~j)Rs)MU`;(?CqqzoNbNe$ z#GD!8-486U)#=Cj6YBg=kCYTD2~hQ6!VG*5pt`ft8u$9I0+zyKP0YODwDiI9b64?Y zu#MH&z_;+yBh}B{QJ2LmhfYrG1eQgkSWC=u#nL#ec0`(lP_@94!Ig&bs1z$yu{@Wl zOFM4(V>hHM-byzc962m`A=CjTRjW~orNv6}3&`+V2D~o8;vsk9zlSr|~SZTJ1 zao_^+nuCS;EBn?6M60xlg5{q$~S3Kq9@Z)6pt3SsKZ!=%eQOH_8^BW3eJ3s%fxXeouI?y=sYMhoNlM==#b zYmU_~hRF<8q8Gw(;Gl2+n8{RU}i9w~&D*fWKtQe*N40^DVIA*XFLVYnTzz7*> zID=)=DGO8@)2_oxUJPY$p-@>0Ayy16o5av@Uo7doMci$J_g%4Pgrj0O_E|{`Rs#JM z8!h`T9^z6@PJbA*bfYbVI;>K2urxj^3Bv=uR!Oib!k-Xg5w0UxtQ|L2(~kKoX&IDR_ymKMK-)epf2_~}RVyGY&FRf> zsJQ-0=CE`IJ`K?6-I9{7qe14Z*7sRTxRzjXp+dEagB7k?63ArtL)FUC^5@q8sEQlj zgd7&P6e3-tNj#&{xU3{pqka)&1*7u*cg_3i3)i!_;Z1d}8t1P@*|Th3C_yVJR7h9+ zq*x(yLL?;hfU81KPJcj|2};)oEgcQGdDkRbX=ui!$0s0WV48RN+N?BvSIiLSU@?2H z^jf9IiW`$+h$WR;*`ra;ywEEuEtgZyDlg?LJ%U}drb_-uF!74=ED(Y+WdkM8GhElYwU?ua6P!~4H zyR&$@CAf3|%iFeFQ+KXTKr04r|(n?pVRNTI4s)=Ar~w8%3%@} zHcjb6kwVb2uNo3v))Xw({$@^x`?y_1QVONzkPj9s7%igrg4YF4+B1Cui|4R7&B$`B z?0S_{x`TNtOtaW%`RzNrxO4!^!?t^@5z4Vb)(yE}G1do}Xob71oW5&bCoBZKq*$Tt zGrAe#WwhBc`MnSnO|Ou3Lf)Po(thbPSP{ML@+J?Tg`IJE(&>=KtQX*wTG6uZ-7&y* z0t+dJ1=KGaR)~FP*!V;$fjX@!>i0y8mOLm`daUod&IXYTOWTo!>6Lub1qPNaW{^h> zTD0_P1$wMEgdWSX4@cACsNJQ*)T|`-OLC;_tAiTTj&_oA_VCO+)*A+oWmBzDM}uxr z2iGk*UMNzyRw2ymQz&N_Dzb^;mDv zj5{;KV)bNk%c4*D^XtXpyDWvrdfiQ{_*iMYh=*?ZX_fqES_dt)ZcV{rH1$PeCBdmb zuo|d%S~Y&f_O|4x1irCW_&QVot&7hnR@{Q9Ma)a97)8)>3Q4PORXx`00bA&`tulJ7 zG={h+uhD{qcD9duMNzc8`W!mJLr&i@Xq7KkNLLoJz!L+OH5Apx4P3O;x-|vM^CU%R zo1dlSPY;s>5 znqaM02w7+;Jl1REc9|Hgq#uUl$q z$!pdee>Oc-wx(q4q_@gFhEuTo+hzP`hIT98n%ni}edE?Won2pVMo4R)IfJz}R(i=t zotDiX*&o5nUHL8O0B9Y-ikuN@vC>Vu{cJoAmXBqZZv0vUt-D3&Z!4=OX9=2}zFP{R z7g*fv%C8V=m!U;6l+*8+7oJ&I#S}vnE*)5`eK;|N(4l$e3|8D?4t7>QT(9(Q#{(?; zUL46g!|Wb4E$p1Y()Bhlx<}djb+p|MTIJGi+(MO#H6twGXfQUfmJ?XK8KDg;RQd}I zE^DC5f~pwajX1PA-{<9^ja;%&P}Q>Lu|10P+{j9<*pRk&pfj?@2`R-kbxC`61H_p;`${J>ucbkrMh+w z7UHaYu<{KaP}N#rt>Tt*5CUfA{Z*5*vSVdcE#!SpHbyKyi^m07CqkE(rB)?6Z#&fYt#l^t>XB7tAp4cp;1hi+5Tz zRyky#)eJ~~i=1EinRmX|vYC7Aabmp{r>gfydwto&K#O~e}#;d^;AZldSwkHJi`QE&9eS29W`1f zu(s{8WN$lvw#d%Vb+6Fp1ZyD<>jW07ZDuP=J6^sk!cT2$DaX(@^U5k%A-`>M$m|<1 zI9;DQZNkf-t{jG-mD9^ctQh@RexU(#Ps>_t^nm z+Oxu!U9s{DNqv!Gg`HbOihK6a(wY^%?0^;i!`YXlCG*7y+_cB(PFX9t6m@2-#*)rU z^d%kEnH(Z!hw)%}T6eFrH9$)`FS%jm5t4f1#XD}h&WZ`tU`gjCHC8Nlg`LsKR!X)E zmZcc#yRW#j!i#H9U}2k9J!XYGy}BN-*3c}^bC8x3SbkVp7k5}|hmsRov%%`0Ox$~I zkgruLN)BN0v9kQWVB5m%g^;go{9@>Jf;DPi!^va)W&l?HHhwEJM*hq%#3ha zJ^$lJjvUcEqha-b_99Ka`EM@-n@_v)>PAuFjzt@_HY)cD-gw48)wd#3cdhZuU+U7y zs<#R!P0eidOjhfiX_6Kc>EZlr|IhW3(wnETov8;2U77)rOTWaVeW7`cgE-%Mo|W4k d_~_qdbUPil#_!3!(?F*%c)I$ztaD0e0sse~NwEL` literal 0 HcmV?d00001 diff --git a/Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.bundle/error@2x.png b/Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.bundle/error@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..aaf6798547863870637b959e44dfea4bc8239ef7 GIT binary patch literal 306 zcmeAS@N?(olHy`uVBq!ia0vp^79h;Q0wkIGKTicxKRsO>Ln;{GUfUYU%E-X-u=bkq zI?i`Of)|D37=>c%CMA4NnRIX_+rRwHXODlqpVjqdsqp@|zTgzQwOt`Ai>CFRo4ed= zYWtR3-l>yx*PW`0DwSU4+I7d%igU8v@g?UCUl#lPl0jvv6x*Gg<8SnQ@|lw=#abul zco{99bY^ABe9P&3lKoU0gQfSZ*_~72vD@w2;pBHh9)Hunoe4e}bNt`NGp(MplP^7P z*kY-W+vhPiIq3O}E0$`deV$0n=EqhJOzD%({7ji`&E}`%A3ewS-O|vDk8(aKuATO2 l%2~1WiR`@QbK@`7n~J7%Ce;M|$^ixfgQu&X%Q~loCIH_Yh_L_w literal 0 HcmV?d00001 diff --git a/Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.bundle/error@3x.png b/Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.bundle/error@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..c92518f8534a47a1d2e43c760ccf80f0a045dc52 GIT binary patch literal 398 zcmeAS@N?(olHy`uVBq!ia0vp^At21b3?#L;KKKlz%mREuT!AzhV0&3c5m1{@NswPK zgTbY5li2kCuf6s#2-WVQm}!wOdzu75`Eymhj?UWpG<)+E&)k8M!@| z#X=JE1Q)#WU3G5>n8@;7f9Z=BdBm%Im%nKFtiAN*RpD%QpXPVwyP~JO-@Tr9R>*92+OrISWatG(T3q+W)4?j0*g?*VsuWex9fNjK%}@dp3?H1b?Lr57fx zy3k5a(&$dzwVqXI0yBGWD8KSJ5uiuA**6uZSW0mJP}>XxY9YfqsX6 zYIBn|KOO4#FY}heVxFZ5i!Pb>kDL<&LaS*)18Q>q*f9>bwg?qF03+%;+*P}}5#XIq zV&0^Q`Q#n2t|(?FO-#uKa3Q%@!Ndj7(s8eX9a@hp_~5SIcXEn0V#{%R!B5`DH$c2# zWCO5c?9K&W|NA!Q*ub3%_N&SJ$E-!63FAVGX0IRQA8zyg`ax#cp+y6-^jmajSVW&0 zP2=rCY)f@;o7!sn~nG0+Iov{5v?`0ZQI7#@FsV3SsTq)QAK|l zM;3>*biFtHWUh@u*l4bwyy1E+Raggg7KlSE3)JbT0uqA_5kgqz|L!(OD<{fm;RG!W zaEDJU5<(cFR-z2u3=_gy4SGr(Tz3st3SpRTN>ZiX9$~rr9HkJ|Znsd_qfwP2)fgx2 zQtxQRsP>#4!ZA25EU(cukJQLJx&XT;w8&LbVhY$)dfmN}^B~3*i!ln7Qcs;+pjnJGf;!9Ikat9bA}VT9yhpZeRiD>(Rq{LZk+Zru)bdrozPe9jfZdGcvt zq|oS~s*Dx>FOknc1LgOYFjkdAsIj(UpTtiJ>$EKFm%C1)JWmw%%MF8V6aKGCshWFB z*k-T-^|MwOt))_&<}YEbe#H-lwt7NFF`Bv8rs4-fP^G~hVUBCHC@^-Jslp!rQKcl^ z3>U&8PpWY!XL-_GAq>||84|VG@#QpcxJqxQXaW)^>*;chCgzMUQyI{1u{mdbp*kH^ uSW7o})6ZsGYp0#on(Y^Fxy000DcNkl8g^j2n&U#O}fUpe5Cpf+nmqA$OijSF@NepFXW@ct)Zo?TpSvv>W zc*Ybd--y<0zxhqG^WOZ6IU|fvWDHlZk$ZTJFZr4O`IB$?kQcd!ja5bUFWi4%_gv$(`(z^ebC)vbROr}Z&2LOi(RVH&4n|P9c zwf&!B1}+IRmDlUK{Fo(-p@~K`F@`04TzBLfOd~Ny^GMjypKRe2qH+pb_$!R@2(849 z&piH@4t`@k&6v{6e14Ni|1%Gt7-``p3H=`nDPv2Sh5RQGU!qD(Obf5TL)3_ifQQ06 zG@Tf@k{%WAA1)(qF6AE;yN4^W!eNn|^}Do_1ns;dJuJd8m$^-X+)06?C~&XzvdvWL zS_!ZPk0kNgFFmcrfE(rD)i@-L!y4)BMj|ppUZH(Bq=Caed97v;fhxbM!|uZ;Eqr-a zep)%QGxK&$+wUy2DenMQX} z!-R`u4$w+N9+4kQGtQ$|+Ig7qu*|F)FioZ&0cMN}ujnYu2xPi4ok4JATD%Y;-Dgx- zs5HEe+vs}!%F$%W(K0wrAt< zJjv6~CJ&q~bpVfpI7fZ;87{V*#7WrV@|n_e4hOMBeX$H%R;oBFv1O@>vy_8)Mb5yE z8oknLSRr@#6?7=kr4qO!vE%em=;_$eq!Pa_N@$Ex!JmZO2t_JfW6-!lhJzdlmErOV zG&ZP>m*q<6Wh%}FH11X#$LC7ucopYfG+tF3tGN=|qT;-U##d@%C09Z#D$du`BNHn( zS3(_`bk-xqYjPzN$u@?iP`UNxTnQ~}w_bahPRNze6SS8}8=h*p5*olBs1G3vHZi${Bo$n+u^XpUNFJC_tnrR03GZiX@T&5e8##0r#P+TW2gD@Rg zY)DI}!D55(s4U-PBvgD6kD4!tnF}>v5KC~0@g!N5?lCInwjfK4Q5S6sMCT?t>EtG& zQ{YYU?f49lKn950@QBV){Vh5kw~1#bFfkTvPR&@b88H@^S~XUtV%1n>WYrMXrDT3N zf<4mHI$Jx@?TOln?zXfOX$Gx#Xe9|o>jtfOEN_=4XnDJa7?=^72p=RME~-2zQGaJ9 zF%i_+G8a(7mLd!4Y?%Qu;xj)qy8g&59E&N(ax*`MM%VfH#7?Vb9p1^=xJ1F_Yw+nUl_NVAXx3|y2B_-Nf%lGs~ zY~Qn%j{N@xV+NlKBBd8#l9Sbdw~TYMSAQCYne+lP+Gnbisui-cJzB z9PXu==iyJ=cJBwaKeG3iy|M&iH`7c6L^gHG|_PkKzY_uhBy;?W>kwV3TaCcXE(b5;7Zn>HU! zaekCx_!AfRXJ+W+2{%!zgAaV*2}<3t+y^>PsUqAw4hmi6z2z1;fl zos%e3;FaZ?oJFA=&n&l05{1t3&~mG|D3sy8<+e$oP>LPP-6xGgE^C&1NEU^Xv@G|G z^C)zdCCj}ck3y$tSne%F6gp1La__i^LPw}t?md@L$YDYLg32gl7!mF|Ds>3gj!M^s z8^NGZ+3$RC@Y5CfKd*Y74{f|-)H7P*oy>>hcU>Fi|6ayTS`S6|+5oH)gNRCn! z?uyR;_=Y@Ih&aQjP%y0007!Nkl)zUkVeinDTMyPH3~RwHXSK(yT9P@54>78YWX|DJjLOeVCvz!ZVN_O(={Cz!4|&JdrW#5BAA% z84sg=Vw;nBg;W^zE$f`j>tw~KFInPb-lPCVeab93)yrbkhfI*n+IHvnp_19s?)=_U zGQ05(MzxX5LA-}i^(1qw-TA$OWX|Mcj4CYi`w~9GsO&PoujMO@O2suNa|=IURD8K+ z?B;ijiYnKPg9N~+Fr0QWj}a21f^bx>8IdsRADQ1T5F4X@)A^mG81)0|Wq!|qQD3oK z=Jz~y=l6MXs+YtgzNbCo$?nnleTrmO$3vz)*szkv=J%13*%VKa!>yu6=J&pm*~ydh z`&8MuJa4Ll?AG6tnea0kJ$7+zB0G)dJv{7ZHhCnqn(Q)-5AlLu*eoBU46mbv?681O z@seNJB7dMu^Qv;oHDe`TA-tPfidT_dt{EHn!TUqRR!J?%%Ss}D; +#import + +extern NSString * _Nonnull const SVProgressHUDDidReceiveTouchEventNotification; +extern NSString * _Nonnull const SVProgressHUDDidTouchDownInsideNotification; +extern NSString * _Nonnull const SVProgressHUDWillDisappearNotification; +extern NSString * _Nonnull const SVProgressHUDDidDisappearNotification; +extern NSString * _Nonnull const SVProgressHUDWillAppearNotification; +extern NSString * _Nonnull const SVProgressHUDDidAppearNotification; + +extern NSString * _Nonnull const SVProgressHUDStatusUserInfoKey; + +typedef NS_ENUM(NSInteger, SVProgressHUDStyle) { + SVProgressHUDStyleLight, // default style, white HUD with black text, HUD background will be blurred + SVProgressHUDStyleDark, // black HUD and white text, HUD background will be blurred + SVProgressHUDStyleCustom // uses the fore- and background color properties +}; + +typedef NS_ENUM(NSUInteger, SVProgressHUDMaskType) { + SVProgressHUDMaskTypeNone = 1, // default mask type, allow user interactions while HUD is displayed + SVProgressHUDMaskTypeClear, // don't allow user interactions with background objects + SVProgressHUDMaskTypeBlack, // don't allow user interactions with background objects and dim the UI in the back of the HUD (as seen in iOS 7 and above) + SVProgressHUDMaskTypeGradient, // don't allow user interactions with background objects and dim the UI with a a-la UIAlertView background gradient (as seen in iOS 6) + SVProgressHUDMaskTypeCustom // don't allow user interactions with background objects and dim the UI in the back of the HUD with a custom color +}; + +typedef NS_ENUM(NSUInteger, SVProgressHUDAnimationType) { + SVProgressHUDAnimationTypeFlat, // default animation type, custom flat animation (indefinite animated ring) + SVProgressHUDAnimationTypeNative // iOS native UIActivityIndicatorView +}; + +typedef void (^SVProgressHUDShowCompletion)(void); +typedef void (^SVProgressHUDDismissCompletion)(void); + +@interface SVProgressHUD : UIView + +#pragma mark - Customization + +@property (assign, nonatomic) SVProgressHUDStyle defaultStyle UI_APPEARANCE_SELECTOR; // default is SVProgressHUDStyleLight +@property (assign, nonatomic) SVProgressHUDMaskType defaultMaskType UI_APPEARANCE_SELECTOR; // default is SVProgressHUDMaskTypeNone +@property (assign, nonatomic) SVProgressHUDAnimationType defaultAnimationType UI_APPEARANCE_SELECTOR; // default is SVProgressHUDAnimationTypeFlat +@property (strong, nonatomic, nullable) UIView *containerView; // if nil then use default window level +@property (assign, nonatomic) CGSize minimumSize UI_APPEARANCE_SELECTOR; // default is CGSizeZero, can be used to avoid resizing for a larger message +@property (assign, nonatomic) CGFloat ringThickness UI_APPEARANCE_SELECTOR; // default is 2 pt +@property (assign, nonatomic) CGFloat ringRadius UI_APPEARANCE_SELECTOR; // default is 18 pt +@property (assign, nonatomic) CGFloat ringNoTextRadius UI_APPEARANCE_SELECTOR; // default is 24 pt +@property (assign, nonatomic) CGFloat cornerRadius UI_APPEARANCE_SELECTOR; // default is 14 pt +@property (strong, nonatomic, nonnull) UIFont *font UI_APPEARANCE_SELECTOR; // default is [UIFont preferredFontForTextStyle:UIFontTextStyleSubheadline] +@property (strong, nonatomic, nonnull) UIColor *backgroundColor UI_APPEARANCE_SELECTOR; // default is [UIColor whiteColor] +@property (strong, nonatomic, nonnull) UIColor *foregroundColor UI_APPEARANCE_SELECTOR; // default is [UIColor blackColor] +@property (strong, nonatomic, nonnull) UIColor *backgroundLayerColor UI_APPEARANCE_SELECTOR;// default is [UIColor colorWithWhite:0 alpha:0.4] +@property (assign, nonatomic) CGSize imageViewSize UI_APPEARANCE_SELECTOR; // default is 28x28 pt +@property (assign, nonatomic) BOOL shouldTintImages UI_APPEARANCE_SELECTOR; // default is YES +@property (strong, nonatomic, nonnull) UIImage *infoImage UI_APPEARANCE_SELECTOR; // default is the bundled info image provided by Freepik +@property (strong, nonatomic, nonnull) UIImage *successImage UI_APPEARANCE_SELECTOR; // default is the bundled success image provided by Freepik +@property (strong, nonatomic, nonnull) UIImage *errorImage UI_APPEARANCE_SELECTOR; // default is the bundled error image provided by Freepik +@property (strong, nonatomic, nonnull) UIView *viewForExtension UI_APPEARANCE_SELECTOR; // default is nil, only used if #define SV_APP_EXTENSIONS is set +@property (assign, nonatomic) NSTimeInterval graceTimeInterval; // default is 0 seconds +@property (assign, nonatomic) NSTimeInterval minimumDismissTimeInterval; // default is 5.0 seconds +@property (assign, nonatomic) NSTimeInterval maximumDismissTimeInterval; // default is CGFLOAT_MAX + +@property (assign, nonatomic) UIOffset offsetFromCenter UI_APPEARANCE_SELECTOR; // default is 0, 0 + +@property (assign, nonatomic) NSTimeInterval fadeInAnimationDuration UI_APPEARANCE_SELECTOR; // default is 0.15 +@property (assign, nonatomic) NSTimeInterval fadeOutAnimationDuration UI_APPEARANCE_SELECTOR; // default is 0.15 + +@property (assign, nonatomic) UIWindowLevel maxSupportedWindowLevel; // default is UIWindowLevelNormal + +@property (assign, nonatomic) BOOL hapticsEnabled; // default is NO + ++ (void)setDefaultStyle:(SVProgressHUDStyle)style; // default is SVProgressHUDStyleLight ++ (void)setDefaultMaskType:(SVProgressHUDMaskType)maskType; // default is SVProgressHUDMaskTypeNone ++ (void)setDefaultAnimationType:(SVProgressHUDAnimationType)type; // default is SVProgressHUDAnimationTypeFlat ++ (void)setContainerView:(nullable UIView*)containerView; // default is window level ++ (void)setMinimumSize:(CGSize)minimumSize; // default is CGSizeZero, can be used to avoid resizing for a larger message ++ (void)setRingThickness:(CGFloat)ringThickness; // default is 2 pt ++ (void)setRingRadius:(CGFloat)radius; // default is 18 pt ++ (void)setRingNoTextRadius:(CGFloat)radius; // default is 24 pt ++ (void)setCornerRadius:(CGFloat)cornerRadius; // default is 14 pt ++ (void)setBorderColor:(nonnull UIColor*)color; // default is nil ++ (void)setBorderWidth:(CGFloat)width; // default is 0 ++ (void)setFont:(nonnull UIFont*)font; // default is [UIFont preferredFontForTextStyle:UIFontTextStyleSubheadline] ++ (void)setForegroundColor:(nonnull UIColor*)color; // default is [UIColor blackColor], only used for SVProgressHUDStyleCustom ++ (void)setBackgroundColor:(nonnull UIColor*)color; // default is [UIColor whiteColor], only used for SVProgressHUDStyleCustom ++ (void)setBackgroundLayerColor:(nonnull UIColor*)color; // default is [UIColor colorWithWhite:0 alpha:0.5], only used for SVProgressHUDMaskTypeCustom ++ (void)setImageViewSize:(CGSize)size; // default is 28x28 pt ++ (void)setShouldTintImages:(BOOL)shouldTintImages; // default is YES ++ (void)setInfoImage:(nonnull UIImage*)image; // default is the bundled info image provided by Freepik ++ (void)setSuccessImage:(nonnull UIImage*)image; // default is the bundled success image provided by Freepik ++ (void)setErrorImage:(nonnull UIImage*)image; // default is the bundled error image provided by Freepik ++ (void)setViewForExtension:(nonnull UIView*)view; // default is nil, only used if #define SV_APP_EXTENSIONS is set ++ (void)setGraceTimeInterval:(NSTimeInterval)interval; // default is 0 seconds ++ (void)setMinimumDismissTimeInterval:(NSTimeInterval)interval; // default is 5.0 seconds ++ (void)setMaximumDismissTimeInterval:(NSTimeInterval)interval; // default is infinite ++ (void)setFadeInAnimationDuration:(NSTimeInterval)duration; // default is 0.15 seconds ++ (void)setFadeOutAnimationDuration:(NSTimeInterval)duration; // default is 0.15 seconds ++ (void)setMaxSupportedWindowLevel:(UIWindowLevel)windowLevel; // default is UIWindowLevelNormal ++ (void)setHapticsEnabled:(BOOL)hapticsEnabled; // default is NO + +#pragma mark - Show Methods + ++ (void)show; ++ (void)showWithMaskType:(SVProgressHUDMaskType)maskType __attribute__((deprecated("Use show and setDefaultMaskType: instead."))); ++ (void)showWithStatus:(nullable NSString*)status; ++ (void)showWithStatus:(nullable NSString*)status maskType:(SVProgressHUDMaskType)maskType __attribute__((deprecated("Use showWithStatus: and setDefaultMaskType: instead."))); + ++ (void)showProgress:(float)progress; ++ (void)showProgress:(float)progress maskType:(SVProgressHUDMaskType)maskType __attribute__((deprecated("Use showProgress: and setDefaultMaskType: instead."))); ++ (void)showProgress:(float)progress status:(nullable NSString*)status; ++ (void)showProgress:(float)progress status:(nullable NSString*)status maskType:(SVProgressHUDMaskType)maskType __attribute__((deprecated("Use showProgress:status: and setDefaultMaskType: instead."))); + ++ (void)setStatus:(nullable NSString*)status; // change the HUD loading status while it's showing + +// stops the activity indicator, shows a glyph + status, and dismisses the HUD a little bit later ++ (void)showInfoWithStatus:(nullable NSString*)status; ++ (void)showInfoWithStatus:(nullable NSString*)status maskType:(SVProgressHUDMaskType)maskType __attribute__((deprecated("Use showInfoWithStatus: and setDefaultMaskType: instead."))); ++ (void)showSuccessWithStatus:(nullable NSString*)status; ++ (void)showSuccessWithStatus:(nullable NSString*)status maskType:(SVProgressHUDMaskType)maskType __attribute__((deprecated("Use showSuccessWithStatus: and setDefaultMaskType: instead."))); ++ (void)showErrorWithStatus:(nullable NSString*)status; ++ (void)showErrorWithStatus:(nullable NSString*)status maskType:(SVProgressHUDMaskType)maskType __attribute__((deprecated("Use showErrorWithStatus: and setDefaultMaskType: instead."))); + +// shows a image + status, use white PNGs with the imageViewSize (default is 28x28 pt) ++ (void)showImage:(nonnull UIImage*)image status:(nullable NSString*)status; ++ (void)showImage:(nonnull UIImage*)image status:(nullable NSString*)status maskType:(SVProgressHUDMaskType)maskType __attribute__((deprecated("Use showImage:status: and setDefaultMaskType: instead."))); + ++ (void)setOffsetFromCenter:(UIOffset)offset; ++ (void)resetOffsetFromCenter; + ++ (void)popActivity; // decrease activity count, if activity count == 0 the HUD is dismissed ++ (void)dismiss; ++ (void)dismissWithCompletion:(nullable SVProgressHUDDismissCompletion)completion; ++ (void)dismissWithDelay:(NSTimeInterval)delay; ++ (void)dismissWithDelay:(NSTimeInterval)delay completion:(nullable SVProgressHUDDismissCompletion)completion; + ++ (BOOL)isVisible; + ++ (NSTimeInterval)displayDurationForString:(nullable NSString*)string; + +@end + diff --git a/Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.m b/Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.m new file mode 100644 index 00000000..2b669920 --- /dev/null +++ b/Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.m @@ -0,0 +1,1509 @@ +// +// SVProgressHUD.h +// SVProgressHUD, https://github.com/SVProgressHUD/SVProgressHUD +// +// Copyright (c) 2011-2018 Sam Vermette and contributors. All rights reserved. +// + +#if !__has_feature(objc_arc) +#error SVProgressHUD is ARC only. Either turn on ARC for the project or use -fobjc-arc flag +#endif + +#import "SVProgressHUD.h" +#import "SVIndefiniteAnimatedView.h" +#import "SVProgressAnimatedView.h" +#import "SVRadialGradientLayer.h" + +NSString * const SVProgressHUDDidReceiveTouchEventNotification = @"SVProgressHUDDidReceiveTouchEventNotification"; +NSString * const SVProgressHUDDidTouchDownInsideNotification = @"SVProgressHUDDidTouchDownInsideNotification"; +NSString * const SVProgressHUDWillDisappearNotification = @"SVProgressHUDWillDisappearNotification"; +NSString * const SVProgressHUDDidDisappearNotification = @"SVProgressHUDDidDisappearNotification"; +NSString * const SVProgressHUDWillAppearNotification = @"SVProgressHUDWillAppearNotification"; +NSString * const SVProgressHUDDidAppearNotification = @"SVProgressHUDDidAppearNotification"; + +NSString * const SVProgressHUDStatusUserInfoKey = @"SVProgressHUDStatusUserInfoKey"; + +static const CGFloat SVProgressHUDParallaxDepthPoints = 10.0f; +static const CGFloat SVProgressHUDUndefinedProgress = -1; +static const CGFloat SVProgressHUDDefaultAnimationDuration = 0.15f; +static const CGFloat SVProgressHUDVerticalSpacing = 12.0f; +static const CGFloat SVProgressHUDHorizontalSpacing = 12.0f; +static const CGFloat SVProgressHUDLabelSpacing = 8.0f; + + +@interface SVProgressHUD () + +@property (nonatomic, strong) NSTimer *graceTimer; +@property (nonatomic, strong) NSTimer *fadeOutTimer; + +@property (nonatomic, strong) UIControl *controlView; +@property (nonatomic, strong) UIView *backgroundView; +@property (nonatomic, strong) SVRadialGradientLayer *backgroundRadialGradientLayer; +@property (nonatomic, strong) UIVisualEffectView *hudView; +@property (nonatomic, strong) UILabel *statusLabel; +@property (nonatomic, strong) UIImageView *imageView; + +@property (nonatomic, strong) UIView *indefiniteAnimatedView; +@property (nonatomic, strong) SVProgressAnimatedView *ringView; +@property (nonatomic, strong) SVProgressAnimatedView *backgroundRingView; + +@property (nonatomic, readwrite) CGFloat progress; +@property (nonatomic, readwrite) NSUInteger activityCount; + +@property (nonatomic, readonly) CGFloat visibleKeyboardHeight; +@property (nonatomic, readonly) UIWindow *frontWindow; + +#if TARGET_OS_IOS && __IPHONE_OS_VERSION_MAX_ALLOWED >= 100000 +@property (nonatomic, strong) UINotificationFeedbackGenerator *hapticGenerator NS_AVAILABLE_IOS(10_0); +#endif + +@end + +@implementation SVProgressHUD { + BOOL _isInitializing; +} + ++ (SVProgressHUD*)sharedView { + static dispatch_once_t once; + + static SVProgressHUD *sharedView; +#if !defined(SV_APP_EXTENSIONS) + dispatch_once(&once, ^{ sharedView = [[self alloc] initWithFrame:[[[UIApplication sharedApplication] delegate] window].bounds]; }); +#else + dispatch_once(&once, ^{ sharedView = [[self alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; }); +#endif + return sharedView; +} + + +#pragma mark - Setters + ++ (void)setStatus:(NSString*)status { + [[self sharedView] setStatus:status]; +} + ++ (void)setDefaultStyle:(SVProgressHUDStyle)style { + [self sharedView].defaultStyle = style; +} + ++ (void)setDefaultMaskType:(SVProgressHUDMaskType)maskType { + [self sharedView].defaultMaskType = maskType; +} + ++ (void)setDefaultAnimationType:(SVProgressHUDAnimationType)type { + [self sharedView].defaultAnimationType = type; +} + ++ (void)setContainerView:(nullable UIView*)containerView { + [self sharedView].containerView = containerView; +} + ++ (void)setMinimumSize:(CGSize)minimumSize { + [self sharedView].minimumSize = minimumSize; +} + ++ (void)setRingThickness:(CGFloat)ringThickness { + [self sharedView].ringThickness = ringThickness; +} + ++ (void)setRingRadius:(CGFloat)radius { + [self sharedView].ringRadius = radius; +} + ++ (void)setRingNoTextRadius:(CGFloat)radius { + [self sharedView].ringNoTextRadius = radius; +} + ++ (void)setCornerRadius:(CGFloat)cornerRadius { + [self sharedView].cornerRadius = cornerRadius; +} + ++ (void)setBorderColor:(nonnull UIColor*)color { + [self sharedView].hudView.layer.borderColor = color.CGColor; +} + ++ (void)setBorderWidth:(CGFloat)width { + [self sharedView].hudView.layer.borderWidth = width; +} + ++ (void)setFont:(UIFont*)font { + [self sharedView].font = font; +} + ++ (void)setForegroundColor:(UIColor*)color { + [self sharedView].foregroundColor = color; + [self setDefaultStyle:SVProgressHUDStyleCustom]; +} + ++ (void)setBackgroundColor:(UIColor*)color { + [self sharedView].backgroundColor = color; + [self setDefaultStyle:SVProgressHUDStyleCustom]; +} + ++ (void)setBackgroundLayerColor:(UIColor*)color { + [self sharedView].backgroundLayerColor = color; +} + ++ (void)setImageViewSize:(CGSize)size { + [self sharedView].imageViewSize = size; +} + ++ (void)setShouldTintImages:(BOOL)shouldTintImages { + [self sharedView].shouldTintImages = shouldTintImages; +} + ++ (void)setInfoImage:(UIImage*)image { + [self sharedView].infoImage = image; +} + ++ (void)setSuccessImage:(UIImage*)image { + [self sharedView].successImage = image; +} + ++ (void)setErrorImage:(UIImage*)image { + [self sharedView].errorImage = image; +} + ++ (void)setViewForExtension:(UIView*)view { + [self sharedView].viewForExtension = view; +} + ++ (void)setGraceTimeInterval:(NSTimeInterval)interval { + [self sharedView].graceTimeInterval = interval; +} + ++ (void)setMinimumDismissTimeInterval:(NSTimeInterval)interval { + [self sharedView].minimumDismissTimeInterval = interval; +} + ++ (void)setMaximumDismissTimeInterval:(NSTimeInterval)interval { + [self sharedView].maximumDismissTimeInterval = interval; +} + ++ (void)setFadeInAnimationDuration:(NSTimeInterval)duration { + [self sharedView].fadeInAnimationDuration = duration; +} + ++ (void)setFadeOutAnimationDuration:(NSTimeInterval)duration { + [self sharedView].fadeOutAnimationDuration = duration; +} + ++ (void)setMaxSupportedWindowLevel:(UIWindowLevel)windowLevel { + [self sharedView].maxSupportedWindowLevel = windowLevel; +} + ++ (void)setHapticsEnabled:(BOOL)hapticsEnabled { + [self sharedView].hapticsEnabled = hapticsEnabled; +} + +#pragma mark - Show Methods + ++ (void)show { + [self showWithStatus:nil]; +} + ++ (void)showWithMaskType:(SVProgressHUDMaskType)maskType { + SVProgressHUDMaskType existingMaskType = [self sharedView].defaultMaskType; + [self setDefaultMaskType:maskType]; + [self show]; + [self setDefaultMaskType:existingMaskType]; +} + ++ (void)showWithStatus:(NSString*)status { + [self showProgress:SVProgressHUDUndefinedProgress status:status]; +} + ++ (void)showWithStatus:(NSString*)status maskType:(SVProgressHUDMaskType)maskType { + SVProgressHUDMaskType existingMaskType = [self sharedView].defaultMaskType; + [self setDefaultMaskType:maskType]; + [self showWithStatus:status]; + [self setDefaultMaskType:existingMaskType]; +} + ++ (void)showProgress:(float)progress { + [self showProgress:progress status:nil]; +} + ++ (void)showProgress:(float)progress maskType:(SVProgressHUDMaskType)maskType { + SVProgressHUDMaskType existingMaskType = [self sharedView].defaultMaskType; + [self setDefaultMaskType:maskType]; + [self showProgress:progress]; + [self setDefaultMaskType:existingMaskType]; +} + ++ (void)showProgress:(float)progress status:(NSString*)status { + [[self sharedView] showProgress:progress status:status]; +} + ++ (void)showProgress:(float)progress status:(NSString*)status maskType:(SVProgressHUDMaskType)maskType { + SVProgressHUDMaskType existingMaskType = [self sharedView].defaultMaskType; + [self setDefaultMaskType:maskType]; + [self showProgress:progress status:status]; + [self setDefaultMaskType:existingMaskType]; +} + + +#pragma mark - Show, then automatically dismiss methods + ++ (void)showInfoWithStatus:(NSString*)status { + [self showImage:[self sharedView].infoImage status:status]; + +#if TARGET_OS_IOS && __IPHONE_OS_VERSION_MAX_ALLOWED >= 100000 + if (@available(iOS 10.0, *)) { + dispatch_async(dispatch_get_main_queue(), ^{ + [[self sharedView].hapticGenerator notificationOccurred:UINotificationFeedbackTypeWarning]; + }); + } +#endif +} + ++ (void)showInfoWithStatus:(NSString*)status maskType:(SVProgressHUDMaskType)maskType { + SVProgressHUDMaskType existingMaskType = [self sharedView].defaultMaskType; + [self setDefaultMaskType:maskType]; + [self showInfoWithStatus:status]; + [self setDefaultMaskType:existingMaskType]; +} + ++ (void)showSuccessWithStatus:(NSString*)status { + [self showImage:[self sharedView].successImage status:status]; + +#if TARGET_OS_IOS && __IPHONE_OS_VERSION_MAX_ALLOWED >= 100000 + if (@available(iOS 10, *)) { + dispatch_async(dispatch_get_main_queue(), ^{ + [[self sharedView].hapticGenerator notificationOccurred:UINotificationFeedbackTypeSuccess]; + }); + } +#endif +} + ++ (void)showSuccessWithStatus:(NSString*)status maskType:(SVProgressHUDMaskType)maskType { + SVProgressHUDMaskType existingMaskType = [self sharedView].defaultMaskType; + [self setDefaultMaskType:maskType]; + [self showSuccessWithStatus:status]; + [self setDefaultMaskType:existingMaskType]; + +#if TARGET_OS_IOS && __IPHONE_OS_VERSION_MAX_ALLOWED >= 100000 + if (@available(iOS 10.0, *)) { + dispatch_async(dispatch_get_main_queue(), ^{ + [[self sharedView].hapticGenerator notificationOccurred:UINotificationFeedbackTypeSuccess]; + }); + } +#endif +} + ++ (void)showErrorWithStatus:(NSString*)status { + [self showImage:[self sharedView].errorImage status:status]; + +#if TARGET_OS_IOS && __IPHONE_OS_VERSION_MAX_ALLOWED >= 100000 + if (@available(iOS 10.0, *)) { + dispatch_async(dispatch_get_main_queue(), ^{ + [[self sharedView].hapticGenerator notificationOccurred:UINotificationFeedbackTypeError]; + }); + } +#endif +} + ++ (void)showErrorWithStatus:(NSString*)status maskType:(SVProgressHUDMaskType)maskType { + SVProgressHUDMaskType existingMaskType = [self sharedView].defaultMaskType; + [self setDefaultMaskType:maskType]; + [self showErrorWithStatus:status]; + [self setDefaultMaskType:existingMaskType]; + +#if TARGET_OS_IOS && __IPHONE_OS_VERSION_MAX_ALLOWED >= 100000 + if (@available(iOS 10.0, *)) { + dispatch_async(dispatch_get_main_queue(), ^{ + [[self sharedView].hapticGenerator notificationOccurred:UINotificationFeedbackTypeError]; + }); + } +#endif +} + ++ (void)showImage:(UIImage*)image status:(NSString*)status { + NSTimeInterval displayInterval = [self displayDurationForString:status]; + [[self sharedView] showImage:image status:status duration:displayInterval]; +} + ++ (void)showImage:(UIImage*)image status:(NSString*)status maskType:(SVProgressHUDMaskType)maskType { + SVProgressHUDMaskType existingMaskType = [self sharedView].defaultMaskType; + [self setDefaultMaskType:maskType]; + [self showImage:image status:status]; + [self setDefaultMaskType:existingMaskType]; +} + + +#pragma mark - Dismiss Methods + ++ (void)popActivity { + if([self sharedView].activityCount > 0) { + [self sharedView].activityCount--; + } + if([self sharedView].activityCount == 0) { + [[self sharedView] dismiss]; + } +} + ++ (void)dismiss { + [self dismissWithDelay:0.0 completion:nil]; +} + ++ (void)dismissWithCompletion:(SVProgressHUDDismissCompletion)completion { + [self dismissWithDelay:0.0 completion:completion]; +} + ++ (void)dismissWithDelay:(NSTimeInterval)delay { + [self dismissWithDelay:delay completion:nil]; +} + ++ (void)dismissWithDelay:(NSTimeInterval)delay completion:(SVProgressHUDDismissCompletion)completion { + [[self sharedView] dismissWithDelay:delay completion:completion]; +} + + +#pragma mark - Offset + ++ (void)setOffsetFromCenter:(UIOffset)offset { + [self sharedView].offsetFromCenter = offset; +} + ++ (void)resetOffsetFromCenter { + [self setOffsetFromCenter:UIOffsetZero]; +} + + +#pragma mark - Instance Methods + +- (instancetype)initWithFrame:(CGRect)frame { + if((self = [super initWithFrame:frame])) { + _isInitializing = YES; + + self.userInteractionEnabled = NO; + self.activityCount = 0; + + self.backgroundView.alpha = 0.0f; + self.imageView.alpha = 0.0f; + self.statusLabel.alpha = 0.0f; + self.indefiniteAnimatedView.alpha = 0.0f; + self.ringView.alpha = self.backgroundRingView.alpha = 0.0f; + + + _backgroundColor = [UIColor whiteColor]; + _foregroundColor = [UIColor blackColor]; + _backgroundLayerColor = [UIColor colorWithWhite:0 alpha:0.4]; + + // Set default values + _defaultMaskType = SVProgressHUDMaskTypeNone; + _defaultStyle = SVProgressHUDStyleLight; + _defaultAnimationType = SVProgressHUDAnimationTypeFlat; + _minimumSize = CGSizeZero; + _font = [UIFont preferredFontForTextStyle:UIFontTextStyleSubheadline]; + + _imageViewSize = CGSizeMake(28.0f, 28.0f); + _shouldTintImages = YES; + + NSBundle *bundle = [NSBundle bundleForClass:[SVProgressHUD class]]; + NSURL *url = [bundle URLForResource:@"SVProgressHUD" withExtension:@"bundle"]; + NSBundle *imageBundle = [NSBundle bundleWithURL:url]; + + _infoImage = [UIImage imageWithContentsOfFile:[imageBundle pathForResource:@"info" ofType:@"png"]]; + _successImage = [UIImage imageWithContentsOfFile:[imageBundle pathForResource:@"success" ofType:@"png"]]; + _errorImage = [UIImage imageWithContentsOfFile:[imageBundle pathForResource:@"error" ofType:@"png"]]; + + _ringThickness = 2.0f; + _ringRadius = 18.0f; + _ringNoTextRadius = 24.0f; + + _cornerRadius = 14.0f; + + _graceTimeInterval = 0.0f; + _minimumDismissTimeInterval = 5.0; + _maximumDismissTimeInterval = CGFLOAT_MAX; + + _fadeInAnimationDuration = SVProgressHUDDefaultAnimationDuration; + _fadeOutAnimationDuration = SVProgressHUDDefaultAnimationDuration; + + _maxSupportedWindowLevel = UIWindowLevelNormal; + + _hapticsEnabled = NO; + + // Accessibility support + self.accessibilityIdentifier = @"SVProgressHUD"; + self.isAccessibilityElement = YES; + + _isInitializing = NO; + } + return self; +} + +- (void)updateHUDFrame { + // Check if an image or progress ring is displayed + BOOL imageUsed = (self.imageView.image) && !(self.imageView.hidden); + BOOL progressUsed = self.imageView.hidden; + + // Calculate size of string + CGRect labelRect = CGRectZero; + CGFloat labelHeight = 0.0f; + CGFloat labelWidth = 0.0f; + + if(self.statusLabel.text) { + CGSize constraintSize = CGSizeMake(200.0f, 300.0f); + labelRect = [self.statusLabel.text boundingRectWithSize:constraintSize + options:(NSStringDrawingOptions)(NSStringDrawingUsesFontLeading | NSStringDrawingTruncatesLastVisibleLine | NSStringDrawingUsesLineFragmentOrigin) + attributes:@{NSFontAttributeName: self.statusLabel.font} + context:NULL]; + labelHeight = ceilf(CGRectGetHeight(labelRect)); + labelWidth = ceilf(CGRectGetWidth(labelRect)); + } + + // Calculate hud size based on content + // For the beginning use default values, these + // might get update if string is too large etc. + CGFloat hudWidth; + CGFloat hudHeight; + + CGFloat contentWidth = 0.0f; + CGFloat contentHeight = 0.0f; + + if(imageUsed || progressUsed) { + contentWidth = CGRectGetWidth(imageUsed ? self.imageView.frame : self.indefiniteAnimatedView.frame); + contentHeight = CGRectGetHeight(imageUsed ? self.imageView.frame : self.indefiniteAnimatedView.frame); + } + + // |-spacing-content-spacing-| + hudWidth = SVProgressHUDHorizontalSpacing + MAX(labelWidth, contentWidth) + SVProgressHUDHorizontalSpacing; + + // |-spacing-content-(labelSpacing-label-)spacing-| + hudHeight = SVProgressHUDVerticalSpacing + labelHeight + contentHeight + SVProgressHUDVerticalSpacing; + if(self.statusLabel.text && (imageUsed || progressUsed)){ + // Add spacing if both content and label are used + hudHeight += SVProgressHUDLabelSpacing; + } + + // Update values on subviews + self.hudView.bounds = CGRectMake(0.0f, 0.0f, MAX(self.minimumSize.width, hudWidth), MAX(self.minimumSize.height, hudHeight)); + + // Animate value update + [CATransaction begin]; + [CATransaction setDisableActions:YES]; + + // Spinner and image view + CGFloat centerY; + if(self.statusLabel.text) { + CGFloat yOffset = MAX(SVProgressHUDVerticalSpacing, (self.minimumSize.height - contentHeight - SVProgressHUDLabelSpacing - labelHeight) / 2.0f); + centerY = yOffset + contentHeight / 2.0f; + } else { + centerY = CGRectGetMidY(self.hudView.bounds); + } + self.indefiniteAnimatedView.center = CGPointMake(CGRectGetMidX(self.hudView.bounds), centerY); + if(self.progress != SVProgressHUDUndefinedProgress) { + self.backgroundRingView.center = self.ringView.center = CGPointMake(CGRectGetMidX(self.hudView.bounds), centerY); + } + self.imageView.center = CGPointMake(CGRectGetMidX(self.hudView.bounds), centerY); + + // Label + if(imageUsed || progressUsed) { + centerY = CGRectGetMaxY(imageUsed ? self.imageView.frame : self.indefiniteAnimatedView.frame) + SVProgressHUDLabelSpacing + labelHeight / 2.0f; + } else { + centerY = CGRectGetMidY(self.hudView.bounds); + } + self.statusLabel.frame = labelRect; + self.statusLabel.center = CGPointMake(CGRectGetMidX(self.hudView.bounds), centerY); + + [CATransaction commit]; +} + +#if TARGET_OS_IOS +- (void)updateMotionEffectForOrientation:(UIInterfaceOrientation)orientation { + UIInterpolatingMotionEffectType xMotionEffectType = UIInterfaceOrientationIsPortrait(orientation) ? UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis : UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis; + UIInterpolatingMotionEffectType yMotionEffectType = UIInterfaceOrientationIsPortrait(orientation) ? UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis : UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis; + [self updateMotionEffectForXMotionEffectType:xMotionEffectType yMotionEffectType:yMotionEffectType]; +} +#endif + +- (void)updateMotionEffectForXMotionEffectType:(UIInterpolatingMotionEffectType)xMotionEffectType yMotionEffectType:(UIInterpolatingMotionEffectType)yMotionEffectType { + UIInterpolatingMotionEffect *effectX = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.x" type:xMotionEffectType]; + effectX.minimumRelativeValue = @(-SVProgressHUDParallaxDepthPoints); + effectX.maximumRelativeValue = @(SVProgressHUDParallaxDepthPoints); + + UIInterpolatingMotionEffect *effectY = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.y" type:yMotionEffectType]; + effectY.minimumRelativeValue = @(-SVProgressHUDParallaxDepthPoints); + effectY.maximumRelativeValue = @(SVProgressHUDParallaxDepthPoints); + + UIMotionEffectGroup *effectGroup = [UIMotionEffectGroup new]; + effectGroup.motionEffects = @[effectX, effectY]; + + // Clear old motion effect, then add new motion effects + self.hudView.motionEffects = @[]; + [self.hudView addMotionEffect:effectGroup]; +} + +- (void)updateViewHierarchy { + // Add the overlay to the application window if necessary + if(!self.controlView.superview) { + if(self.containerView){ + [self.containerView addSubview:self.controlView]; + } else { +#if !defined(SV_APP_EXTENSIONS) + [self.frontWindow addSubview:self.controlView]; +#else + // If SVProgressHUD is used inside an app extension add it to the given view + if(self.viewForExtension) { + [self.viewForExtension addSubview:self.controlView]; + } +#endif + } + } else { + // The HUD is already on screen, but maybe not in front. Therefore + // ensure that overlay will be on top of rootViewController (which may + // be changed during runtime). + [self.controlView.superview bringSubviewToFront:self.controlView]; + } + + // Add self to the overlay view + if(!self.superview) { + [self.controlView addSubview:self]; + } +} + +- (void)setStatus:(NSString*)status { + self.statusLabel.text = status; + self.statusLabel.hidden = status.length == 0; + [self updateHUDFrame]; +} + +- (void)setGraceTimer:(NSTimer*)timer { + if(_graceTimer) { + [_graceTimer invalidate]; + _graceTimer = nil; + } + if(timer) { + _graceTimer = timer; + } +} + +- (void)setFadeOutTimer:(NSTimer*)timer { + if(_fadeOutTimer) { + [_fadeOutTimer invalidate]; + _fadeOutTimer = nil; + } + if(timer) { + _fadeOutTimer = timer; + } +} + + +#pragma mark - Notifications and their handling + +- (void)registerNotifications { +#if TARGET_OS_IOS + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(positionHUD:) + name:UIApplicationDidChangeStatusBarOrientationNotification + object:nil]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(positionHUD:) + name:UIKeyboardWillHideNotification + object:nil]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(positionHUD:) + name:UIKeyboardDidHideNotification + object:nil]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(positionHUD:) + name:UIKeyboardWillShowNotification + object:nil]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(positionHUD:) + name:UIKeyboardDidShowNotification + object:nil]; +#endif + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(positionHUD:) + name:UIApplicationDidBecomeActiveNotification + object:nil]; +} + +- (NSDictionary*)notificationUserInfo { + return (self.statusLabel.text ? @{SVProgressHUDStatusUserInfoKey : self.statusLabel.text} : nil); +} + +- (void)positionHUD:(NSNotification*)notification { + CGFloat keyboardHeight = 0.0f; + double animationDuration = 0.0; + +#if !defined(SV_APP_EXTENSIONS) && TARGET_OS_IOS + self.frame = [[[UIApplication sharedApplication] delegate] window].bounds; + UIInterfaceOrientation orientation = UIApplication.sharedApplication.statusBarOrientation; +#elif !defined(SV_APP_EXTENSIONS) && !TARGET_OS_IOS + self.frame= [UIApplication sharedApplication].keyWindow.bounds; +#else + if (self.viewForExtension) { + self.frame = self.viewForExtension.frame; + } else { + self.frame = UIScreen.mainScreen.bounds; + } +#if TARGET_OS_IOS + UIInterfaceOrientation orientation = CGRectGetWidth(self.frame) > CGRectGetHeight(self.frame) ? UIInterfaceOrientationLandscapeLeft : UIInterfaceOrientationPortrait; +#endif +#endif + +#if TARGET_OS_IOS + // Get keyboardHeight in regard to current state + if(notification) { + NSDictionary* keyboardInfo = [notification userInfo]; + CGRect keyboardFrame = [keyboardInfo[UIKeyboardFrameBeginUserInfoKey] CGRectValue]; + animationDuration = [keyboardInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue]; + + if(notification.name == UIKeyboardWillShowNotification || notification.name == UIKeyboardDidShowNotification) { + keyboardHeight = CGRectGetWidth(keyboardFrame); + + if(UIInterfaceOrientationIsPortrait(orientation)) { + keyboardHeight = CGRectGetHeight(keyboardFrame); + } + } + } else { + keyboardHeight = self.visibleKeyboardHeight; + } +#endif + + // Get the currently active frame of the display (depends on orientation) + CGRect orientationFrame = self.bounds; + +#if !defined(SV_APP_EXTENSIONS) && TARGET_OS_IOS + CGRect statusBarFrame = UIApplication.sharedApplication.statusBarFrame; +#else + CGRect statusBarFrame = CGRectZero; +#endif + +#if TARGET_OS_IOS + // Update the motion effects in regard to orientation + [self updateMotionEffectForOrientation:orientation]; +#else + [self updateMotionEffectForXMotionEffectType:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis yMotionEffectType:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis]; +#endif + + // Calculate available height for display + CGFloat activeHeight = CGRectGetHeight(orientationFrame); + if(keyboardHeight > 0) { + activeHeight += CGRectGetHeight(statusBarFrame) * 2; + } + activeHeight -= keyboardHeight; + + CGFloat posX = CGRectGetMidX(orientationFrame); + CGFloat posY = floorf(activeHeight*0.45f); + + CGFloat rotateAngle = 0.0; + CGPoint newCenter = CGPointMake(posX, posY); + + if(notification) { + // Animate update if notification was present + [UIView animateWithDuration:animationDuration + delay:0 + options:(UIViewAnimationOptions) (UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionBeginFromCurrentState) + animations:^{ + [self moveToPoint:newCenter rotateAngle:rotateAngle]; + [self.hudView setNeedsDisplay]; + } completion:nil]; + } else { + [self moveToPoint:newCenter rotateAngle:rotateAngle]; + } +} + +- (void)moveToPoint:(CGPoint)newCenter rotateAngle:(CGFloat)angle { + self.hudView.transform = CGAffineTransformMakeRotation(angle); + if (self.containerView) { + self.hudView.center = CGPointMake(self.containerView.center.x + self.offsetFromCenter.horizontal, self.containerView.center.y + self.offsetFromCenter.vertical); + } else { + self.hudView.center = CGPointMake(newCenter.x + self.offsetFromCenter.horizontal, newCenter.y + self.offsetFromCenter.vertical); + } +} + + +#pragma mark - Event handling + +- (void)controlViewDidReceiveTouchEvent:(id)sender forEvent:(UIEvent*)event { + [[NSNotificationCenter defaultCenter] postNotificationName:SVProgressHUDDidReceiveTouchEventNotification + object:self + userInfo:[self notificationUserInfo]]; + + UITouch *touch = event.allTouches.anyObject; + CGPoint touchLocation = [touch locationInView:self]; + + if(CGRectContainsPoint(self.hudView.frame, touchLocation)) { + [[NSNotificationCenter defaultCenter] postNotificationName:SVProgressHUDDidTouchDownInsideNotification + object:self + userInfo:[self notificationUserInfo]]; + } +} + + +#pragma mark - Master show/dismiss methods + +- (void)showProgress:(float)progress status:(NSString*)status { + __weak SVProgressHUD *weakSelf = self; + [[NSOperationQueue mainQueue] addOperationWithBlock:^{ + __strong SVProgressHUD *strongSelf = weakSelf; + if(strongSelf){ + if(strongSelf.fadeOutTimer) { + strongSelf.activityCount = 0; + } + + // Stop timer + strongSelf.fadeOutTimer = nil; + strongSelf.graceTimer = nil; + + // Update / Check view hierarchy to ensure the HUD is visible + [strongSelf updateViewHierarchy]; + + // Reset imageView and fadeout timer if an image is currently displayed + strongSelf.imageView.hidden = YES; + strongSelf.imageView.image = nil; + + // Update text and set progress to the given value + strongSelf.statusLabel.hidden = status.length == 0; + strongSelf.statusLabel.text = status; + strongSelf.progress = progress; + + // Choose the "right" indicator depending on the progress + if(progress >= 0) { + // Cancel the indefiniteAnimatedView, then show the ringLayer + [strongSelf cancelIndefiniteAnimatedViewAnimation]; + + // Add ring to HUD + if(!strongSelf.ringView.superview){ + [strongSelf.hudView.contentView addSubview:strongSelf.ringView]; + } + if(!strongSelf.backgroundRingView.superview){ + [strongSelf.hudView.contentView addSubview:strongSelf.backgroundRingView]; + } + + // Set progress animated + [CATransaction begin]; + [CATransaction setDisableActions:YES]; + strongSelf.ringView.strokeEnd = progress; + [CATransaction commit]; + + // Update the activity count + if(progress == 0) { + strongSelf.activityCount++; + } + } else { + // Cancel the ringLayer animation, then show the indefiniteAnimatedView + [strongSelf cancelRingLayerAnimation]; + + // Add indefiniteAnimatedView to HUD + [strongSelf.hudView.contentView addSubview:strongSelf.indefiniteAnimatedView]; + if([strongSelf.indefiniteAnimatedView respondsToSelector:@selector(startAnimating)]) { + [(id)strongSelf.indefiniteAnimatedView startAnimating]; + } + + // Update the activity count + strongSelf.activityCount++; + } + + // Fade in delayed if a grace time is set + if (self.graceTimeInterval > 0.0 && self.backgroundView.alpha == 0.0f) { + strongSelf.graceTimer = [NSTimer timerWithTimeInterval:self.graceTimeInterval target:strongSelf selector:@selector(fadeIn:) userInfo:nil repeats:NO]; + [[NSRunLoop mainRunLoop] addTimer:strongSelf.graceTimer forMode:NSRunLoopCommonModes]; + } else { + [strongSelf fadeIn:nil]; + } + + // Tell the Haptics Generator to prepare for feedback, which may come soon +#if TARGET_OS_IOS && __IPHONE_OS_VERSION_MAX_ALLOWED >= 100000 + if (@available(iOS 10.0, *)) { + [strongSelf.hapticGenerator prepare]; + } +#endif + } + }]; +} + +- (void)showImage:(UIImage*)image status:(NSString*)status duration:(NSTimeInterval)duration { + __weak SVProgressHUD *weakSelf = self; + [[NSOperationQueue mainQueue] addOperationWithBlock:^{ + __strong SVProgressHUD *strongSelf = weakSelf; + if(strongSelf){ + // Stop timer + strongSelf.fadeOutTimer = nil; + strongSelf.graceTimer = nil; + + // Update / Check view hierarchy to ensure the HUD is visible + [strongSelf updateViewHierarchy]; + + // Reset progress and cancel any running animation + strongSelf.progress = SVProgressHUDUndefinedProgress; + [strongSelf cancelRingLayerAnimation]; + [strongSelf cancelIndefiniteAnimatedViewAnimation]; + + // Update imageView + if (self.shouldTintImages) { + if (image.renderingMode != UIImageRenderingModeAlwaysTemplate) { + strongSelf.imageView.image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + } + strongSelf.imageView.tintColor = strongSelf.foregroundColorForStyle;; + } else { + strongSelf.imageView.image = image; + } + strongSelf.imageView.hidden = NO; + + // Update text + strongSelf.statusLabel.hidden = status.length == 0; + strongSelf.statusLabel.text = status; + + // Fade in delayed if a grace time is set + // An image will be dismissed automatically. Thus pass the duration as userInfo. + if (self.graceTimeInterval > 0.0 && self.backgroundView.alpha == 0.0f) { + strongSelf.graceTimer = [NSTimer timerWithTimeInterval:self.graceTimeInterval target:strongSelf selector:@selector(fadeIn:) userInfo:@(duration) repeats:NO]; + [[NSRunLoop mainRunLoop] addTimer:strongSelf.graceTimer forMode:NSRunLoopCommonModes]; + } else { + [strongSelf fadeIn:@(duration)]; + } + } + }]; +} + +- (void)fadeIn:(id)data { + // Update the HUDs frame to the new content and position HUD + [self updateHUDFrame]; + [self positionHUD:nil]; + + // Update accessibility as well as user interaction + if(self.defaultMaskType != SVProgressHUDMaskTypeNone) { + self.controlView.userInteractionEnabled = YES; + self.accessibilityLabel = self.statusLabel.text ?: NSLocalizedString(@"Loading", nil); + self.isAccessibilityElement = YES; + } else { + self.controlView.userInteractionEnabled = NO; + self.hudView.accessibilityLabel = self.statusLabel.text ?: NSLocalizedString(@"Loading", nil); + self.hudView.isAccessibilityElement = YES; + } + + // Get duration + id duration = [data isKindOfClass:[NSTimer class]] ? ((NSTimer *)data).userInfo : data; + + // Show if not already visible + if(self.backgroundView.alpha != 1.0f) { + // Post notification to inform user + [[NSNotificationCenter defaultCenter] postNotificationName:SVProgressHUDWillAppearNotification + object:self + userInfo:[self notificationUserInfo]]; + + // Shrink HUD to to make a nice appear / pop up animation + self.hudView.transform = self.hudView.transform = CGAffineTransformScale(self.hudView.transform, 1/1.5f, 1/1.5f); + + __block void (^animationsBlock)(void) = ^{ + // Zoom HUD a little to make a nice appear / pop up animation + self.hudView.transform = CGAffineTransformIdentity; + + // Fade in all effects (colors, blur, etc.) + [self fadeInEffects]; + }; + + __block void (^completionBlock)(void) = ^{ + // Check if we really achieved to show the HUD (<=> alpha) + // and the change of these values has not been cancelled in between e.g. due to a dismissal + if(self.backgroundView.alpha == 1.0f){ + // Register observer <=> we now have to handle orientation changes etc. + [self registerNotifications]; + + // Post notification to inform user + [[NSNotificationCenter defaultCenter] postNotificationName:SVProgressHUDDidAppearNotification + object:self + userInfo:[self notificationUserInfo]]; + + // Update accessibility + UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, nil); + UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, self.statusLabel.text); + + // Dismiss automatically if a duration was passed as userInfo. We start a timer + // which then will call dismiss after the predefined duration + if(duration){ + self.fadeOutTimer = [NSTimer timerWithTimeInterval:[(NSNumber *)duration doubleValue] target:self selector:@selector(dismiss) userInfo:nil repeats:NO]; + [[NSRunLoop mainRunLoop] addTimer:self.fadeOutTimer forMode:NSRunLoopCommonModes]; + } + } + }; + + // Animate appearance + if (self.fadeInAnimationDuration > 0) { + // Animate appearance + [UIView animateWithDuration:self.fadeInAnimationDuration + delay:0 + options:(UIViewAnimationOptions) (UIViewAnimationOptionAllowUserInteraction | UIViewAnimationCurveEaseIn | UIViewAnimationOptionBeginFromCurrentState) + animations:^{ + animationsBlock(); + } completion:^(BOOL finished) { + completionBlock(); + }]; + } else { + animationsBlock(); + completionBlock(); + } + + // Inform iOS to redraw the view hierarchy + [self setNeedsDisplay]; + } else { + // Update accessibility + UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, nil); + UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, self.statusLabel.text); + + // Dismiss automatically if a duration was passed as userInfo. We start a timer + // which then will call dismiss after the predefined duration + if(duration){ + self.fadeOutTimer = [NSTimer timerWithTimeInterval:[(NSNumber *)duration doubleValue] target:self selector:@selector(dismiss) userInfo:nil repeats:NO]; + [[NSRunLoop mainRunLoop] addTimer:self.fadeOutTimer forMode:NSRunLoopCommonModes]; + } + } +} + +- (void)dismiss { + [self dismissWithDelay:0.0 completion:nil]; +} + +- (void)dismissWithDelay:(NSTimeInterval)delay completion:(SVProgressHUDDismissCompletion)completion { + __weak SVProgressHUD *weakSelf = self; + [[NSOperationQueue mainQueue] addOperationWithBlock:^{ + __strong SVProgressHUD *strongSelf = weakSelf; + if(strongSelf){ + // Stop timer + strongSelf.graceTimer = nil; + + // Post notification to inform user + [[NSNotificationCenter defaultCenter] postNotificationName:SVProgressHUDWillDisappearNotification + object:nil + userInfo:[strongSelf notificationUserInfo]]; + + // Reset activity count + strongSelf.activityCount = 0; + + __block void (^animationsBlock)(void) = ^{ + // Shrink HUD a little to make a nice disappear animation + strongSelf.hudView.transform = CGAffineTransformScale(strongSelf.hudView.transform, 1/1.3f, 1/1.3f); + + // Fade out all effects (colors, blur, etc.) + [strongSelf fadeOutEffects]; + }; + + __block void (^completionBlock)(void) = ^{ + // Check if we really achieved to dismiss the HUD (<=> alpha values are applied) + // and the change of these values has not been cancelled in between e.g. due to a new show + if(self.backgroundView.alpha == 0.0f){ + // Clean up view hierarchy (overlays) + [strongSelf.controlView removeFromSuperview]; + [strongSelf.backgroundView removeFromSuperview]; + [strongSelf.hudView removeFromSuperview]; + [strongSelf removeFromSuperview]; + + // Reset progress and cancel any running animation + strongSelf.progress = SVProgressHUDUndefinedProgress; + [strongSelf cancelRingLayerAnimation]; + [strongSelf cancelIndefiniteAnimatedViewAnimation]; + + // Remove observer <=> we do not have to handle orientation changes etc. + [[NSNotificationCenter defaultCenter] removeObserver:strongSelf]; + + // Post notification to inform user + [[NSNotificationCenter defaultCenter] postNotificationName:SVProgressHUDDidDisappearNotification + object:strongSelf + userInfo:[strongSelf notificationUserInfo]]; + + // Tell the rootViewController to update the StatusBar appearance +#if !defined(SV_APP_EXTENSIONS) && TARGET_OS_IOS + UIViewController *rootController = [[UIApplication sharedApplication] keyWindow].rootViewController; + [rootController setNeedsStatusBarAppearanceUpdate]; +#endif + + // Run an (optional) completionHandler + if (completion) { + completion(); + } + } + }; + + // UIViewAnimationOptionBeginFromCurrentState AND a delay doesn't always work as expected + // When UIViewAnimationOptionBeginFromCurrentState is set, animateWithDuration: evaluates the current + // values to check if an animation is necessary. The evaluation happens at function call time and not + // after the delay => the animation is sometimes skipped. Therefore we delay using dispatch_after. + + dispatch_time_t dipatchTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)); + dispatch_after(dipatchTime, dispatch_get_main_queue(), ^{ + if (strongSelf.fadeOutAnimationDuration > 0) { + // Animate appearance + [UIView animateWithDuration:strongSelf.fadeOutAnimationDuration + delay:0 + options:(UIViewAnimationOptions) (UIViewAnimationOptionAllowUserInteraction | UIViewAnimationCurveEaseOut | UIViewAnimationOptionBeginFromCurrentState) + animations:^{ + animationsBlock(); + } completion:^(BOOL finished) { + completionBlock(); + }]; + } else { + animationsBlock(); + completionBlock(); + } + }); + + // Inform iOS to redraw the view hierarchy + [strongSelf setNeedsDisplay]; + } + }]; +} + + +#pragma mark - Ring progress animation + +- (UIView*)indefiniteAnimatedView { + // Get the correct spinner for defaultAnimationType + if(self.defaultAnimationType == SVProgressHUDAnimationTypeFlat){ + // Check if spinner exists and is an object of different class + if(_indefiniteAnimatedView && ![_indefiniteAnimatedView isKindOfClass:[SVIndefiniteAnimatedView class]]){ + [_indefiniteAnimatedView removeFromSuperview]; + _indefiniteAnimatedView = nil; + } + + if(!_indefiniteAnimatedView){ + _indefiniteAnimatedView = [[SVIndefiniteAnimatedView alloc] initWithFrame:CGRectZero]; + } + + // Update styling + SVIndefiniteAnimatedView *indefiniteAnimatedView = (SVIndefiniteAnimatedView*)_indefiniteAnimatedView; + indefiniteAnimatedView.strokeColor = self.foregroundColorForStyle; + indefiniteAnimatedView.strokeThickness = self.ringThickness; + indefiniteAnimatedView.radius = self.statusLabel.text ? self.ringRadius : self.ringNoTextRadius; + } else { + // Check if spinner exists and is an object of different class + if(_indefiniteAnimatedView && ![_indefiniteAnimatedView isKindOfClass:[UIActivityIndicatorView class]]){ + [_indefiniteAnimatedView removeFromSuperview]; + _indefiniteAnimatedView = nil; + } + + if(!_indefiniteAnimatedView){ + _indefiniteAnimatedView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge]; + } + + // Update styling + UIActivityIndicatorView *activityIndicatorView = (UIActivityIndicatorView*)_indefiniteAnimatedView; + activityIndicatorView.color = self.foregroundColorForStyle; + } + [_indefiniteAnimatedView sizeToFit]; + + return _indefiniteAnimatedView; +} + +- (SVProgressAnimatedView*)ringView { + if(!_ringView) { + _ringView = [[SVProgressAnimatedView alloc] initWithFrame:CGRectZero]; + } + + // Update styling + _ringView.strokeColor = self.foregroundColorForStyle; + _ringView.strokeThickness = self.ringThickness; + _ringView.radius = self.statusLabel.text ? self.ringRadius : self.ringNoTextRadius; + + return _ringView; +} + +- (SVProgressAnimatedView*)backgroundRingView { + if(!_backgroundRingView) { + _backgroundRingView = [[SVProgressAnimatedView alloc] initWithFrame:CGRectZero]; + _backgroundRingView.strokeEnd = 1.0f; + } + + // Update styling + _backgroundRingView.strokeColor = [self.foregroundColorForStyle colorWithAlphaComponent:0.1f]; + _backgroundRingView.strokeThickness = self.ringThickness; + _backgroundRingView.radius = self.statusLabel.text ? self.ringRadius : self.ringNoTextRadius; + + return _backgroundRingView; +} + +- (void)cancelRingLayerAnimation { + // Animate value update, stop animation + [CATransaction begin]; + [CATransaction setDisableActions:YES]; + + [self.hudView.layer removeAllAnimations]; + self.ringView.strokeEnd = 0.0f; + + [CATransaction commit]; + + // Remove from view + [self.ringView removeFromSuperview]; + [self.backgroundRingView removeFromSuperview]; +} + +- (void)cancelIndefiniteAnimatedViewAnimation { + // Stop animation + if([self.indefiniteAnimatedView respondsToSelector:@selector(stopAnimating)]) { + [(id)self.indefiniteAnimatedView stopAnimating]; + } + // Remove from view + [self.indefiniteAnimatedView removeFromSuperview]; +} + + +#pragma mark - Utilities + ++ (BOOL)isVisible { + // Checking one alpha value is sufficient as they are all the same + return [self sharedView].backgroundView.alpha > 0.0f; +} + + +#pragma mark - Getters + ++ (NSTimeInterval)displayDurationForString:(NSString*)string { + CGFloat minimum = MAX((CGFloat)string.length * 0.06 + 0.5, [self sharedView].minimumDismissTimeInterval); + return MIN(minimum, [self sharedView].maximumDismissTimeInterval); +} + +- (UIColor*)foregroundColorForStyle { + if(self.defaultStyle == SVProgressHUDStyleLight) { + return [UIColor blackColor]; + } else if(self.defaultStyle == SVProgressHUDStyleDark) { + return [UIColor whiteColor]; + } else { + return self.foregroundColor; + } +} + +- (UIColor*)backgroundColorForStyle { + if(self.defaultStyle == SVProgressHUDStyleLight) { + return [UIColor whiteColor]; + } else if(self.defaultStyle == SVProgressHUDStyleDark) { + return [UIColor blackColor]; + } else { + return self.backgroundColor; + } +} + +- (UIControl*)controlView { + if(!_controlView) { + _controlView = [UIControl new]; + _controlView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + _controlView.backgroundColor = [UIColor clearColor]; + _controlView.userInteractionEnabled = YES; + [_controlView addTarget:self action:@selector(controlViewDidReceiveTouchEvent:forEvent:) forControlEvents:UIControlEventTouchDown]; + } + + // Update frames +#if !defined(SV_APP_EXTENSIONS) + CGRect windowBounds = [[[UIApplication sharedApplication] delegate] window].bounds; + _controlView.frame = windowBounds; +#else + _controlView.frame = [UIScreen mainScreen].bounds; +#endif + + return _controlView; +} + +-(UIView *)backgroundView { + if(!_backgroundView){ + _backgroundView = [UIView new]; + _backgroundView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + } + if(!_backgroundView.superview){ + [self insertSubview:_backgroundView belowSubview:self.hudView]; + } + + // Update styling + if(self.defaultMaskType == SVProgressHUDMaskTypeGradient){ + if(!_backgroundRadialGradientLayer){ + _backgroundRadialGradientLayer = [SVRadialGradientLayer layer]; + } + if(!_backgroundRadialGradientLayer.superlayer){ + [_backgroundView.layer insertSublayer:_backgroundRadialGradientLayer atIndex:0]; + } + _backgroundView.backgroundColor = [UIColor clearColor]; + } else { + if(_backgroundRadialGradientLayer && _backgroundRadialGradientLayer.superlayer){ + [_backgroundRadialGradientLayer removeFromSuperlayer]; + } + if(self.defaultMaskType == SVProgressHUDMaskTypeBlack){ + _backgroundView.backgroundColor = [UIColor colorWithWhite:0 alpha:0.4]; + } else if(self.defaultMaskType == SVProgressHUDMaskTypeCustom){ + _backgroundView.backgroundColor = self.backgroundLayerColor; + } else { + _backgroundView.backgroundColor = [UIColor clearColor]; + } + } + + // Update frame + if(_backgroundView){ + _backgroundView.frame = self.bounds; + } + if(_backgroundRadialGradientLayer){ + _backgroundRadialGradientLayer.frame = self.bounds; + + // Calculate the new center of the gradient, it may change if keyboard is visible + CGPoint gradientCenter = self.center; + gradientCenter.y = (self.bounds.size.height - self.visibleKeyboardHeight)/2; + _backgroundRadialGradientLayer.gradientCenter = gradientCenter; + [_backgroundRadialGradientLayer setNeedsDisplay]; + } + + return _backgroundView; +} +- (UIVisualEffectView*)hudView { + if(!_hudView) { + _hudView = [UIVisualEffectView new]; + _hudView.layer.masksToBounds = YES; + _hudView.autoresizingMask = UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleLeftMargin; + } + if(!_hudView.superview) { + [self addSubview:_hudView]; + } + + // Update styling + _hudView.layer.cornerRadius = self.cornerRadius; + + return _hudView; +} + +- (UILabel*)statusLabel { + if(!_statusLabel) { + _statusLabel = [[UILabel alloc] initWithFrame:CGRectZero]; + _statusLabel.backgroundColor = [UIColor clearColor]; + _statusLabel.adjustsFontSizeToFitWidth = YES; + _statusLabel.textAlignment = NSTextAlignmentCenter; + _statusLabel.baselineAdjustment = UIBaselineAdjustmentAlignCenters; + _statusLabel.numberOfLines = 0; + } + if(!_statusLabel.superview) { + [self.hudView.contentView addSubview:_statusLabel]; + } + + // Update styling + _statusLabel.textColor = self.foregroundColorForStyle; + _statusLabel.font = self.font; + + return _statusLabel; +} + +- (UIImageView*)imageView { + if(_imageView && !CGSizeEqualToSize(_imageView.bounds.size, _imageViewSize)) { + [_imageView removeFromSuperview]; + _imageView = nil; + } + + if(!_imageView) { + _imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, _imageViewSize.width, _imageViewSize.height)]; + } + if(!_imageView.superview) { + [self.hudView.contentView addSubview:_imageView]; + } + + return _imageView; +} + + +#pragma mark - Helper + +- (CGFloat)visibleKeyboardHeight { +#if !defined(SV_APP_EXTENSIONS) + UIWindow *keyboardWindow = nil; + for (UIWindow *testWindow in UIApplication.sharedApplication.windows) { + if(![testWindow.class isEqual:UIWindow.class]) { + keyboardWindow = testWindow; + break; + } + } + + for (__strong UIView *possibleKeyboard in keyboardWindow.subviews) { + NSString *viewName = NSStringFromClass(possibleKeyboard.class); + if([viewName hasPrefix:@"UI"]){ + if([viewName hasSuffix:@"PeripheralHostView"] || [viewName hasSuffix:@"Keyboard"]){ + return CGRectGetHeight(possibleKeyboard.bounds); + } else if ([viewName hasSuffix:@"InputSetContainerView"]){ + for (__strong UIView *possibleKeyboardSubview in possibleKeyboard.subviews) { + viewName = NSStringFromClass(possibleKeyboardSubview.class); + if([viewName hasPrefix:@"UI"] && [viewName hasSuffix:@"InputSetHostView"]) { + CGRect convertedRect = [possibleKeyboard convertRect:possibleKeyboardSubview.frame toView:self]; + CGRect intersectedRect = CGRectIntersection(convertedRect, self.bounds); + if (!CGRectIsNull(intersectedRect)) { + return CGRectGetHeight(intersectedRect); + } + } + } + } + } + } +#endif + return 0; +} + +- (UIWindow *)frontWindow { +#if !defined(SV_APP_EXTENSIONS) + NSEnumerator *frontToBackWindows = [UIApplication.sharedApplication.windows reverseObjectEnumerator]; + for (UIWindow *window in frontToBackWindows) { + BOOL windowOnMainScreen = window.screen == UIScreen.mainScreen; + BOOL windowIsVisible = !window.hidden && window.alpha > 0; + BOOL windowLevelSupported = (window.windowLevel >= UIWindowLevelNormal && window.windowLevel <= self.maxSupportedWindowLevel); + BOOL windowKeyWindow = window.isKeyWindow; + + if(windowOnMainScreen && windowIsVisible && windowLevelSupported && windowKeyWindow) { + return window; + } + } +#endif + return nil; +} + +- (void)fadeInEffects { + if(self.defaultStyle != SVProgressHUDStyleCustom) { + // Add blur effect + UIBlurEffectStyle blurEffectStyle = self.defaultStyle == SVProgressHUDStyleDark ? UIBlurEffectStyleDark : UIBlurEffectStyleLight; + UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle:blurEffectStyle]; + self.hudView.effect = blurEffect; + + // We omit UIVibrancy effect and use a suitable background color as an alternative. + // This will make everything more readable. See the following for details: + // https://www.omnigroup.com/developer/how-to-make-text-in-a-uivisualeffectview-readable-on-any-background + + self.hudView.backgroundColor = [self.backgroundColorForStyle colorWithAlphaComponent:0.6f]; + } else { + self.hudView.backgroundColor = self.backgroundColorForStyle; + } + + // Fade in views + self.backgroundView.alpha = 1.0f; + + self.imageView.alpha = 1.0f; + self.statusLabel.alpha = 1.0f; + self.indefiniteAnimatedView.alpha = 1.0f; + self.ringView.alpha = self.backgroundRingView.alpha = 1.0f; +} + +- (void)fadeOutEffects +{ + if(self.defaultStyle != SVProgressHUDStyleCustom) { + // Remove blur effect + self.hudView.effect = nil; + } + + // Remove background color + self.hudView.backgroundColor = [UIColor clearColor]; + + // Fade out views + self.backgroundView.alpha = 0.0f; + + self.imageView.alpha = 0.0f; + self.statusLabel.alpha = 0.0f; + self.indefiniteAnimatedView.alpha = 0.0f; + self.ringView.alpha = self.backgroundRingView.alpha = 0.0f; +} + +#if TARGET_OS_IOS && __IPHONE_OS_VERSION_MAX_ALLOWED >= 100000 +- (UINotificationFeedbackGenerator *)hapticGenerator NS_AVAILABLE_IOS(10_0) { + // Only return if haptics are enabled + if(!self.hapticsEnabled) { + return nil; + } + + if(!_hapticGenerator) { + _hapticGenerator = [[UINotificationFeedbackGenerator alloc] init]; + } + return _hapticGenerator; +} +#endif + + +#pragma mark - UIAppearance Setters + +- (void)setDefaultStyle:(SVProgressHUDStyle)style { + if (!_isInitializing) _defaultStyle = style; +} + +- (void)setDefaultMaskType:(SVProgressHUDMaskType)maskType { + if (!_isInitializing) _defaultMaskType = maskType; +} + +- (void)setDefaultAnimationType:(SVProgressHUDAnimationType)animationType { + if (!_isInitializing) _defaultAnimationType = animationType; +} + +- (void)setContainerView:(UIView *)containerView { + if (!_isInitializing) _containerView = containerView; +} + +- (void)setMinimumSize:(CGSize)minimumSize { + if (!_isInitializing) _minimumSize = minimumSize; +} + +- (void)setRingThickness:(CGFloat)ringThickness { + if (!_isInitializing) _ringThickness = ringThickness; +} + +- (void)setRingRadius:(CGFloat)ringRadius { + if (!_isInitializing) _ringRadius = ringRadius; +} + +- (void)setRingNoTextRadius:(CGFloat)ringNoTextRadius { + if (!_isInitializing) _ringNoTextRadius = ringNoTextRadius; +} + +- (void)setCornerRadius:(CGFloat)cornerRadius { + if (!_isInitializing) _cornerRadius = cornerRadius; +} + +- (void)setFont:(UIFont*)font { + if (!_isInitializing) _font = font; +} + +- (void)setForegroundColor:(UIColor*)color { + if (!_isInitializing) _foregroundColor = color; +} + +- (void)setBackgroundColor:(UIColor*)color { + if (!_isInitializing) _backgroundColor = color; +} + +- (void)setBackgroundLayerColor:(UIColor*)color { + if (!_isInitializing) _backgroundLayerColor = color; +} + +- (void)setShouldTintImages:(BOOL)shouldTintImages { + if (!_isInitializing) _shouldTintImages = shouldTintImages; +} + +- (void)setInfoImage:(UIImage*)image { + if (!_isInitializing) _infoImage = image; +} + +- (void)setSuccessImage:(UIImage*)image { + if (!_isInitializing) _successImage = image; +} + +- (void)setErrorImage:(UIImage*)image { + if (!_isInitializing) _errorImage = image; +} + +- (void)setViewForExtension:(UIView*)view { + if (!_isInitializing) _viewForExtension = view; +} + +- (void)setOffsetFromCenter:(UIOffset)offset { + if (!_isInitializing) _offsetFromCenter = offset; +} + +- (void)setMinimumDismissTimeInterval:(NSTimeInterval)minimumDismissTimeInterval { + if (!_isInitializing) _minimumDismissTimeInterval = minimumDismissTimeInterval; +} + +- (void)setFadeInAnimationDuration:(NSTimeInterval)duration { + if (!_isInitializing) _fadeInAnimationDuration = duration; +} + +- (void)setFadeOutAnimationDuration:(NSTimeInterval)duration { + if (!_isInitializing) _fadeOutAnimationDuration = duration; +} + +- (void)setMaxSupportedWindowLevel:(UIWindowLevel)maxSupportedWindowLevel { + if (!_isInitializing) _maxSupportedWindowLevel = maxSupportedWindowLevel; +} + +@end diff --git a/Pods/SVProgressHUD/SVProgressHUD/SVRadialGradientLayer.h b/Pods/SVProgressHUD/SVProgressHUD/SVRadialGradientLayer.h new file mode 100644 index 00000000..68d452a2 --- /dev/null +++ b/Pods/SVProgressHUD/SVProgressHUD/SVRadialGradientLayer.h @@ -0,0 +1,14 @@ +// +// SVRadialGradientLayer.h +// SVProgressHUD, https://github.com/SVProgressHUD/SVProgressHUD +// +// Copyright (c) 2014-2018 Tobias Tiemerding. All rights reserved. +// + +#import + +@interface SVRadialGradientLayer : CALayer + +@property (nonatomic) CGPoint gradientCenter; + +@end diff --git a/Pods/SVProgressHUD/SVProgressHUD/SVRadialGradientLayer.m b/Pods/SVProgressHUD/SVProgressHUD/SVRadialGradientLayer.m new file mode 100644 index 00000000..c62e0f85 --- /dev/null +++ b/Pods/SVProgressHUD/SVProgressHUD/SVRadialGradientLayer.m @@ -0,0 +1,25 @@ +// +// SVRadialGradientLayer.m +// SVProgressHUD, https://github.com/SVProgressHUD/SVProgressHUD +// +// Copyright (c) 2014-2018 Tobias Tiemerding. All rights reserved. +// + +#import "SVRadialGradientLayer.h" + +@implementation SVRadialGradientLayer + +- (void)drawInContext:(CGContextRef)context { + size_t locationsCount = 2; + CGFloat locations[2] = {0.0f, 1.0f}; + CGFloat colors[8] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.75f}; + CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); + CGGradientRef gradient = CGGradientCreateWithColorComponents(colorSpace, colors, locations, locationsCount); + CGColorSpaceRelease(colorSpace); + + float radius = MIN(self.bounds.size.width , self.bounds.size.height); + CGContextDrawRadialGradient (context, gradient, self.gradientCenter, 0, self.gradientCenter, radius, kCGGradientDrawsAfterEndLocation); + CGGradientRelease(gradient); +} + +@end diff --git a/Pods/Target Support Files/ActionSheetPicker-3.0/ActionSheetPicker-3.0-dummy.m b/Pods/Target Support Files/ActionSheetPicker-3.0/ActionSheetPicker-3.0-dummy.m new file mode 100644 index 00000000..aa2e50d6 --- /dev/null +++ b/Pods/Target Support Files/ActionSheetPicker-3.0/ActionSheetPicker-3.0-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_ActionSheetPicker_3_0 : NSObject +@end +@implementation PodsDummy_ActionSheetPicker_3_0 +@end diff --git a/Pods/Target Support Files/ActionSheetPicker-3.0/ActionSheetPicker-3.0-prefix.pch b/Pods/Target Support Files/ActionSheetPicker-3.0/ActionSheetPicker-3.0-prefix.pch new file mode 100644 index 00000000..beb2a244 --- /dev/null +++ b/Pods/Target Support Files/ActionSheetPicker-3.0/ActionSheetPicker-3.0-prefix.pch @@ -0,0 +1,12 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + diff --git a/Pods/Target Support Files/ActionSheetPicker-3.0/ActionSheetPicker-3.0-umbrella.h b/Pods/Target Support Files/ActionSheetPicker-3.0/ActionSheetPicker-3.0-umbrella.h new file mode 100644 index 00000000..2f1af7c3 --- /dev/null +++ b/Pods/Target Support Files/ActionSheetPicker-3.0/ActionSheetPicker-3.0-umbrella.h @@ -0,0 +1,27 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "AbstractActionSheetPicker.h" +#import "ActionSheetCustomPicker.h" +#import "ActionSheetCustomPickerDelegate.h" +#import "ActionSheetDatePicker.h" +#import "ActionSheetDistancePicker.h" +#import "ActionSheetLocalePicker.h" +#import "ActionSheetMultipleStringPicker.h" +#import "ActionSheetPicker.h" +#import "ActionSheetStringPicker.h" +#import "DistancePickerView.h" +#import "SWActionSheet.h" + +FOUNDATION_EXPORT double ActionSheetPicker_3_0VersionNumber; +FOUNDATION_EXPORT const unsigned char ActionSheetPicker_3_0VersionString[]; + diff --git a/Pods/Target Support Files/ActionSheetPicker-3.0/ActionSheetPicker-3.0.modulemap b/Pods/Target Support Files/ActionSheetPicker-3.0/ActionSheetPicker-3.0.modulemap new file mode 100644 index 00000000..49be3be9 --- /dev/null +++ b/Pods/Target Support Files/ActionSheetPicker-3.0/ActionSheetPicker-3.0.modulemap @@ -0,0 +1,6 @@ +framework module ActionSheetPicker_3_0 { + umbrella header "ActionSheetPicker-3.0-umbrella.h" + + export * + module * { export * } +} diff --git a/Pods/Target Support Files/ActionSheetPicker-3.0/ActionSheetPicker-3.0.xcconfig b/Pods/Target Support Files/ActionSheetPicker-3.0/ActionSheetPicker-3.0.xcconfig new file mode 100644 index 00000000..7742fbec --- /dev/null +++ b/Pods/Target Support Files/ActionSheetPicker-3.0/ActionSheetPicker-3.0.xcconfig @@ -0,0 +1,9 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/ActionSheetPicker-3.0 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +OTHER_LDFLAGS = -framework "UIKit" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/ActionSheetPicker-3.0 +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES diff --git a/Pods/Target Support Files/ActionSheetPicker-3.0/Info.plist b/Pods/Target Support Files/ActionSheetPicker-3.0/Info.plist new file mode 100644 index 00000000..d135faf1 --- /dev/null +++ b/Pods/Target Support Files/ActionSheetPicker-3.0/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 2.3.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Pods/Target Support Files/ChameleonFramework/ChameleonFramework-dummy.m b/Pods/Target Support Files/ChameleonFramework/ChameleonFramework-dummy.m new file mode 100644 index 00000000..1fd1a46d --- /dev/null +++ b/Pods/Target Support Files/ChameleonFramework/ChameleonFramework-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_ChameleonFramework : NSObject +@end +@implementation PodsDummy_ChameleonFramework +@end diff --git a/Pods/Target Support Files/ChameleonFramework/ChameleonFramework-prefix.pch b/Pods/Target Support Files/ChameleonFramework/ChameleonFramework-prefix.pch new file mode 100644 index 00000000..beb2a244 --- /dev/null +++ b/Pods/Target Support Files/ChameleonFramework/ChameleonFramework-prefix.pch @@ -0,0 +1,12 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + diff --git a/Pods/Target Support Files/ChameleonFramework/ChameleonFramework-umbrella.h b/Pods/Target Support Files/ChameleonFramework/ChameleonFramework-umbrella.h new file mode 100644 index 00000000..a45ea6f1 --- /dev/null +++ b/Pods/Target Support Files/ChameleonFramework/ChameleonFramework-umbrella.h @@ -0,0 +1,46 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "Chameleon.h" +#import "ChameleonConstants.h" +#import "ChameleonEnums.h" +#import "ChameleonMacros.h" +#import "Chameleon_.h" +#import "NSArray+Chameleon.h" +#import "UIAppearance+Swift.h" +#import "UIButton+Chameleon.h" +#import "UIColor+Chameleon.h" +#import "UIColor+ChameleonPrivate.h" +#import "UIImage+ChameleonPrivate.h" +#import "UILabel+Chameleon.h" +#import "UINavigationController+Chameleon.h" +#import "UIView+ChameleonPrivate.h" +#import "UIViewController+Chameleon.h" +#import "Chameleon.h" +#import "ChameleonConstants.h" +#import "ChameleonEnums.h" +#import "ChameleonMacros.h" +#import "Chameleon_.h" +#import "NSArray+Chameleon.h" +#import "UIAppearance+Swift.h" +#import "UIButton+Chameleon.h" +#import "UIColor+Chameleon.h" +#import "UIColor+ChameleonPrivate.h" +#import "UIImage+ChameleonPrivate.h" +#import "UILabel+Chameleon.h" +#import "UINavigationController+Chameleon.h" +#import "UIView+ChameleonPrivate.h" +#import "UIViewController+Chameleon.h" + +FOUNDATION_EXPORT double ChameleonFrameworkVersionNumber; +FOUNDATION_EXPORT const unsigned char ChameleonFrameworkVersionString[]; + diff --git a/Pods/Target Support Files/ChameleonFramework/ChameleonFramework.modulemap b/Pods/Target Support Files/ChameleonFramework/ChameleonFramework.modulemap new file mode 100644 index 00000000..d60f497b --- /dev/null +++ b/Pods/Target Support Files/ChameleonFramework/ChameleonFramework.modulemap @@ -0,0 +1,6 @@ +framework module ChameleonFramework { + umbrella header "ChameleonFramework-umbrella.h" + + export * + module * { export * } +} diff --git a/Pods/Target Support Files/ChameleonFramework/ChameleonFramework.xcconfig b/Pods/Target Support Files/ChameleonFramework/ChameleonFramework.xcconfig new file mode 100644 index 00000000..0a4d6374 --- /dev/null +++ b/Pods/Target Support Files/ChameleonFramework/ChameleonFramework.xcconfig @@ -0,0 +1,9 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/ChameleonFramework +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +OTHER_LDFLAGS = -framework "CoreGraphics" -framework "QuartzCore" -framework "UIKit" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/ChameleonFramework +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES diff --git a/Pods/Target Support Files/ChameleonFramework/Info.plist b/Pods/Target Support Files/ChameleonFramework/Info.plist new file mode 100644 index 00000000..7f71fffc --- /dev/null +++ b/Pods/Target Support Files/ChameleonFramework/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 2.1.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Pods/Target Support Files/Charts/Charts-dummy.m b/Pods/Target Support Files/Charts/Charts-dummy.m new file mode 100644 index 00000000..0d0640ce --- /dev/null +++ b/Pods/Target Support Files/Charts/Charts-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_Charts : NSObject +@end +@implementation PodsDummy_Charts +@end diff --git a/Pods/Target Support Files/Charts/Charts-prefix.pch b/Pods/Target Support Files/Charts/Charts-prefix.pch new file mode 100644 index 00000000..beb2a244 --- /dev/null +++ b/Pods/Target Support Files/Charts/Charts-prefix.pch @@ -0,0 +1,12 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + diff --git a/Pods/Target Support Files/Charts/Charts-umbrella.h b/Pods/Target Support Files/Charts/Charts-umbrella.h new file mode 100644 index 00000000..006a8a22 --- /dev/null +++ b/Pods/Target Support Files/Charts/Charts-umbrella.h @@ -0,0 +1,16 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + + +FOUNDATION_EXPORT double ChartsVersionNumber; +FOUNDATION_EXPORT const unsigned char ChartsVersionString[]; + diff --git a/Pods/Target Support Files/Charts/Charts.modulemap b/Pods/Target Support Files/Charts/Charts.modulemap new file mode 100644 index 00000000..663dec7a --- /dev/null +++ b/Pods/Target Support Files/Charts/Charts.modulemap @@ -0,0 +1,6 @@ +framework module Charts { + umbrella header "Charts-umbrella.h" + + export * + module * { export * } +} diff --git a/Pods/Target Support Files/Charts/Charts.xcconfig b/Pods/Target Support Files/Charts/Charts.xcconfig new file mode 100644 index 00000000..14cebff7 --- /dev/null +++ b/Pods/Target Support Files/Charts/Charts.xcconfig @@ -0,0 +1,9 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Charts +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" "-suppress-warnings" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/Charts +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES diff --git a/Pods/Target Support Files/Charts/Info.plist b/Pods/Target Support Files/Charts/Info.plist new file mode 100644 index 00000000..3ac477e6 --- /dev/null +++ b/Pods/Target Support Files/Charts/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 3.3.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Pods/Target Support Files/Eddystone/Eddystone-dummy.m b/Pods/Target Support Files/Eddystone/Eddystone-dummy.m new file mode 100644 index 00000000..04d5e390 --- /dev/null +++ b/Pods/Target Support Files/Eddystone/Eddystone-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_Eddystone : NSObject +@end +@implementation PodsDummy_Eddystone +@end diff --git a/Pods/Target Support Files/Eddystone/Eddystone-prefix.pch b/Pods/Target Support Files/Eddystone/Eddystone-prefix.pch new file mode 100644 index 00000000..beb2a244 --- /dev/null +++ b/Pods/Target Support Files/Eddystone/Eddystone-prefix.pch @@ -0,0 +1,12 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + diff --git a/Pods/Target Support Files/Eddystone/Eddystone-umbrella.h b/Pods/Target Support Files/Eddystone/Eddystone-umbrella.h new file mode 100644 index 00000000..1980f086 --- /dev/null +++ b/Pods/Target Support Files/Eddystone/Eddystone-umbrella.h @@ -0,0 +1,16 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + + +FOUNDATION_EXPORT double EddystoneVersionNumber; +FOUNDATION_EXPORT const unsigned char EddystoneVersionString[]; + diff --git a/Pods/Target Support Files/Eddystone/Eddystone.modulemap b/Pods/Target Support Files/Eddystone/Eddystone.modulemap new file mode 100644 index 00000000..f7bfb1ef --- /dev/null +++ b/Pods/Target Support Files/Eddystone/Eddystone.modulemap @@ -0,0 +1,6 @@ +framework module Eddystone { + umbrella header "Eddystone-umbrella.h" + + export * + module * { export * } +} diff --git a/Pods/Target Support Files/Eddystone/Eddystone.xcconfig b/Pods/Target Support Files/Eddystone/Eddystone.xcconfig new file mode 100644 index 00000000..f315588c --- /dev/null +++ b/Pods/Target Support Files/Eddystone/Eddystone.xcconfig @@ -0,0 +1,10 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Eddystone +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +OTHER_LDFLAGS = -framework "CoreBluetooth" +OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" "-suppress-warnings" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/Eddystone +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES diff --git a/Pods/Target Support Files/Eddystone/Info.plist b/Pods/Target Support Files/Eddystone/Info.plist new file mode 100644 index 00000000..bfb89879 --- /dev/null +++ b/Pods/Target Support Files/Eddystone/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.1.3 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Pods/Target Support Files/Eddystone/ResourceBundle-Eddystone-Info.plist b/Pods/Target Support Files/Eddystone/ResourceBundle-Eddystone-Info.plist new file mode 100644 index 00000000..63d8a6c3 --- /dev/null +++ b/Pods/Target Support Files/Eddystone/ResourceBundle-Eddystone-Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.1.3 + CFBundleSignature + ???? + CFBundleVersion + 1 + NSPrincipalClass + + + diff --git a/Pods/Target Support Files/IP-UIKit-Wisdom/IP-UIKit-Wisdom-dummy.m b/Pods/Target Support Files/IP-UIKit-Wisdom/IP-UIKit-Wisdom-dummy.m new file mode 100644 index 00000000..8a51730d --- /dev/null +++ b/Pods/Target Support Files/IP-UIKit-Wisdom/IP-UIKit-Wisdom-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_IP_UIKit_Wisdom : NSObject +@end +@implementation PodsDummy_IP_UIKit_Wisdom +@end diff --git a/Pods/Target Support Files/IP-UIKit-Wisdom/IP-UIKit-Wisdom-prefix.pch b/Pods/Target Support Files/IP-UIKit-Wisdom/IP-UIKit-Wisdom-prefix.pch new file mode 100644 index 00000000..beb2a244 --- /dev/null +++ b/Pods/Target Support Files/IP-UIKit-Wisdom/IP-UIKit-Wisdom-prefix.pch @@ -0,0 +1,12 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + diff --git a/Pods/Target Support Files/IP-UIKit-Wisdom/IP-UIKit-Wisdom-umbrella.h b/Pods/Target Support Files/IP-UIKit-Wisdom/IP-UIKit-Wisdom-umbrella.h new file mode 100644 index 00000000..b1ada0c9 --- /dev/null +++ b/Pods/Target Support Files/IP-UIKit-Wisdom/IP-UIKit-Wisdom-umbrella.h @@ -0,0 +1,26 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "CAGradientLayer+IPGradients.h" +#import "UIButton+IPUtils.h" +#import "UIColor+IPRandomColor.h" +#import "UIImage+ColorMaskedImage.h" +#import "UITableView+Utils.h" +#import "UIView+Constraints.h" +#import "UIView+IPAncestry.h" +#import "UIView+IPFrameUtils.h" +#import "UIView+NibInitable.h" +#import "UIViewController+Containment.h" + +FOUNDATION_EXPORT double IP_UIKit_WisdomVersionNumber; +FOUNDATION_EXPORT const unsigned char IP_UIKit_WisdomVersionString[]; + diff --git a/Pods/Target Support Files/IP-UIKit-Wisdom/IP-UIKit-Wisdom.modulemap b/Pods/Target Support Files/IP-UIKit-Wisdom/IP-UIKit-Wisdom.modulemap new file mode 100644 index 00000000..157bf018 --- /dev/null +++ b/Pods/Target Support Files/IP-UIKit-Wisdom/IP-UIKit-Wisdom.modulemap @@ -0,0 +1,6 @@ +framework module IP_UIKit_Wisdom { + umbrella header "IP-UIKit-Wisdom-umbrella.h" + + export * + module * { export * } +} diff --git a/Pods/Target Support Files/IP-UIKit-Wisdom/IP-UIKit-Wisdom.xcconfig b/Pods/Target Support Files/IP-UIKit-Wisdom/IP-UIKit-Wisdom.xcconfig new file mode 100644 index 00000000..2bae54a3 --- /dev/null +++ b/Pods/Target Support Files/IP-UIKit-Wisdom/IP-UIKit-Wisdom.xcconfig @@ -0,0 +1,9 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/IP-UIKit-Wisdom +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +OTHER_LDFLAGS = -framework "UIKit" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/IP-UIKit-Wisdom +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES diff --git a/Pods/Target Support Files/IP-UIKit-Wisdom/Info.plist b/Pods/Target Support Files/IP-UIKit-Wisdom/Info.plist new file mode 100644 index 00000000..2fcc332e --- /dev/null +++ b/Pods/Target Support Files/IP-UIKit-Wisdom/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 0.0.10 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Pods/Target Support Files/KVOController/Info.plist b/Pods/Target Support Files/KVOController/Info.plist new file mode 100644 index 00000000..2a9158a0 --- /dev/null +++ b/Pods/Target Support Files/KVOController/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.2.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Pods/Target Support Files/KVOController/KVOController-dummy.m b/Pods/Target Support Files/KVOController/KVOController-dummy.m new file mode 100644 index 00000000..d97357f9 --- /dev/null +++ b/Pods/Target Support Files/KVOController/KVOController-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_KVOController : NSObject +@end +@implementation PodsDummy_KVOController +@end diff --git a/Pods/Target Support Files/KVOController/KVOController-prefix.pch b/Pods/Target Support Files/KVOController/KVOController-prefix.pch new file mode 100644 index 00000000..beb2a244 --- /dev/null +++ b/Pods/Target Support Files/KVOController/KVOController-prefix.pch @@ -0,0 +1,12 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + diff --git a/Pods/Target Support Files/KVOController/KVOController-umbrella.h b/Pods/Target Support Files/KVOController/KVOController-umbrella.h new file mode 100644 index 00000000..c445e6db --- /dev/null +++ b/Pods/Target Support Files/KVOController/KVOController-umbrella.h @@ -0,0 +1,19 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "FBKVOController.h" +#import "KVOController.h" +#import "NSObject+FBKVOController.h" + +FOUNDATION_EXPORT double KVOControllerVersionNumber; +FOUNDATION_EXPORT const unsigned char KVOControllerVersionString[]; + diff --git a/Pods/Target Support Files/KVOController/KVOController.modulemap b/Pods/Target Support Files/KVOController/KVOController.modulemap new file mode 100644 index 00000000..5c7486a7 --- /dev/null +++ b/Pods/Target Support Files/KVOController/KVOController.modulemap @@ -0,0 +1,6 @@ +framework module KVOController { + umbrella header "KVOController-umbrella.h" + + export * + module * { export * } +} diff --git a/Pods/Target Support Files/KVOController/KVOController.xcconfig b/Pods/Target Support Files/KVOController/KVOController.xcconfig new file mode 100644 index 00000000..0d67b358 --- /dev/null +++ b/Pods/Target Support Files/KVOController/KVOController.xcconfig @@ -0,0 +1,8 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/KVOController +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/KVOController +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES diff --git a/Pods/Target Support Files/MZTimerLabel/Info.plist b/Pods/Target Support Files/MZTimerLabel/Info.plist new file mode 100644 index 00000000..2f2e6f87 --- /dev/null +++ b/Pods/Target Support Files/MZTimerLabel/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 0.5.4 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Pods/Target Support Files/MZTimerLabel/MZTimerLabel-dummy.m b/Pods/Target Support Files/MZTimerLabel/MZTimerLabel-dummy.m new file mode 100644 index 00000000..1f18ea4f --- /dev/null +++ b/Pods/Target Support Files/MZTimerLabel/MZTimerLabel-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_MZTimerLabel : NSObject +@end +@implementation PodsDummy_MZTimerLabel +@end diff --git a/Pods/Target Support Files/MZTimerLabel/MZTimerLabel-prefix.pch b/Pods/Target Support Files/MZTimerLabel/MZTimerLabel-prefix.pch new file mode 100644 index 00000000..beb2a244 --- /dev/null +++ b/Pods/Target Support Files/MZTimerLabel/MZTimerLabel-prefix.pch @@ -0,0 +1,12 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + diff --git a/Pods/Target Support Files/MZTimerLabel/MZTimerLabel-umbrella.h b/Pods/Target Support Files/MZTimerLabel/MZTimerLabel-umbrella.h new file mode 100644 index 00000000..96c34a13 --- /dev/null +++ b/Pods/Target Support Files/MZTimerLabel/MZTimerLabel-umbrella.h @@ -0,0 +1,17 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "MZTimerLabel.h" + +FOUNDATION_EXPORT double MZTimerLabelVersionNumber; +FOUNDATION_EXPORT const unsigned char MZTimerLabelVersionString[]; + diff --git a/Pods/Target Support Files/MZTimerLabel/MZTimerLabel.modulemap b/Pods/Target Support Files/MZTimerLabel/MZTimerLabel.modulemap new file mode 100644 index 00000000..c6b8dd0f --- /dev/null +++ b/Pods/Target Support Files/MZTimerLabel/MZTimerLabel.modulemap @@ -0,0 +1,6 @@ +framework module MZTimerLabel { + umbrella header "MZTimerLabel-umbrella.h" + + export * + module * { export * } +} diff --git a/Pods/Target Support Files/MZTimerLabel/MZTimerLabel.xcconfig b/Pods/Target Support Files/MZTimerLabel/MZTimerLabel.xcconfig new file mode 100644 index 00000000..1be279f8 --- /dev/null +++ b/Pods/Target Support Files/MZTimerLabel/MZTimerLabel.xcconfig @@ -0,0 +1,8 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/MZTimerLabel +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/MZTimerLabel +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES diff --git a/Pods/Target Support Files/Pods-BlueGecko/Info.plist b/Pods/Target Support Files/Pods-BlueGecko/Info.plist new file mode 100644 index 00000000..2243fe6e --- /dev/null +++ b/Pods/Target Support Files/Pods-BlueGecko/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Pods/Target Support Files/Pods-BlueGecko/Pods-BlueGecko-acknowledgements.markdown b/Pods/Target Support Files/Pods-BlueGecko/Pods-BlueGecko-acknowledgements.markdown new file mode 100644 index 00000000..bd0c55b0 --- /dev/null +++ b/Pods/Target Support Files/Pods-BlueGecko/Pods-BlueGecko-acknowledgements.markdown @@ -0,0 +1,440 @@ +# Acknowledgements +This application makes use of the following third party libraries: + +## ActionSheetPicker-3.0 + +Copyright (c) 2011, Tim Cinel (see AUTHORS) +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +## ChameleonFramework + +##The MIT License (MIT) + +> Copyright (c) 2014-2015 Vicc Alexander + +> Permission is hereby granted, free of charge, to any person obtaining a copy +> of this software and associated documentation files (the "Software"), to deal +> in the Software without restriction, including without limitation the rights +> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +> copies of the Software, and to permit persons to whom the Software is +> furnished to do so, subject to the following conditions: + +> The above copyright notice and this permission notice shall be included in all +> copies or substantial portions of the Software. + +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +> SOFTWARE. + + +## Charts + +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2016 Daniel Cohen Gindi & Philipp Jahoda + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + +## Eddystone + +Copyright (c) 2015 Tanner Nelson + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +## IP-UIKit-Wisdom + +The MIT License (MIT) + +Copyright (c) 2015 Intrepid Pursuits LLC + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +## KVOController + +BSD License + +For KVOController software + +Copyright (c) 2014, Facebook, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name Facebook nor the names of its contributors may be used to + endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +## MZTimerLabel + +The MIT License (MIT) + +Copyright (c) 2013 mineschan + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +## PureLayout + +This code is distributed under the terms and conditions of the MIT license. + +Copyright (c) 2014-2015 Tyler Fox + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +## SVProgressHUD + +MIT License + +Copyright (c) 2011-2018 Sam Vermette, Tobias Tiemerding and contributors. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +## UICircularProgressRing + +Copyright (c) 2017 Luis Padron + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +## WYPopoverController + +WYPopoverController is available under the MIT license. + +Copyright © 2013 Nicolas CHENG + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +## XMLDictionary + +XMLDictionary + +Copyright (C) 2011 Charcoal Design + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +Generated by CocoaPods - https://cocoapods.org diff --git a/Pods/Target Support Files/Pods-BlueGecko/Pods-BlueGecko-acknowledgements.plist b/Pods/Target Support Files/Pods-BlueGecko/Pods-BlueGecko-acknowledgements.plist new file mode 100644 index 00000000..ff03efd0 --- /dev/null +++ b/Pods/Target Support Files/Pods-BlueGecko/Pods-BlueGecko-acknowledgements.plist @@ -0,0 +1,538 @@ + + + + + PreferenceSpecifiers + + + FooterText + This application makes use of the following third party libraries: + Title + Acknowledgements + Type + PSGroupSpecifier + + + FooterText + Copyright (c) 2011, Tim Cinel (see AUTHORS) +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the <organization> nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + License + BSD + Title + ActionSheetPicker-3.0 + Type + PSGroupSpecifier + + + FooterText + ##The MIT License (MIT) + +> Copyright (c) 2014-2015 Vicc Alexander + +> Permission is hereby granted, free of charge, to any person obtaining a copy +> of this software and associated documentation files (the "Software"), to deal +> in the Software without restriction, including without limitation the rights +> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +> copies of the Software, and to permit persons to whom the Software is +> furnished to do so, subject to the following conditions: + +> The above copyright notice and this permission notice shall be included in all +> copies or substantial portions of the Software. + +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +> SOFTWARE. + + License + MIT + Title + ChameleonFramework + Type + PSGroupSpecifier + + + FooterText + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2016 Daniel Cohen Gindi & Philipp Jahoda + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + License + Apache License, Version 2.0 + Title + Charts + Type + PSGroupSpecifier + + + FooterText + Copyright (c) 2015 Tanner Nelson <tanner@bluebite.com> + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + License + MIT + Title + Eddystone + Type + PSGroupSpecifier + + + FooterText + The MIT License (MIT) + +Copyright (c) 2015 Intrepid Pursuits LLC + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + License + MIT + Title + IP-UIKit-Wisdom + Type + PSGroupSpecifier + + + FooterText + BSD License + +For KVOController software + +Copyright (c) 2014, Facebook, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name Facebook nor the names of its contributors may be used to + endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + License + BSD + Title + KVOController + Type + PSGroupSpecifier + + + FooterText + The MIT License (MIT) + +Copyright (c) 2013 mineschan + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + License + MIT + Title + MZTimerLabel + Type + PSGroupSpecifier + + + FooterText + This code is distributed under the terms and conditions of the MIT license. + +Copyright (c) 2014-2015 Tyler Fox + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + License + MIT + Title + PureLayout + Type + PSGroupSpecifier + + + FooterText + MIT License + +Copyright (c) 2011-2018 Sam Vermette, Tobias Tiemerding and contributors. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + License + MIT + Title + SVProgressHUD + Type + PSGroupSpecifier + + + FooterText + Copyright (c) 2017 Luis Padron + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + License + MIT + Title + UICircularProgressRing + Type + PSGroupSpecifier + + + FooterText + WYPopoverController is available under the MIT license. + +Copyright © 2013 Nicolas CHENG + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + License + MIT + Title + WYPopoverController + Type + PSGroupSpecifier + + + FooterText + XMLDictionary + +Copyright (C) 2011 Charcoal Design + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. + License + zlib + Title + XMLDictionary + Type + PSGroupSpecifier + + + FooterText + Generated by CocoaPods - https://cocoapods.org + Title + + Type + PSGroupSpecifier + + + StringsTable + Acknowledgements + Title + Acknowledgements + + diff --git a/Pods/Target Support Files/Pods-BlueGecko/Pods-BlueGecko-dummy.m b/Pods/Target Support Files/Pods-BlueGecko/Pods-BlueGecko-dummy.m new file mode 100644 index 00000000..0b33cf9f --- /dev/null +++ b/Pods/Target Support Files/Pods-BlueGecko/Pods-BlueGecko-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_Pods_BlueGecko : NSObject +@end +@implementation PodsDummy_Pods_BlueGecko +@end diff --git a/Pods/Target Support Files/Pods-BlueGecko/Pods-BlueGecko-frameworks.sh b/Pods/Target Support Files/Pods-BlueGecko/Pods-BlueGecko-frameworks.sh new file mode 100755 index 00000000..47998d17 --- /dev/null +++ b/Pods/Target Support Files/Pods-BlueGecko/Pods-BlueGecko-frameworks.sh @@ -0,0 +1,175 @@ +#!/bin/sh +set -e +set -u +set -o pipefail + +if [ -z ${FRAMEWORKS_FOLDER_PATH+x} ]; then + # If FRAMEWORKS_FOLDER_PATH is not set, then there's nowhere for us to copy + # frameworks to, so exit 0 (signalling the script phase was successful). + exit 0 +fi + +echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" +mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + +COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}" +SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" + +# Used as a return value for each invocation of `strip_invalid_archs` function. +STRIP_BINARY_RETVAL=0 + +# This protects against multiple targets copying the same framework dependency at the same time. The solution +# was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html +RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") + +# Copies and strips a vendored framework +install_framework() +{ + if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then + local source="${BUILT_PRODUCTS_DIR}/$1" + elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then + local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" + elif [ -r "$1" ]; then + local source="$1" + fi + + local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + + if [ -L "${source}" ]; then + echo "Symlinked..." + source="$(readlink "${source}")" + fi + + # Use filter instead of exclude so missing patterns don't throw errors. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" + + local basename + basename="$(basename -s .framework "$1")" + binary="${destination}/${basename}.framework/${basename}" + if ! [ -r "$binary" ]; then + binary="${destination}/${basename}" + fi + + # Strip invalid architectures so "fat" simulator / device frameworks work on device + if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then + strip_invalid_archs "$binary" + fi + + # Resign the code if required by the build settings to avoid unstable apps + code_sign_if_enabled "${destination}/$(basename "$1")" + + # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. + if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then + local swift_runtime_libs + swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) + for lib in $swift_runtime_libs; do + echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" + rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" + code_sign_if_enabled "${destination}/${lib}" + done + fi +} + +# Copies and strips a vendored dSYM +install_dsym() { + local source="$1" + if [ -r "$source" ]; then + # Copy the dSYM into a the targets temp dir. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}" + + local basename + basename="$(basename -s .framework.dSYM "$source")" + binary="${DERIVED_FILES_DIR}/${basename}.framework.dSYM/Contents/Resources/DWARF/${basename}" + + # Strip invalid architectures so "fat" simulator / device frameworks work on device + if [[ "$(file "$binary")" == *"Mach-O dSYM companion"* ]]; then + strip_invalid_archs "$binary" + fi + + if [[ $STRIP_BINARY_RETVAL == 1 ]]; then + # Move the stripped file into its final destination. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.framework.dSYM" "${DWARF_DSYM_FOLDER_PATH}" + else + # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing. + touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.framework.dSYM" + fi + fi +} + +# Signs a framework with the provided identity +code_sign_if_enabled() { + if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then + # Use the current code_sign_identitiy + echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" + local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements '$1'" + + if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then + code_sign_cmd="$code_sign_cmd &" + fi + echo "$code_sign_cmd" + eval "$code_sign_cmd" + fi +} + +# Strip invalid architectures +strip_invalid_archs() { + binary="$1" + # Get architectures for current target binary + binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)" + # Intersect them with the architectures we are building for + intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)" + # If there are no archs supported by this binary then warn the user + if [[ -z "$intersected_archs" ]]; then + echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)." + STRIP_BINARY_RETVAL=0 + return + fi + stripped="" + for arch in $binary_archs; do + if ! [[ "${ARCHS}" == *"$arch"* ]]; then + # Strip non-valid architectures in-place + lipo -remove "$arch" -output "$binary" "$binary" || exit 1 + stripped="$stripped $arch" + fi + done + if [[ "$stripped" ]]; then + echo "Stripped $binary of architectures:$stripped" + fi + STRIP_BINARY_RETVAL=1 +} + + +if [[ "$CONFIGURATION" == "Debug" ]]; then + install_framework "${BUILT_PRODUCTS_DIR}/ActionSheetPicker-3.0/ActionSheetPicker_3_0.framework" + install_framework "${BUILT_PRODUCTS_DIR}/ChameleonFramework/ChameleonFramework.framework" + install_framework "${BUILT_PRODUCTS_DIR}/Charts/Charts.framework" + install_framework "${BUILT_PRODUCTS_DIR}/Eddystone/Eddystone.framework" + install_framework "${BUILT_PRODUCTS_DIR}/IP-UIKit-Wisdom/IP_UIKit_Wisdom.framework" + install_framework "${BUILT_PRODUCTS_DIR}/KVOController/KVOController.framework" + install_framework "${BUILT_PRODUCTS_DIR}/MZTimerLabel/MZTimerLabel.framework" + install_framework "${BUILT_PRODUCTS_DIR}/PureLayout/PureLayout.framework" + install_framework "${BUILT_PRODUCTS_DIR}/SVProgressHUD/SVProgressHUD.framework" + install_framework "${BUILT_PRODUCTS_DIR}/UICircularProgressRing/UICircularProgressRing.framework" + install_framework "${BUILT_PRODUCTS_DIR}/WYPopoverController/WYPopoverController.framework" + install_framework "${BUILT_PRODUCTS_DIR}/XMLDictionary/XMLDictionary.framework" +fi +if [[ "$CONFIGURATION" == "Release" ]]; then + install_framework "${BUILT_PRODUCTS_DIR}/ActionSheetPicker-3.0/ActionSheetPicker_3_0.framework" + install_framework "${BUILT_PRODUCTS_DIR}/ChameleonFramework/ChameleonFramework.framework" + install_framework "${BUILT_PRODUCTS_DIR}/Charts/Charts.framework" + install_framework "${BUILT_PRODUCTS_DIR}/Eddystone/Eddystone.framework" + install_framework "${BUILT_PRODUCTS_DIR}/IP-UIKit-Wisdom/IP_UIKit_Wisdom.framework" + install_framework "${BUILT_PRODUCTS_DIR}/KVOController/KVOController.framework" + install_framework "${BUILT_PRODUCTS_DIR}/MZTimerLabel/MZTimerLabel.framework" + install_framework "${BUILT_PRODUCTS_DIR}/PureLayout/PureLayout.framework" + install_framework "${BUILT_PRODUCTS_DIR}/SVProgressHUD/SVProgressHUD.framework" + install_framework "${BUILT_PRODUCTS_DIR}/UICircularProgressRing/UICircularProgressRing.framework" + install_framework "${BUILT_PRODUCTS_DIR}/WYPopoverController/WYPopoverController.framework" + install_framework "${BUILT_PRODUCTS_DIR}/XMLDictionary/XMLDictionary.framework" +fi +if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then + wait +fi diff --git a/Pods/Target Support Files/Pods-BlueGecko/Pods-BlueGecko-resources.sh b/Pods/Target Support Files/Pods-BlueGecko/Pods-BlueGecko-resources.sh new file mode 100755 index 00000000..345301f2 --- /dev/null +++ b/Pods/Target Support Files/Pods-BlueGecko/Pods-BlueGecko-resources.sh @@ -0,0 +1,118 @@ +#!/bin/sh +set -e +set -u +set -o pipefail + +if [ -z ${UNLOCALIZED_RESOURCES_FOLDER_PATH+x} ]; then + # If UNLOCALIZED_RESOURCES_FOLDER_PATH is not set, then there's nowhere for us to copy + # resources to, so exit 0 (signalling the script phase was successful). + exit 0 +fi + +mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" + +RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt +> "$RESOURCES_TO_COPY" + +XCASSET_FILES=() + +# This protects against multiple targets copying the same framework dependency at the same time. The solution +# was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html +RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") + +case "${TARGETED_DEVICE_FAMILY:-}" in + 1,2) + TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" + ;; + 1) + TARGET_DEVICE_ARGS="--target-device iphone" + ;; + 2) + TARGET_DEVICE_ARGS="--target-device ipad" + ;; + 3) + TARGET_DEVICE_ARGS="--target-device tv" + ;; + 4) + TARGET_DEVICE_ARGS="--target-device watch" + ;; + *) + TARGET_DEVICE_ARGS="--target-device mac" + ;; +esac + +install_resource() +{ + if [[ "$1" = /* ]] ; then + RESOURCE_PATH="$1" + else + RESOURCE_PATH="${PODS_ROOT}/$1" + fi + if [[ ! -e "$RESOURCE_PATH" ]] ; then + cat << EOM +error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. +EOM + exit 1 + fi + case $RESOURCE_PATH in + *.storyboard) + echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true + ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} + ;; + *.xib) + echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true + ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} + ;; + *.framework) + echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true + mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + ;; + *.xcdatamodel) + echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" || true + xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" + ;; + *.xcdatamodeld) + echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" || true + xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" + ;; + *.xcmappingmodel) + echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" || true + xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" + ;; + *.xcassets) + ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH" + XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") + ;; + *) + echo "$RESOURCE_PATH" || true + echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" + ;; + esac +} + +mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" +rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" +if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then + mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" + rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" +fi +rm -f "$RESOURCES_TO_COPY" + +if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "${XCASSET_FILES:-}" ] +then + # Find all other xcassets (this unfortunately includes those of path pods and other targets). + OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) + while read line; do + if [[ $line != "${PODS_ROOT}*" ]]; then + XCASSET_FILES+=("$line") + fi + done <<<"$OTHER_XCASSETS" + + if [ -z ${ASSETCATALOG_COMPILER_APPICON_NAME+x} ]; then + printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" + else + printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" --app-icon "${ASSETCATALOG_COMPILER_APPICON_NAME}" --output-partial-info-plist "${TARGET_TEMP_DIR}/assetcatalog_generated_info_cocoapods.plist" + fi +fi diff --git a/Pods/Target Support Files/Pods-BlueGecko/Pods-BlueGecko-umbrella.h b/Pods/Target Support Files/Pods-BlueGecko/Pods-BlueGecko-umbrella.h new file mode 100644 index 00000000..9e0e0941 --- /dev/null +++ b/Pods/Target Support Files/Pods-BlueGecko/Pods-BlueGecko-umbrella.h @@ -0,0 +1,16 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + + +FOUNDATION_EXPORT double Pods_BlueGeckoVersionNumber; +FOUNDATION_EXPORT const unsigned char Pods_BlueGeckoVersionString[]; + diff --git a/Pods/Target Support Files/Pods-BlueGecko/Pods-BlueGecko.debug.xcconfig b/Pods/Target Support Files/Pods-BlueGecko/Pods-BlueGecko.debug.xcconfig new file mode 100644 index 00000000..dbab75d5 --- /dev/null +++ b/Pods/Target Support Files/Pods-BlueGecko/Pods-BlueGecko.debug.xcconfig @@ -0,0 +1,11 @@ +ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/ActionSheetPicker-3.0" "${PODS_CONFIGURATION_BUILD_DIR}/ChameleonFramework" "${PODS_CONFIGURATION_BUILD_DIR}/Charts" "${PODS_CONFIGURATION_BUILD_DIR}/Eddystone" "${PODS_CONFIGURATION_BUILD_DIR}/IP-UIKit-Wisdom" "${PODS_CONFIGURATION_BUILD_DIR}/KVOController" "${PODS_CONFIGURATION_BUILD_DIR}/MZTimerLabel" "${PODS_CONFIGURATION_BUILD_DIR}/PureLayout" "${PODS_CONFIGURATION_BUILD_DIR}/SVProgressHUD" "${PODS_CONFIGURATION_BUILD_DIR}/UICircularProgressRing" "${PODS_CONFIGURATION_BUILD_DIR}/WYPopoverController" "${PODS_CONFIGURATION_BUILD_DIR}/XMLDictionary" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/ActionSheetPicker-3.0/ActionSheetPicker_3_0.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/ChameleonFramework/ChameleonFramework.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/Charts/Charts.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/Eddystone/Eddystone.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/IP-UIKit-Wisdom/IP_UIKit_Wisdom.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/KVOController/KVOController.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/MZTimerLabel/MZTimerLabel.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/PureLayout/PureLayout.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/SVProgressHUD/SVProgressHUD.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/UICircularProgressRing/UICircularProgressRing.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/WYPopoverController/WYPopoverController.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/XMLDictionary/XMLDictionary.framework/Headers" +OTHER_LDFLAGS = $(inherited) -framework "ActionSheetPicker_3_0" -framework "ChameleonFramework" -framework "Charts" -framework "Eddystone" -framework "IP_UIKit_Wisdom" -framework "KVOController" -framework "MZTimerLabel" -framework "PureLayout" -framework "SVProgressHUD" -framework "UICircularProgressRing" -framework "WYPopoverController" -framework "XMLDictionary" +OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_PODFILE_DIR_PATH = ${SRCROOT}/. +PODS_ROOT = ${SRCROOT}/Pods diff --git a/Pods/Target Support Files/Pods-BlueGecko/Pods-BlueGecko.modulemap b/Pods/Target Support Files/Pods-BlueGecko/Pods-BlueGecko.modulemap new file mode 100644 index 00000000..e0a00f8f --- /dev/null +++ b/Pods/Target Support Files/Pods-BlueGecko/Pods-BlueGecko.modulemap @@ -0,0 +1,6 @@ +framework module Pods_BlueGecko { + umbrella header "Pods-BlueGecko-umbrella.h" + + export * + module * { export * } +} diff --git a/Pods/Target Support Files/Pods-BlueGecko/Pods-BlueGecko.release.xcconfig b/Pods/Target Support Files/Pods-BlueGecko/Pods-BlueGecko.release.xcconfig new file mode 100644 index 00000000..dbab75d5 --- /dev/null +++ b/Pods/Target Support Files/Pods-BlueGecko/Pods-BlueGecko.release.xcconfig @@ -0,0 +1,11 @@ +ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/ActionSheetPicker-3.0" "${PODS_CONFIGURATION_BUILD_DIR}/ChameleonFramework" "${PODS_CONFIGURATION_BUILD_DIR}/Charts" "${PODS_CONFIGURATION_BUILD_DIR}/Eddystone" "${PODS_CONFIGURATION_BUILD_DIR}/IP-UIKit-Wisdom" "${PODS_CONFIGURATION_BUILD_DIR}/KVOController" "${PODS_CONFIGURATION_BUILD_DIR}/MZTimerLabel" "${PODS_CONFIGURATION_BUILD_DIR}/PureLayout" "${PODS_CONFIGURATION_BUILD_DIR}/SVProgressHUD" "${PODS_CONFIGURATION_BUILD_DIR}/UICircularProgressRing" "${PODS_CONFIGURATION_BUILD_DIR}/WYPopoverController" "${PODS_CONFIGURATION_BUILD_DIR}/XMLDictionary" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/ActionSheetPicker-3.0/ActionSheetPicker_3_0.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/ChameleonFramework/ChameleonFramework.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/Charts/Charts.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/Eddystone/Eddystone.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/IP-UIKit-Wisdom/IP_UIKit_Wisdom.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/KVOController/KVOController.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/MZTimerLabel/MZTimerLabel.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/PureLayout/PureLayout.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/SVProgressHUD/SVProgressHUD.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/UICircularProgressRing/UICircularProgressRing.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/WYPopoverController/WYPopoverController.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/XMLDictionary/XMLDictionary.framework/Headers" +OTHER_LDFLAGS = $(inherited) -framework "ActionSheetPicker_3_0" -framework "ChameleonFramework" -framework "Charts" -framework "Eddystone" -framework "IP_UIKit_Wisdom" -framework "KVOController" -framework "MZTimerLabel" -framework "PureLayout" -framework "SVProgressHUD" -framework "UICircularProgressRing" -framework "WYPopoverController" -framework "XMLDictionary" +OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_PODFILE_DIR_PATH = ${SRCROOT}/. +PODS_ROOT = ${SRCROOT}/Pods diff --git a/Pods/Target Support Files/Pods-BlueGeckoWithHomeKit/Info.plist b/Pods/Target Support Files/Pods-BlueGeckoWithHomeKit/Info.plist new file mode 100644 index 00000000..2243fe6e --- /dev/null +++ b/Pods/Target Support Files/Pods-BlueGeckoWithHomeKit/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Pods/Target Support Files/Pods-BlueGeckoWithHomeKit/Pods-BlueGeckoWithHomeKit-acknowledgements.markdown b/Pods/Target Support Files/Pods-BlueGeckoWithHomeKit/Pods-BlueGeckoWithHomeKit-acknowledgements.markdown new file mode 100644 index 00000000..bd0c55b0 --- /dev/null +++ b/Pods/Target Support Files/Pods-BlueGeckoWithHomeKit/Pods-BlueGeckoWithHomeKit-acknowledgements.markdown @@ -0,0 +1,440 @@ +# Acknowledgements +This application makes use of the following third party libraries: + +## ActionSheetPicker-3.0 + +Copyright (c) 2011, Tim Cinel (see AUTHORS) +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +## ChameleonFramework + +##The MIT License (MIT) + +> Copyright (c) 2014-2015 Vicc Alexander + +> Permission is hereby granted, free of charge, to any person obtaining a copy +> of this software and associated documentation files (the "Software"), to deal +> in the Software without restriction, including without limitation the rights +> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +> copies of the Software, and to permit persons to whom the Software is +> furnished to do so, subject to the following conditions: + +> The above copyright notice and this permission notice shall be included in all +> copies or substantial portions of the Software. + +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +> SOFTWARE. + + +## Charts + +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2016 Daniel Cohen Gindi & Philipp Jahoda + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + +## Eddystone + +Copyright (c) 2015 Tanner Nelson + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +## IP-UIKit-Wisdom + +The MIT License (MIT) + +Copyright (c) 2015 Intrepid Pursuits LLC + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +## KVOController + +BSD License + +For KVOController software + +Copyright (c) 2014, Facebook, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name Facebook nor the names of its contributors may be used to + endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +## MZTimerLabel + +The MIT License (MIT) + +Copyright (c) 2013 mineschan + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +## PureLayout + +This code is distributed under the terms and conditions of the MIT license. + +Copyright (c) 2014-2015 Tyler Fox + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +## SVProgressHUD + +MIT License + +Copyright (c) 2011-2018 Sam Vermette, Tobias Tiemerding and contributors. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +## UICircularProgressRing + +Copyright (c) 2017 Luis Padron + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +## WYPopoverController + +WYPopoverController is available under the MIT license. + +Copyright © 2013 Nicolas CHENG + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +## XMLDictionary + +XMLDictionary + +Copyright (C) 2011 Charcoal Design + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +Generated by CocoaPods - https://cocoapods.org diff --git a/Pods/Target Support Files/Pods-BlueGeckoWithHomeKit/Pods-BlueGeckoWithHomeKit-acknowledgements.plist b/Pods/Target Support Files/Pods-BlueGeckoWithHomeKit/Pods-BlueGeckoWithHomeKit-acknowledgements.plist new file mode 100644 index 00000000..ff03efd0 --- /dev/null +++ b/Pods/Target Support Files/Pods-BlueGeckoWithHomeKit/Pods-BlueGeckoWithHomeKit-acknowledgements.plist @@ -0,0 +1,538 @@ + + + + + PreferenceSpecifiers + + + FooterText + This application makes use of the following third party libraries: + Title + Acknowledgements + Type + PSGroupSpecifier + + + FooterText + Copyright (c) 2011, Tim Cinel (see AUTHORS) +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the <organization> nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + License + BSD + Title + ActionSheetPicker-3.0 + Type + PSGroupSpecifier + + + FooterText + ##The MIT License (MIT) + +> Copyright (c) 2014-2015 Vicc Alexander + +> Permission is hereby granted, free of charge, to any person obtaining a copy +> of this software and associated documentation files (the "Software"), to deal +> in the Software without restriction, including without limitation the rights +> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +> copies of the Software, and to permit persons to whom the Software is +> furnished to do so, subject to the following conditions: + +> The above copyright notice and this permission notice shall be included in all +> copies or substantial portions of the Software. + +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +> SOFTWARE. + + License + MIT + Title + ChameleonFramework + Type + PSGroupSpecifier + + + FooterText + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2016 Daniel Cohen Gindi & Philipp Jahoda + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + License + Apache License, Version 2.0 + Title + Charts + Type + PSGroupSpecifier + + + FooterText + Copyright (c) 2015 Tanner Nelson <tanner@bluebite.com> + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + License + MIT + Title + Eddystone + Type + PSGroupSpecifier + + + FooterText + The MIT License (MIT) + +Copyright (c) 2015 Intrepid Pursuits LLC + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + License + MIT + Title + IP-UIKit-Wisdom + Type + PSGroupSpecifier + + + FooterText + BSD License + +For KVOController software + +Copyright (c) 2014, Facebook, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name Facebook nor the names of its contributors may be used to + endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + License + BSD + Title + KVOController + Type + PSGroupSpecifier + + + FooterText + The MIT License (MIT) + +Copyright (c) 2013 mineschan + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + License + MIT + Title + MZTimerLabel + Type + PSGroupSpecifier + + + FooterText + This code is distributed under the terms and conditions of the MIT license. + +Copyright (c) 2014-2015 Tyler Fox + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + License + MIT + Title + PureLayout + Type + PSGroupSpecifier + + + FooterText + MIT License + +Copyright (c) 2011-2018 Sam Vermette, Tobias Tiemerding and contributors. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + License + MIT + Title + SVProgressHUD + Type + PSGroupSpecifier + + + FooterText + Copyright (c) 2017 Luis Padron + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + License + MIT + Title + UICircularProgressRing + Type + PSGroupSpecifier + + + FooterText + WYPopoverController is available under the MIT license. + +Copyright © 2013 Nicolas CHENG + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + License + MIT + Title + WYPopoverController + Type + PSGroupSpecifier + + + FooterText + XMLDictionary + +Copyright (C) 2011 Charcoal Design + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. + License + zlib + Title + XMLDictionary + Type + PSGroupSpecifier + + + FooterText + Generated by CocoaPods - https://cocoapods.org + Title + + Type + PSGroupSpecifier + + + StringsTable + Acknowledgements + Title + Acknowledgements + + diff --git a/Pods/Target Support Files/Pods-BlueGeckoWithHomeKit/Pods-BlueGeckoWithHomeKit-dummy.m b/Pods/Target Support Files/Pods-BlueGeckoWithHomeKit/Pods-BlueGeckoWithHomeKit-dummy.m new file mode 100644 index 00000000..3ea05e23 --- /dev/null +++ b/Pods/Target Support Files/Pods-BlueGeckoWithHomeKit/Pods-BlueGeckoWithHomeKit-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_Pods_BlueGeckoWithHomeKit : NSObject +@end +@implementation PodsDummy_Pods_BlueGeckoWithHomeKit +@end diff --git a/Pods/Target Support Files/Pods-BlueGeckoWithHomeKit/Pods-BlueGeckoWithHomeKit-frameworks.sh b/Pods/Target Support Files/Pods-BlueGeckoWithHomeKit/Pods-BlueGeckoWithHomeKit-frameworks.sh new file mode 100755 index 00000000..47998d17 --- /dev/null +++ b/Pods/Target Support Files/Pods-BlueGeckoWithHomeKit/Pods-BlueGeckoWithHomeKit-frameworks.sh @@ -0,0 +1,175 @@ +#!/bin/sh +set -e +set -u +set -o pipefail + +if [ -z ${FRAMEWORKS_FOLDER_PATH+x} ]; then + # If FRAMEWORKS_FOLDER_PATH is not set, then there's nowhere for us to copy + # frameworks to, so exit 0 (signalling the script phase was successful). + exit 0 +fi + +echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" +mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + +COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}" +SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" + +# Used as a return value for each invocation of `strip_invalid_archs` function. +STRIP_BINARY_RETVAL=0 + +# This protects against multiple targets copying the same framework dependency at the same time. The solution +# was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html +RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") + +# Copies and strips a vendored framework +install_framework() +{ + if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then + local source="${BUILT_PRODUCTS_DIR}/$1" + elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then + local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" + elif [ -r "$1" ]; then + local source="$1" + fi + + local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + + if [ -L "${source}" ]; then + echo "Symlinked..." + source="$(readlink "${source}")" + fi + + # Use filter instead of exclude so missing patterns don't throw errors. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" + + local basename + basename="$(basename -s .framework "$1")" + binary="${destination}/${basename}.framework/${basename}" + if ! [ -r "$binary" ]; then + binary="${destination}/${basename}" + fi + + # Strip invalid architectures so "fat" simulator / device frameworks work on device + if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then + strip_invalid_archs "$binary" + fi + + # Resign the code if required by the build settings to avoid unstable apps + code_sign_if_enabled "${destination}/$(basename "$1")" + + # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. + if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then + local swift_runtime_libs + swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) + for lib in $swift_runtime_libs; do + echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" + rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" + code_sign_if_enabled "${destination}/${lib}" + done + fi +} + +# Copies and strips a vendored dSYM +install_dsym() { + local source="$1" + if [ -r "$source" ]; then + # Copy the dSYM into a the targets temp dir. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}" + + local basename + basename="$(basename -s .framework.dSYM "$source")" + binary="${DERIVED_FILES_DIR}/${basename}.framework.dSYM/Contents/Resources/DWARF/${basename}" + + # Strip invalid architectures so "fat" simulator / device frameworks work on device + if [[ "$(file "$binary")" == *"Mach-O dSYM companion"* ]]; then + strip_invalid_archs "$binary" + fi + + if [[ $STRIP_BINARY_RETVAL == 1 ]]; then + # Move the stripped file into its final destination. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.framework.dSYM" "${DWARF_DSYM_FOLDER_PATH}" + else + # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing. + touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.framework.dSYM" + fi + fi +} + +# Signs a framework with the provided identity +code_sign_if_enabled() { + if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then + # Use the current code_sign_identitiy + echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" + local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements '$1'" + + if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then + code_sign_cmd="$code_sign_cmd &" + fi + echo "$code_sign_cmd" + eval "$code_sign_cmd" + fi +} + +# Strip invalid architectures +strip_invalid_archs() { + binary="$1" + # Get architectures for current target binary + binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)" + # Intersect them with the architectures we are building for + intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)" + # If there are no archs supported by this binary then warn the user + if [[ -z "$intersected_archs" ]]; then + echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)." + STRIP_BINARY_RETVAL=0 + return + fi + stripped="" + for arch in $binary_archs; do + if ! [[ "${ARCHS}" == *"$arch"* ]]; then + # Strip non-valid architectures in-place + lipo -remove "$arch" -output "$binary" "$binary" || exit 1 + stripped="$stripped $arch" + fi + done + if [[ "$stripped" ]]; then + echo "Stripped $binary of architectures:$stripped" + fi + STRIP_BINARY_RETVAL=1 +} + + +if [[ "$CONFIGURATION" == "Debug" ]]; then + install_framework "${BUILT_PRODUCTS_DIR}/ActionSheetPicker-3.0/ActionSheetPicker_3_0.framework" + install_framework "${BUILT_PRODUCTS_DIR}/ChameleonFramework/ChameleonFramework.framework" + install_framework "${BUILT_PRODUCTS_DIR}/Charts/Charts.framework" + install_framework "${BUILT_PRODUCTS_DIR}/Eddystone/Eddystone.framework" + install_framework "${BUILT_PRODUCTS_DIR}/IP-UIKit-Wisdom/IP_UIKit_Wisdom.framework" + install_framework "${BUILT_PRODUCTS_DIR}/KVOController/KVOController.framework" + install_framework "${BUILT_PRODUCTS_DIR}/MZTimerLabel/MZTimerLabel.framework" + install_framework "${BUILT_PRODUCTS_DIR}/PureLayout/PureLayout.framework" + install_framework "${BUILT_PRODUCTS_DIR}/SVProgressHUD/SVProgressHUD.framework" + install_framework "${BUILT_PRODUCTS_DIR}/UICircularProgressRing/UICircularProgressRing.framework" + install_framework "${BUILT_PRODUCTS_DIR}/WYPopoverController/WYPopoverController.framework" + install_framework "${BUILT_PRODUCTS_DIR}/XMLDictionary/XMLDictionary.framework" +fi +if [[ "$CONFIGURATION" == "Release" ]]; then + install_framework "${BUILT_PRODUCTS_DIR}/ActionSheetPicker-3.0/ActionSheetPicker_3_0.framework" + install_framework "${BUILT_PRODUCTS_DIR}/ChameleonFramework/ChameleonFramework.framework" + install_framework "${BUILT_PRODUCTS_DIR}/Charts/Charts.framework" + install_framework "${BUILT_PRODUCTS_DIR}/Eddystone/Eddystone.framework" + install_framework "${BUILT_PRODUCTS_DIR}/IP-UIKit-Wisdom/IP_UIKit_Wisdom.framework" + install_framework "${BUILT_PRODUCTS_DIR}/KVOController/KVOController.framework" + install_framework "${BUILT_PRODUCTS_DIR}/MZTimerLabel/MZTimerLabel.framework" + install_framework "${BUILT_PRODUCTS_DIR}/PureLayout/PureLayout.framework" + install_framework "${BUILT_PRODUCTS_DIR}/SVProgressHUD/SVProgressHUD.framework" + install_framework "${BUILT_PRODUCTS_DIR}/UICircularProgressRing/UICircularProgressRing.framework" + install_framework "${BUILT_PRODUCTS_DIR}/WYPopoverController/WYPopoverController.framework" + install_framework "${BUILT_PRODUCTS_DIR}/XMLDictionary/XMLDictionary.framework" +fi +if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then + wait +fi diff --git a/Pods/Target Support Files/Pods-BlueGeckoWithHomeKit/Pods-BlueGeckoWithHomeKit-resources.sh b/Pods/Target Support Files/Pods-BlueGeckoWithHomeKit/Pods-BlueGeckoWithHomeKit-resources.sh new file mode 100755 index 00000000..345301f2 --- /dev/null +++ b/Pods/Target Support Files/Pods-BlueGeckoWithHomeKit/Pods-BlueGeckoWithHomeKit-resources.sh @@ -0,0 +1,118 @@ +#!/bin/sh +set -e +set -u +set -o pipefail + +if [ -z ${UNLOCALIZED_RESOURCES_FOLDER_PATH+x} ]; then + # If UNLOCALIZED_RESOURCES_FOLDER_PATH is not set, then there's nowhere for us to copy + # resources to, so exit 0 (signalling the script phase was successful). + exit 0 +fi + +mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" + +RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt +> "$RESOURCES_TO_COPY" + +XCASSET_FILES=() + +# This protects against multiple targets copying the same framework dependency at the same time. The solution +# was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html +RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") + +case "${TARGETED_DEVICE_FAMILY:-}" in + 1,2) + TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" + ;; + 1) + TARGET_DEVICE_ARGS="--target-device iphone" + ;; + 2) + TARGET_DEVICE_ARGS="--target-device ipad" + ;; + 3) + TARGET_DEVICE_ARGS="--target-device tv" + ;; + 4) + TARGET_DEVICE_ARGS="--target-device watch" + ;; + *) + TARGET_DEVICE_ARGS="--target-device mac" + ;; +esac + +install_resource() +{ + if [[ "$1" = /* ]] ; then + RESOURCE_PATH="$1" + else + RESOURCE_PATH="${PODS_ROOT}/$1" + fi + if [[ ! -e "$RESOURCE_PATH" ]] ; then + cat << EOM +error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. +EOM + exit 1 + fi + case $RESOURCE_PATH in + *.storyboard) + echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true + ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} + ;; + *.xib) + echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true + ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} + ;; + *.framework) + echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true + mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + ;; + *.xcdatamodel) + echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" || true + xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" + ;; + *.xcdatamodeld) + echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" || true + xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" + ;; + *.xcmappingmodel) + echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" || true + xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" + ;; + *.xcassets) + ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH" + XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") + ;; + *) + echo "$RESOURCE_PATH" || true + echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" + ;; + esac +} + +mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" +rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" +if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then + mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" + rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" +fi +rm -f "$RESOURCES_TO_COPY" + +if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "${XCASSET_FILES:-}" ] +then + # Find all other xcassets (this unfortunately includes those of path pods and other targets). + OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) + while read line; do + if [[ $line != "${PODS_ROOT}*" ]]; then + XCASSET_FILES+=("$line") + fi + done <<<"$OTHER_XCASSETS" + + if [ -z ${ASSETCATALOG_COMPILER_APPICON_NAME+x} ]; then + printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" + else + printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" --app-icon "${ASSETCATALOG_COMPILER_APPICON_NAME}" --output-partial-info-plist "${TARGET_TEMP_DIR}/assetcatalog_generated_info_cocoapods.plist" + fi +fi diff --git a/Pods/Target Support Files/Pods-BlueGeckoWithHomeKit/Pods-BlueGeckoWithHomeKit-umbrella.h b/Pods/Target Support Files/Pods-BlueGeckoWithHomeKit/Pods-BlueGeckoWithHomeKit-umbrella.h new file mode 100644 index 00000000..4987ec99 --- /dev/null +++ b/Pods/Target Support Files/Pods-BlueGeckoWithHomeKit/Pods-BlueGeckoWithHomeKit-umbrella.h @@ -0,0 +1,16 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + + +FOUNDATION_EXPORT double Pods_BlueGeckoWithHomeKitVersionNumber; +FOUNDATION_EXPORT const unsigned char Pods_BlueGeckoWithHomeKitVersionString[]; + diff --git a/Pods/Target Support Files/Pods-BlueGeckoWithHomeKit/Pods-BlueGeckoWithHomeKit.debug.xcconfig b/Pods/Target Support Files/Pods-BlueGeckoWithHomeKit/Pods-BlueGeckoWithHomeKit.debug.xcconfig new file mode 100644 index 00000000..dbab75d5 --- /dev/null +++ b/Pods/Target Support Files/Pods-BlueGeckoWithHomeKit/Pods-BlueGeckoWithHomeKit.debug.xcconfig @@ -0,0 +1,11 @@ +ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/ActionSheetPicker-3.0" "${PODS_CONFIGURATION_BUILD_DIR}/ChameleonFramework" "${PODS_CONFIGURATION_BUILD_DIR}/Charts" "${PODS_CONFIGURATION_BUILD_DIR}/Eddystone" "${PODS_CONFIGURATION_BUILD_DIR}/IP-UIKit-Wisdom" "${PODS_CONFIGURATION_BUILD_DIR}/KVOController" "${PODS_CONFIGURATION_BUILD_DIR}/MZTimerLabel" "${PODS_CONFIGURATION_BUILD_DIR}/PureLayout" "${PODS_CONFIGURATION_BUILD_DIR}/SVProgressHUD" "${PODS_CONFIGURATION_BUILD_DIR}/UICircularProgressRing" "${PODS_CONFIGURATION_BUILD_DIR}/WYPopoverController" "${PODS_CONFIGURATION_BUILD_DIR}/XMLDictionary" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/ActionSheetPicker-3.0/ActionSheetPicker_3_0.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/ChameleonFramework/ChameleonFramework.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/Charts/Charts.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/Eddystone/Eddystone.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/IP-UIKit-Wisdom/IP_UIKit_Wisdom.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/KVOController/KVOController.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/MZTimerLabel/MZTimerLabel.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/PureLayout/PureLayout.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/SVProgressHUD/SVProgressHUD.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/UICircularProgressRing/UICircularProgressRing.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/WYPopoverController/WYPopoverController.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/XMLDictionary/XMLDictionary.framework/Headers" +OTHER_LDFLAGS = $(inherited) -framework "ActionSheetPicker_3_0" -framework "ChameleonFramework" -framework "Charts" -framework "Eddystone" -framework "IP_UIKit_Wisdom" -framework "KVOController" -framework "MZTimerLabel" -framework "PureLayout" -framework "SVProgressHUD" -framework "UICircularProgressRing" -framework "WYPopoverController" -framework "XMLDictionary" +OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_PODFILE_DIR_PATH = ${SRCROOT}/. +PODS_ROOT = ${SRCROOT}/Pods diff --git a/Pods/Target Support Files/Pods-BlueGeckoWithHomeKit/Pods-BlueGeckoWithHomeKit.modulemap b/Pods/Target Support Files/Pods-BlueGeckoWithHomeKit/Pods-BlueGeckoWithHomeKit.modulemap new file mode 100644 index 00000000..dbaa2937 --- /dev/null +++ b/Pods/Target Support Files/Pods-BlueGeckoWithHomeKit/Pods-BlueGeckoWithHomeKit.modulemap @@ -0,0 +1,6 @@ +framework module Pods_BlueGeckoWithHomeKit { + umbrella header "Pods-BlueGeckoWithHomeKit-umbrella.h" + + export * + module * { export * } +} diff --git a/Pods/Target Support Files/Pods-BlueGeckoWithHomeKit/Pods-BlueGeckoWithHomeKit.release.xcconfig b/Pods/Target Support Files/Pods-BlueGeckoWithHomeKit/Pods-BlueGeckoWithHomeKit.release.xcconfig new file mode 100644 index 00000000..dbab75d5 --- /dev/null +++ b/Pods/Target Support Files/Pods-BlueGeckoWithHomeKit/Pods-BlueGeckoWithHomeKit.release.xcconfig @@ -0,0 +1,11 @@ +ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/ActionSheetPicker-3.0" "${PODS_CONFIGURATION_BUILD_DIR}/ChameleonFramework" "${PODS_CONFIGURATION_BUILD_DIR}/Charts" "${PODS_CONFIGURATION_BUILD_DIR}/Eddystone" "${PODS_CONFIGURATION_BUILD_DIR}/IP-UIKit-Wisdom" "${PODS_CONFIGURATION_BUILD_DIR}/KVOController" "${PODS_CONFIGURATION_BUILD_DIR}/MZTimerLabel" "${PODS_CONFIGURATION_BUILD_DIR}/PureLayout" "${PODS_CONFIGURATION_BUILD_DIR}/SVProgressHUD" "${PODS_CONFIGURATION_BUILD_DIR}/UICircularProgressRing" "${PODS_CONFIGURATION_BUILD_DIR}/WYPopoverController" "${PODS_CONFIGURATION_BUILD_DIR}/XMLDictionary" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/ActionSheetPicker-3.0/ActionSheetPicker_3_0.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/ChameleonFramework/ChameleonFramework.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/Charts/Charts.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/Eddystone/Eddystone.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/IP-UIKit-Wisdom/IP_UIKit_Wisdom.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/KVOController/KVOController.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/MZTimerLabel/MZTimerLabel.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/PureLayout/PureLayout.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/SVProgressHUD/SVProgressHUD.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/UICircularProgressRing/UICircularProgressRing.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/WYPopoverController/WYPopoverController.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/XMLDictionary/XMLDictionary.framework/Headers" +OTHER_LDFLAGS = $(inherited) -framework "ActionSheetPicker_3_0" -framework "ChameleonFramework" -framework "Charts" -framework "Eddystone" -framework "IP_UIKit_Wisdom" -framework "KVOController" -framework "MZTimerLabel" -framework "PureLayout" -framework "SVProgressHUD" -framework "UICircularProgressRing" -framework "WYPopoverController" -framework "XMLDictionary" +OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_PODFILE_DIR_PATH = ${SRCROOT}/. +PODS_ROOT = ${SRCROOT}/Pods diff --git a/Pods/Target Support Files/Pods-WirelessGecko/Info.plist b/Pods/Target Support Files/Pods-WirelessGecko/Info.plist new file mode 100644 index 00000000..2243fe6e --- /dev/null +++ b/Pods/Target Support Files/Pods-WirelessGecko/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Pods/Target Support Files/Pods-WirelessGecko/Pods-WirelessGecko-acknowledgements.markdown b/Pods/Target Support Files/Pods-WirelessGecko/Pods-WirelessGecko-acknowledgements.markdown new file mode 100644 index 00000000..bd0c55b0 --- /dev/null +++ b/Pods/Target Support Files/Pods-WirelessGecko/Pods-WirelessGecko-acknowledgements.markdown @@ -0,0 +1,440 @@ +# Acknowledgements +This application makes use of the following third party libraries: + +## ActionSheetPicker-3.0 + +Copyright (c) 2011, Tim Cinel (see AUTHORS) +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +## ChameleonFramework + +##The MIT License (MIT) + +> Copyright (c) 2014-2015 Vicc Alexander + +> Permission is hereby granted, free of charge, to any person obtaining a copy +> of this software and associated documentation files (the "Software"), to deal +> in the Software without restriction, including without limitation the rights +> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +> copies of the Software, and to permit persons to whom the Software is +> furnished to do so, subject to the following conditions: + +> The above copyright notice and this permission notice shall be included in all +> copies or substantial portions of the Software. + +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +> SOFTWARE. + + +## Charts + +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2016 Daniel Cohen Gindi & Philipp Jahoda + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + +## Eddystone + +Copyright (c) 2015 Tanner Nelson + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +## IP-UIKit-Wisdom + +The MIT License (MIT) + +Copyright (c) 2015 Intrepid Pursuits LLC + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +## KVOController + +BSD License + +For KVOController software + +Copyright (c) 2014, Facebook, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name Facebook nor the names of its contributors may be used to + endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +## MZTimerLabel + +The MIT License (MIT) + +Copyright (c) 2013 mineschan + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +## PureLayout + +This code is distributed under the terms and conditions of the MIT license. + +Copyright (c) 2014-2015 Tyler Fox + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +## SVProgressHUD + +MIT License + +Copyright (c) 2011-2018 Sam Vermette, Tobias Tiemerding and contributors. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +## UICircularProgressRing + +Copyright (c) 2017 Luis Padron + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +## WYPopoverController + +WYPopoverController is available under the MIT license. + +Copyright © 2013 Nicolas CHENG + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +## XMLDictionary + +XMLDictionary + +Copyright (C) 2011 Charcoal Design + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +Generated by CocoaPods - https://cocoapods.org diff --git a/Pods/Target Support Files/Pods-WirelessGecko/Pods-WirelessGecko-acknowledgements.plist b/Pods/Target Support Files/Pods-WirelessGecko/Pods-WirelessGecko-acknowledgements.plist new file mode 100644 index 00000000..ff03efd0 --- /dev/null +++ b/Pods/Target Support Files/Pods-WirelessGecko/Pods-WirelessGecko-acknowledgements.plist @@ -0,0 +1,538 @@ + + + + + PreferenceSpecifiers + + + FooterText + This application makes use of the following third party libraries: + Title + Acknowledgements + Type + PSGroupSpecifier + + + FooterText + Copyright (c) 2011, Tim Cinel (see AUTHORS) +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the <organization> nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + License + BSD + Title + ActionSheetPicker-3.0 + Type + PSGroupSpecifier + + + FooterText + ##The MIT License (MIT) + +> Copyright (c) 2014-2015 Vicc Alexander + +> Permission is hereby granted, free of charge, to any person obtaining a copy +> of this software and associated documentation files (the "Software"), to deal +> in the Software without restriction, including without limitation the rights +> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +> copies of the Software, and to permit persons to whom the Software is +> furnished to do so, subject to the following conditions: + +> The above copyright notice and this permission notice shall be included in all +> copies or substantial portions of the Software. + +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +> SOFTWARE. + + License + MIT + Title + ChameleonFramework + Type + PSGroupSpecifier + + + FooterText + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2016 Daniel Cohen Gindi & Philipp Jahoda + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + License + Apache License, Version 2.0 + Title + Charts + Type + PSGroupSpecifier + + + FooterText + Copyright (c) 2015 Tanner Nelson <tanner@bluebite.com> + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + License + MIT + Title + Eddystone + Type + PSGroupSpecifier + + + FooterText + The MIT License (MIT) + +Copyright (c) 2015 Intrepid Pursuits LLC + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + License + MIT + Title + IP-UIKit-Wisdom + Type + PSGroupSpecifier + + + FooterText + BSD License + +For KVOController software + +Copyright (c) 2014, Facebook, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name Facebook nor the names of its contributors may be used to + endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + License + BSD + Title + KVOController + Type + PSGroupSpecifier + + + FooterText + The MIT License (MIT) + +Copyright (c) 2013 mineschan + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + License + MIT + Title + MZTimerLabel + Type + PSGroupSpecifier + + + FooterText + This code is distributed under the terms and conditions of the MIT license. + +Copyright (c) 2014-2015 Tyler Fox + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + License + MIT + Title + PureLayout + Type + PSGroupSpecifier + + + FooterText + MIT License + +Copyright (c) 2011-2018 Sam Vermette, Tobias Tiemerding and contributors. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + License + MIT + Title + SVProgressHUD + Type + PSGroupSpecifier + + + FooterText + Copyright (c) 2017 Luis Padron + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + License + MIT + Title + UICircularProgressRing + Type + PSGroupSpecifier + + + FooterText + WYPopoverController is available under the MIT license. + +Copyright © 2013 Nicolas CHENG + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + License + MIT + Title + WYPopoverController + Type + PSGroupSpecifier + + + FooterText + XMLDictionary + +Copyright (C) 2011 Charcoal Design + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. + License + zlib + Title + XMLDictionary + Type + PSGroupSpecifier + + + FooterText + Generated by CocoaPods - https://cocoapods.org + Title + + Type + PSGroupSpecifier + + + StringsTable + Acknowledgements + Title + Acknowledgements + + diff --git a/Pods/Target Support Files/Pods-WirelessGecko/Pods-WirelessGecko-dummy.m b/Pods/Target Support Files/Pods-WirelessGecko/Pods-WirelessGecko-dummy.m new file mode 100644 index 00000000..86fe78af --- /dev/null +++ b/Pods/Target Support Files/Pods-WirelessGecko/Pods-WirelessGecko-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_Pods_WirelessGecko : NSObject +@end +@implementation PodsDummy_Pods_WirelessGecko +@end diff --git a/Pods/Target Support Files/Pods-WirelessGecko/Pods-WirelessGecko-frameworks.sh b/Pods/Target Support Files/Pods-WirelessGecko/Pods-WirelessGecko-frameworks.sh new file mode 100755 index 00000000..47998d17 --- /dev/null +++ b/Pods/Target Support Files/Pods-WirelessGecko/Pods-WirelessGecko-frameworks.sh @@ -0,0 +1,175 @@ +#!/bin/sh +set -e +set -u +set -o pipefail + +if [ -z ${FRAMEWORKS_FOLDER_PATH+x} ]; then + # If FRAMEWORKS_FOLDER_PATH is not set, then there's nowhere for us to copy + # frameworks to, so exit 0 (signalling the script phase was successful). + exit 0 +fi + +echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" +mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + +COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}" +SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" + +# Used as a return value for each invocation of `strip_invalid_archs` function. +STRIP_BINARY_RETVAL=0 + +# This protects against multiple targets copying the same framework dependency at the same time. The solution +# was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html +RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") + +# Copies and strips a vendored framework +install_framework() +{ + if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then + local source="${BUILT_PRODUCTS_DIR}/$1" + elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then + local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" + elif [ -r "$1" ]; then + local source="$1" + fi + + local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + + if [ -L "${source}" ]; then + echo "Symlinked..." + source="$(readlink "${source}")" + fi + + # Use filter instead of exclude so missing patterns don't throw errors. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" + + local basename + basename="$(basename -s .framework "$1")" + binary="${destination}/${basename}.framework/${basename}" + if ! [ -r "$binary" ]; then + binary="${destination}/${basename}" + fi + + # Strip invalid architectures so "fat" simulator / device frameworks work on device + if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then + strip_invalid_archs "$binary" + fi + + # Resign the code if required by the build settings to avoid unstable apps + code_sign_if_enabled "${destination}/$(basename "$1")" + + # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. + if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then + local swift_runtime_libs + swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) + for lib in $swift_runtime_libs; do + echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" + rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" + code_sign_if_enabled "${destination}/${lib}" + done + fi +} + +# Copies and strips a vendored dSYM +install_dsym() { + local source="$1" + if [ -r "$source" ]; then + # Copy the dSYM into a the targets temp dir. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}" + + local basename + basename="$(basename -s .framework.dSYM "$source")" + binary="${DERIVED_FILES_DIR}/${basename}.framework.dSYM/Contents/Resources/DWARF/${basename}" + + # Strip invalid architectures so "fat" simulator / device frameworks work on device + if [[ "$(file "$binary")" == *"Mach-O dSYM companion"* ]]; then + strip_invalid_archs "$binary" + fi + + if [[ $STRIP_BINARY_RETVAL == 1 ]]; then + # Move the stripped file into its final destination. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.framework.dSYM" "${DWARF_DSYM_FOLDER_PATH}" + else + # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing. + touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.framework.dSYM" + fi + fi +} + +# Signs a framework with the provided identity +code_sign_if_enabled() { + if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then + # Use the current code_sign_identitiy + echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" + local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements '$1'" + + if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then + code_sign_cmd="$code_sign_cmd &" + fi + echo "$code_sign_cmd" + eval "$code_sign_cmd" + fi +} + +# Strip invalid architectures +strip_invalid_archs() { + binary="$1" + # Get architectures for current target binary + binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)" + # Intersect them with the architectures we are building for + intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)" + # If there are no archs supported by this binary then warn the user + if [[ -z "$intersected_archs" ]]; then + echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)." + STRIP_BINARY_RETVAL=0 + return + fi + stripped="" + for arch in $binary_archs; do + if ! [[ "${ARCHS}" == *"$arch"* ]]; then + # Strip non-valid architectures in-place + lipo -remove "$arch" -output "$binary" "$binary" || exit 1 + stripped="$stripped $arch" + fi + done + if [[ "$stripped" ]]; then + echo "Stripped $binary of architectures:$stripped" + fi + STRIP_BINARY_RETVAL=1 +} + + +if [[ "$CONFIGURATION" == "Debug" ]]; then + install_framework "${BUILT_PRODUCTS_DIR}/ActionSheetPicker-3.0/ActionSheetPicker_3_0.framework" + install_framework "${BUILT_PRODUCTS_DIR}/ChameleonFramework/ChameleonFramework.framework" + install_framework "${BUILT_PRODUCTS_DIR}/Charts/Charts.framework" + install_framework "${BUILT_PRODUCTS_DIR}/Eddystone/Eddystone.framework" + install_framework "${BUILT_PRODUCTS_DIR}/IP-UIKit-Wisdom/IP_UIKit_Wisdom.framework" + install_framework "${BUILT_PRODUCTS_DIR}/KVOController/KVOController.framework" + install_framework "${BUILT_PRODUCTS_DIR}/MZTimerLabel/MZTimerLabel.framework" + install_framework "${BUILT_PRODUCTS_DIR}/PureLayout/PureLayout.framework" + install_framework "${BUILT_PRODUCTS_DIR}/SVProgressHUD/SVProgressHUD.framework" + install_framework "${BUILT_PRODUCTS_DIR}/UICircularProgressRing/UICircularProgressRing.framework" + install_framework "${BUILT_PRODUCTS_DIR}/WYPopoverController/WYPopoverController.framework" + install_framework "${BUILT_PRODUCTS_DIR}/XMLDictionary/XMLDictionary.framework" +fi +if [[ "$CONFIGURATION" == "Release" ]]; then + install_framework "${BUILT_PRODUCTS_DIR}/ActionSheetPicker-3.0/ActionSheetPicker_3_0.framework" + install_framework "${BUILT_PRODUCTS_DIR}/ChameleonFramework/ChameleonFramework.framework" + install_framework "${BUILT_PRODUCTS_DIR}/Charts/Charts.framework" + install_framework "${BUILT_PRODUCTS_DIR}/Eddystone/Eddystone.framework" + install_framework "${BUILT_PRODUCTS_DIR}/IP-UIKit-Wisdom/IP_UIKit_Wisdom.framework" + install_framework "${BUILT_PRODUCTS_DIR}/KVOController/KVOController.framework" + install_framework "${BUILT_PRODUCTS_DIR}/MZTimerLabel/MZTimerLabel.framework" + install_framework "${BUILT_PRODUCTS_DIR}/PureLayout/PureLayout.framework" + install_framework "${BUILT_PRODUCTS_DIR}/SVProgressHUD/SVProgressHUD.framework" + install_framework "${BUILT_PRODUCTS_DIR}/UICircularProgressRing/UICircularProgressRing.framework" + install_framework "${BUILT_PRODUCTS_DIR}/WYPopoverController/WYPopoverController.framework" + install_framework "${BUILT_PRODUCTS_DIR}/XMLDictionary/XMLDictionary.framework" +fi +if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then + wait +fi diff --git a/Pods/Target Support Files/Pods-WirelessGecko/Pods-WirelessGecko-resources.sh b/Pods/Target Support Files/Pods-WirelessGecko/Pods-WirelessGecko-resources.sh new file mode 100755 index 00000000..345301f2 --- /dev/null +++ b/Pods/Target Support Files/Pods-WirelessGecko/Pods-WirelessGecko-resources.sh @@ -0,0 +1,118 @@ +#!/bin/sh +set -e +set -u +set -o pipefail + +if [ -z ${UNLOCALIZED_RESOURCES_FOLDER_PATH+x} ]; then + # If UNLOCALIZED_RESOURCES_FOLDER_PATH is not set, then there's nowhere for us to copy + # resources to, so exit 0 (signalling the script phase was successful). + exit 0 +fi + +mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" + +RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt +> "$RESOURCES_TO_COPY" + +XCASSET_FILES=() + +# This protects against multiple targets copying the same framework dependency at the same time. The solution +# was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html +RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") + +case "${TARGETED_DEVICE_FAMILY:-}" in + 1,2) + TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" + ;; + 1) + TARGET_DEVICE_ARGS="--target-device iphone" + ;; + 2) + TARGET_DEVICE_ARGS="--target-device ipad" + ;; + 3) + TARGET_DEVICE_ARGS="--target-device tv" + ;; + 4) + TARGET_DEVICE_ARGS="--target-device watch" + ;; + *) + TARGET_DEVICE_ARGS="--target-device mac" + ;; +esac + +install_resource() +{ + if [[ "$1" = /* ]] ; then + RESOURCE_PATH="$1" + else + RESOURCE_PATH="${PODS_ROOT}/$1" + fi + if [[ ! -e "$RESOURCE_PATH" ]] ; then + cat << EOM +error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. +EOM + exit 1 + fi + case $RESOURCE_PATH in + *.storyboard) + echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true + ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} + ;; + *.xib) + echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true + ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} + ;; + *.framework) + echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true + mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + ;; + *.xcdatamodel) + echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" || true + xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" + ;; + *.xcdatamodeld) + echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" || true + xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" + ;; + *.xcmappingmodel) + echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" || true + xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" + ;; + *.xcassets) + ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH" + XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") + ;; + *) + echo "$RESOURCE_PATH" || true + echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" + ;; + esac +} + +mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" +rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" +if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then + mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" + rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" +fi +rm -f "$RESOURCES_TO_COPY" + +if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "${XCASSET_FILES:-}" ] +then + # Find all other xcassets (this unfortunately includes those of path pods and other targets). + OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) + while read line; do + if [[ $line != "${PODS_ROOT}*" ]]; then + XCASSET_FILES+=("$line") + fi + done <<<"$OTHER_XCASSETS" + + if [ -z ${ASSETCATALOG_COMPILER_APPICON_NAME+x} ]; then + printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" + else + printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" --app-icon "${ASSETCATALOG_COMPILER_APPICON_NAME}" --output-partial-info-plist "${TARGET_TEMP_DIR}/assetcatalog_generated_info_cocoapods.plist" + fi +fi diff --git a/Pods/Target Support Files/Pods-WirelessGecko/Pods-WirelessGecko-umbrella.h b/Pods/Target Support Files/Pods-WirelessGecko/Pods-WirelessGecko-umbrella.h new file mode 100644 index 00000000..7db2bd30 --- /dev/null +++ b/Pods/Target Support Files/Pods-WirelessGecko/Pods-WirelessGecko-umbrella.h @@ -0,0 +1,16 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + + +FOUNDATION_EXPORT double Pods_WirelessGeckoVersionNumber; +FOUNDATION_EXPORT const unsigned char Pods_WirelessGeckoVersionString[]; + diff --git a/Pods/Target Support Files/Pods-WirelessGecko/Pods-WirelessGecko.debug.xcconfig b/Pods/Target Support Files/Pods-WirelessGecko/Pods-WirelessGecko.debug.xcconfig new file mode 100644 index 00000000..dbab75d5 --- /dev/null +++ b/Pods/Target Support Files/Pods-WirelessGecko/Pods-WirelessGecko.debug.xcconfig @@ -0,0 +1,11 @@ +ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/ActionSheetPicker-3.0" "${PODS_CONFIGURATION_BUILD_DIR}/ChameleonFramework" "${PODS_CONFIGURATION_BUILD_DIR}/Charts" "${PODS_CONFIGURATION_BUILD_DIR}/Eddystone" "${PODS_CONFIGURATION_BUILD_DIR}/IP-UIKit-Wisdom" "${PODS_CONFIGURATION_BUILD_DIR}/KVOController" "${PODS_CONFIGURATION_BUILD_DIR}/MZTimerLabel" "${PODS_CONFIGURATION_BUILD_DIR}/PureLayout" "${PODS_CONFIGURATION_BUILD_DIR}/SVProgressHUD" "${PODS_CONFIGURATION_BUILD_DIR}/UICircularProgressRing" "${PODS_CONFIGURATION_BUILD_DIR}/WYPopoverController" "${PODS_CONFIGURATION_BUILD_DIR}/XMLDictionary" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/ActionSheetPicker-3.0/ActionSheetPicker_3_0.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/ChameleonFramework/ChameleonFramework.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/Charts/Charts.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/Eddystone/Eddystone.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/IP-UIKit-Wisdom/IP_UIKit_Wisdom.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/KVOController/KVOController.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/MZTimerLabel/MZTimerLabel.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/PureLayout/PureLayout.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/SVProgressHUD/SVProgressHUD.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/UICircularProgressRing/UICircularProgressRing.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/WYPopoverController/WYPopoverController.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/XMLDictionary/XMLDictionary.framework/Headers" +OTHER_LDFLAGS = $(inherited) -framework "ActionSheetPicker_3_0" -framework "ChameleonFramework" -framework "Charts" -framework "Eddystone" -framework "IP_UIKit_Wisdom" -framework "KVOController" -framework "MZTimerLabel" -framework "PureLayout" -framework "SVProgressHUD" -framework "UICircularProgressRing" -framework "WYPopoverController" -framework "XMLDictionary" +OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_PODFILE_DIR_PATH = ${SRCROOT}/. +PODS_ROOT = ${SRCROOT}/Pods diff --git a/Pods/Target Support Files/Pods-WirelessGecko/Pods-WirelessGecko.modulemap b/Pods/Target Support Files/Pods-WirelessGecko/Pods-WirelessGecko.modulemap new file mode 100644 index 00000000..65d8ca44 --- /dev/null +++ b/Pods/Target Support Files/Pods-WirelessGecko/Pods-WirelessGecko.modulemap @@ -0,0 +1,6 @@ +framework module Pods_WirelessGecko { + umbrella header "Pods-WirelessGecko-umbrella.h" + + export * + module * { export * } +} diff --git a/Pods/Target Support Files/Pods-WirelessGecko/Pods-WirelessGecko.release.xcconfig b/Pods/Target Support Files/Pods-WirelessGecko/Pods-WirelessGecko.release.xcconfig new file mode 100644 index 00000000..dbab75d5 --- /dev/null +++ b/Pods/Target Support Files/Pods-WirelessGecko/Pods-WirelessGecko.release.xcconfig @@ -0,0 +1,11 @@ +ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/ActionSheetPicker-3.0" "${PODS_CONFIGURATION_BUILD_DIR}/ChameleonFramework" "${PODS_CONFIGURATION_BUILD_DIR}/Charts" "${PODS_CONFIGURATION_BUILD_DIR}/Eddystone" "${PODS_CONFIGURATION_BUILD_DIR}/IP-UIKit-Wisdom" "${PODS_CONFIGURATION_BUILD_DIR}/KVOController" "${PODS_CONFIGURATION_BUILD_DIR}/MZTimerLabel" "${PODS_CONFIGURATION_BUILD_DIR}/PureLayout" "${PODS_CONFIGURATION_BUILD_DIR}/SVProgressHUD" "${PODS_CONFIGURATION_BUILD_DIR}/UICircularProgressRing" "${PODS_CONFIGURATION_BUILD_DIR}/WYPopoverController" "${PODS_CONFIGURATION_BUILD_DIR}/XMLDictionary" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/ActionSheetPicker-3.0/ActionSheetPicker_3_0.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/ChameleonFramework/ChameleonFramework.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/Charts/Charts.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/Eddystone/Eddystone.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/IP-UIKit-Wisdom/IP_UIKit_Wisdom.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/KVOController/KVOController.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/MZTimerLabel/MZTimerLabel.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/PureLayout/PureLayout.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/SVProgressHUD/SVProgressHUD.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/UICircularProgressRing/UICircularProgressRing.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/WYPopoverController/WYPopoverController.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/XMLDictionary/XMLDictionary.framework/Headers" +OTHER_LDFLAGS = $(inherited) -framework "ActionSheetPicker_3_0" -framework "ChameleonFramework" -framework "Charts" -framework "Eddystone" -framework "IP_UIKit_Wisdom" -framework "KVOController" -framework "MZTimerLabel" -framework "PureLayout" -framework "SVProgressHUD" -framework "UICircularProgressRing" -framework "WYPopoverController" -framework "XMLDictionary" +OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_PODFILE_DIR_PATH = ${SRCROOT}/. +PODS_ROOT = ${SRCROOT}/Pods diff --git a/Pods/Target Support Files/PureLayout/Info.plist b/Pods/Target Support Files/PureLayout/Info.plist new file mode 100644 index 00000000..36f2c7e2 --- /dev/null +++ b/Pods/Target Support Files/PureLayout/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 3.1.4 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Pods/Target Support Files/PureLayout/PureLayout-dummy.m b/Pods/Target Support Files/PureLayout/PureLayout-dummy.m new file mode 100644 index 00000000..de09ca1e --- /dev/null +++ b/Pods/Target Support Files/PureLayout/PureLayout-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_PureLayout : NSObject +@end +@implementation PodsDummy_PureLayout +@end diff --git a/Pods/Target Support Files/PureLayout/PureLayout-prefix.pch b/Pods/Target Support Files/PureLayout/PureLayout-prefix.pch new file mode 100644 index 00000000..beb2a244 --- /dev/null +++ b/Pods/Target Support Files/PureLayout/PureLayout-prefix.pch @@ -0,0 +1,12 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + diff --git a/Pods/Target Support Files/PureLayout/PureLayout-umbrella.h b/Pods/Target Support Files/PureLayout/PureLayout-umbrella.h new file mode 100644 index 00000000..66f0025c --- /dev/null +++ b/Pods/Target Support Files/PureLayout/PureLayout-umbrella.h @@ -0,0 +1,22 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "ALView+PureLayout.h" +#import "NSArray+PureLayout.h" +#import "NSLayoutConstraint+PureLayout.h" +#import "PureLayout+Internal.h" +#import "PureLayout.h" +#import "PureLayoutDefines.h" + +FOUNDATION_EXPORT double PureLayoutVersionNumber; +FOUNDATION_EXPORT const unsigned char PureLayoutVersionString[]; + diff --git a/Pods/Target Support Files/PureLayout/PureLayout.modulemap b/Pods/Target Support Files/PureLayout/PureLayout.modulemap new file mode 100644 index 00000000..fd62d584 --- /dev/null +++ b/Pods/Target Support Files/PureLayout/PureLayout.modulemap @@ -0,0 +1,6 @@ +framework module PureLayout { + umbrella header "PureLayout-umbrella.h" + + export * + module * { export * } +} diff --git a/Pods/Target Support Files/PureLayout/PureLayout.xcconfig b/Pods/Target Support Files/PureLayout/PureLayout.xcconfig new file mode 100644 index 00000000..73d448e7 --- /dev/null +++ b/Pods/Target Support Files/PureLayout/PureLayout.xcconfig @@ -0,0 +1,8 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/PureLayout +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/PureLayout +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES diff --git a/Pods/Target Support Files/SVProgressHUD/Info.plist b/Pods/Target Support Files/SVProgressHUD/Info.plist new file mode 100644 index 00000000..ce4ba6f8 --- /dev/null +++ b/Pods/Target Support Files/SVProgressHUD/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 2.2.5 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Pods/Target Support Files/SVProgressHUD/SVProgressHUD-dummy.m b/Pods/Target Support Files/SVProgressHUD/SVProgressHUD-dummy.m new file mode 100644 index 00000000..696032a7 --- /dev/null +++ b/Pods/Target Support Files/SVProgressHUD/SVProgressHUD-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_SVProgressHUD : NSObject +@end +@implementation PodsDummy_SVProgressHUD +@end diff --git a/Pods/Target Support Files/SVProgressHUD/SVProgressHUD-prefix.pch b/Pods/Target Support Files/SVProgressHUD/SVProgressHUD-prefix.pch new file mode 100644 index 00000000..beb2a244 --- /dev/null +++ b/Pods/Target Support Files/SVProgressHUD/SVProgressHUD-prefix.pch @@ -0,0 +1,12 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + diff --git a/Pods/Target Support Files/SVProgressHUD/SVProgressHUD-umbrella.h b/Pods/Target Support Files/SVProgressHUD/SVProgressHUD-umbrella.h new file mode 100644 index 00000000..bff1d78b --- /dev/null +++ b/Pods/Target Support Files/SVProgressHUD/SVProgressHUD-umbrella.h @@ -0,0 +1,20 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "SVIndefiniteAnimatedView.h" +#import "SVProgressAnimatedView.h" +#import "SVProgressHUD.h" +#import "SVRadialGradientLayer.h" + +FOUNDATION_EXPORT double SVProgressHUDVersionNumber; +FOUNDATION_EXPORT const unsigned char SVProgressHUDVersionString[]; + diff --git a/Pods/Target Support Files/SVProgressHUD/SVProgressHUD.modulemap b/Pods/Target Support Files/SVProgressHUD/SVProgressHUD.modulemap new file mode 100644 index 00000000..2eaf140a --- /dev/null +++ b/Pods/Target Support Files/SVProgressHUD/SVProgressHUD.modulemap @@ -0,0 +1,6 @@ +framework module SVProgressHUD { + umbrella header "SVProgressHUD-umbrella.h" + + export * + module * { export * } +} diff --git a/Pods/Target Support Files/SVProgressHUD/SVProgressHUD.xcconfig b/Pods/Target Support Files/SVProgressHUD/SVProgressHUD.xcconfig new file mode 100644 index 00000000..6798f203 --- /dev/null +++ b/Pods/Target Support Files/SVProgressHUD/SVProgressHUD.xcconfig @@ -0,0 +1,9 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/SVProgressHUD +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +OTHER_LDFLAGS = -framework "QuartzCore" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/SVProgressHUD +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES diff --git a/Pods/Target Support Files/UICircularProgressRing/Info.plist b/Pods/Target Support Files/UICircularProgressRing/Info.plist new file mode 100644 index 00000000..c26f36f0 --- /dev/null +++ b/Pods/Target Support Files/UICircularProgressRing/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 4.1.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Pods/Target Support Files/UICircularProgressRing/UICircularProgressRing-dummy.m b/Pods/Target Support Files/UICircularProgressRing/UICircularProgressRing-dummy.m new file mode 100644 index 00000000..bbcdde3a --- /dev/null +++ b/Pods/Target Support Files/UICircularProgressRing/UICircularProgressRing-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_UICircularProgressRing : NSObject +@end +@implementation PodsDummy_UICircularProgressRing +@end diff --git a/Pods/Target Support Files/UICircularProgressRing/UICircularProgressRing-prefix.pch b/Pods/Target Support Files/UICircularProgressRing/UICircularProgressRing-prefix.pch new file mode 100644 index 00000000..beb2a244 --- /dev/null +++ b/Pods/Target Support Files/UICircularProgressRing/UICircularProgressRing-prefix.pch @@ -0,0 +1,12 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + diff --git a/Pods/Target Support Files/UICircularProgressRing/UICircularProgressRing-umbrella.h b/Pods/Target Support Files/UICircularProgressRing/UICircularProgressRing-umbrella.h new file mode 100644 index 00000000..a62ff397 --- /dev/null +++ b/Pods/Target Support Files/UICircularProgressRing/UICircularProgressRing-umbrella.h @@ -0,0 +1,17 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "UICircularProgressRing.h" + +FOUNDATION_EXPORT double UICircularProgressRingVersionNumber; +FOUNDATION_EXPORT const unsigned char UICircularProgressRingVersionString[]; + diff --git a/Pods/Target Support Files/UICircularProgressRing/UICircularProgressRing.modulemap b/Pods/Target Support Files/UICircularProgressRing/UICircularProgressRing.modulemap new file mode 100644 index 00000000..2e13fb78 --- /dev/null +++ b/Pods/Target Support Files/UICircularProgressRing/UICircularProgressRing.modulemap @@ -0,0 +1,6 @@ +framework module UICircularProgressRing { + umbrella header "UICircularProgressRing-umbrella.h" + + export * + module * { export * } +} diff --git a/Pods/Target Support Files/UICircularProgressRing/UICircularProgressRing.xcconfig b/Pods/Target Support Files/UICircularProgressRing/UICircularProgressRing.xcconfig new file mode 100644 index 00000000..0ec131bb --- /dev/null +++ b/Pods/Target Support Files/UICircularProgressRing/UICircularProgressRing.xcconfig @@ -0,0 +1,9 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/UICircularProgressRing +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" "-suppress-warnings" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/UICircularProgressRing +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES diff --git a/Pods/Target Support Files/WYPopoverController/Info.plist b/Pods/Target Support Files/WYPopoverController/Info.plist new file mode 100644 index 00000000..3f68a24c --- /dev/null +++ b/Pods/Target Support Files/WYPopoverController/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 0.2.2 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Pods/Target Support Files/WYPopoverController/WYPopoverController-dummy.m b/Pods/Target Support Files/WYPopoverController/WYPopoverController-dummy.m new file mode 100644 index 00000000..1ef20df2 --- /dev/null +++ b/Pods/Target Support Files/WYPopoverController/WYPopoverController-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_WYPopoverController : NSObject +@end +@implementation PodsDummy_WYPopoverController +@end diff --git a/Pods/Target Support Files/WYPopoverController/WYPopoverController-prefix.pch b/Pods/Target Support Files/WYPopoverController/WYPopoverController-prefix.pch new file mode 100644 index 00000000..beb2a244 --- /dev/null +++ b/Pods/Target Support Files/WYPopoverController/WYPopoverController-prefix.pch @@ -0,0 +1,12 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + diff --git a/Pods/Target Support Files/WYPopoverController/WYPopoverController-umbrella.h b/Pods/Target Support Files/WYPopoverController/WYPopoverController-umbrella.h new file mode 100644 index 00000000..98c18dd8 --- /dev/null +++ b/Pods/Target Support Files/WYPopoverController/WYPopoverController-umbrella.h @@ -0,0 +1,18 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "WYPopoverController.h" +#import "WYStoryboardPopoverSegue.h" + +FOUNDATION_EXPORT double WYPopoverControllerVersionNumber; +FOUNDATION_EXPORT const unsigned char WYPopoverControllerVersionString[]; + diff --git a/Pods/Target Support Files/WYPopoverController/WYPopoverController.modulemap b/Pods/Target Support Files/WYPopoverController/WYPopoverController.modulemap new file mode 100644 index 00000000..c869ab0c --- /dev/null +++ b/Pods/Target Support Files/WYPopoverController/WYPopoverController.modulemap @@ -0,0 +1,6 @@ +framework module WYPopoverController { + umbrella header "WYPopoverController-umbrella.h" + + export * + module * { export * } +} diff --git a/Pods/Target Support Files/WYPopoverController/WYPopoverController.xcconfig b/Pods/Target Support Files/WYPopoverController/WYPopoverController.xcconfig new file mode 100644 index 00000000..13a88720 --- /dev/null +++ b/Pods/Target Support Files/WYPopoverController/WYPopoverController.xcconfig @@ -0,0 +1,9 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/WYPopoverController +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +OTHER_LDFLAGS = -framework "CoreGraphics" -framework "QuartzCore" -framework "UIKit" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/WYPopoverController +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES diff --git a/Pods/Target Support Files/XMLDictionary/Info.plist b/Pods/Target Support Files/XMLDictionary/Info.plist new file mode 100644 index 00000000..93197ee7 --- /dev/null +++ b/Pods/Target Support Files/XMLDictionary/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.4.1 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Pods/Target Support Files/XMLDictionary/XMLDictionary-dummy.m b/Pods/Target Support Files/XMLDictionary/XMLDictionary-dummy.m new file mode 100644 index 00000000..a031366a --- /dev/null +++ b/Pods/Target Support Files/XMLDictionary/XMLDictionary-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_XMLDictionary : NSObject +@end +@implementation PodsDummy_XMLDictionary +@end diff --git a/Pods/Target Support Files/XMLDictionary/XMLDictionary-prefix.pch b/Pods/Target Support Files/XMLDictionary/XMLDictionary-prefix.pch new file mode 100644 index 00000000..beb2a244 --- /dev/null +++ b/Pods/Target Support Files/XMLDictionary/XMLDictionary-prefix.pch @@ -0,0 +1,12 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + diff --git a/Pods/Target Support Files/XMLDictionary/XMLDictionary-umbrella.h b/Pods/Target Support Files/XMLDictionary/XMLDictionary-umbrella.h new file mode 100644 index 00000000..39e56083 --- /dev/null +++ b/Pods/Target Support Files/XMLDictionary/XMLDictionary-umbrella.h @@ -0,0 +1,17 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "XMLDictionary.h" + +FOUNDATION_EXPORT double XMLDictionaryVersionNumber; +FOUNDATION_EXPORT const unsigned char XMLDictionaryVersionString[]; + diff --git a/Pods/Target Support Files/XMLDictionary/XMLDictionary.modulemap b/Pods/Target Support Files/XMLDictionary/XMLDictionary.modulemap new file mode 100644 index 00000000..d4188b83 --- /dev/null +++ b/Pods/Target Support Files/XMLDictionary/XMLDictionary.modulemap @@ -0,0 +1,6 @@ +framework module XMLDictionary { + umbrella header "XMLDictionary-umbrella.h" + + export * + module * { export * } +} diff --git a/Pods/Target Support Files/XMLDictionary/XMLDictionary.xcconfig b/Pods/Target Support Files/XMLDictionary/XMLDictionary.xcconfig new file mode 100644 index 00000000..31b0e59d --- /dev/null +++ b/Pods/Target Support Files/XMLDictionary/XMLDictionary.xcconfig @@ -0,0 +1,8 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/XMLDictionary +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/XMLDictionary +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES diff --git a/Pods/UICircularProgressRing/LICENSE b/Pods/UICircularProgressRing/LICENSE new file mode 100644 index 00000000..ae072132 --- /dev/null +++ b/Pods/UICircularProgressRing/LICENSE @@ -0,0 +1,7 @@ +Copyright (c) 2017 Luis Padron + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/Pods/UICircularProgressRing/README.md b/Pods/UICircularProgressRing/README.md new file mode 100644 index 00000000..1a9adeda --- /dev/null +++ b/Pods/UICircularProgressRing/README.md @@ -0,0 +1,126 @@ +

+ + + + +

+ +![Banner](https://raw.githubusercontent.com/luispadron/UICircularProgressRing/master/.github/banner.png) + +

A circular progress bar for iOS written in Swift

+ +

+ +

+ +![Styles](https://raw.githubusercontent.com/luispadron/UICircularProgressRing/master/.github/styles-banner.png) + +## Features + +* Interface builder designable +* Highly customizable and flexible +* Easy to use +* Fluid and interruptible animations +* Written in Swift +* RTL language support + +## Apps Usig UICircularProgressRing + +- [GradePoint](http://gradepoint.luispadron.com) by Luis Padron. + +- [UVI Mate](https://itunes.apple.com/us/app/uvi-mate-global-uv-index-now/id1207745216?mt=8) by Alexander Ershov. + +- [HotelTonight](https://itunes.apple.com/app/id407690035?mt=8) by Hotel Tonight Inc. + +- [הנתיב המהיר](https://itunes.apple.com/us/app/הנתיב-המהיר/id1320456872?mt=8) by Elad Hayun + +## Installation + +### CocoaPods (Recommended) + +1. Install [CocoaPods](https://cocoapods.org) +2. Add this repo to your `Podfile` + + ```ruby + target 'Example' do + # IMPORTANT: Make sure use_frameworks! is included at the top of the file + use_frameworks! + + pod 'UICircularProgressRing' + end + ``` +3. Run `pod install` +4. Open up the `.xcworkspace` that CocoaPods created +5. Done! + +### Carthage + +#### Important: Interface builder support with Carthage is either broken or extremely limted + +To use with [Carthage](https://github.com/Carthage/Carthage) + +1. Make sure Carthage is installed + + `brew install carthage` +2. Add this repo to your Cartfile + + `github "luispadron/UICircularProgressRing"` +3. Install dependencies + `carthage update --platform iOS` + +## Usage + +### Interface Builder + +Simply drag a `UIView` into your storyboard. Make sure to subclass `UICircularProgressRing` and that the module points to `UICircularProgressRing`. + +Design your heart out + +![ib-demo.gif](https://raw.githubusercontent.com/luispadron/UICircularProgressRing/master/.github/ib-demo.gif) + +### Code + +```swift +override func viewDidLoad() { + // Create the view + let progressRing = UICircularProgressRing(frame: CGRect(x: 0, y: 0, width: 240, height: 240)) + // Change any of the properties you'd like + progressRing.maxValue = 50 + progressRing.innerRingColor = UIColor.blue + // etc ... +} +``` + +To set a value and animate the view + +```swift +// Somewhere not in viewDidLoad (since the views have not set yet, thus cannot be animated) +// Remember to use unowned or weak self if refrencing self to avoid retain cycle +progressRing.startProgress(to: 49, duration: 2.0) { + print("Done animating!") + // Do anything your heart desires... +} + +// Pause at any time during a running animation +progressRing.pauseProgress() + +// Continue where you left off after a pause +progressRing.continueProgress() +``` + +## Documentation + +Please read this before creating an issue about how to use the package: + +[DOCUMENTATION](https://htmlpreview.github.io/?https://raw.githubusercontent.com/luispadron/UICircularProgressRing/master/docs/Classes/UICircularProgressRing.html) + +## Example project + +Take a look at the example playground over [here](Example/) + +1. Download it +2. Mess around and experiment! + +## Misc. + +Do you use this library? Want to be featured? Go [here.](https://github.com/luispadron/UICircularProgressRing/issues/54) diff --git a/Pods/UICircularProgressRing/src/UICircularProgressRing/UICircularProgressRing.h b/Pods/UICircularProgressRing/src/UICircularProgressRing/UICircularProgressRing.h new file mode 100644 index 00000000..d5a60487 --- /dev/null +++ b/Pods/UICircularProgressRing/src/UICircularProgressRing/UICircularProgressRing.h @@ -0,0 +1,18 @@ +// +// UICircularProgressRing.h +// UICircularProgressRing +// +// Created by Luis Padron on 9/13/16. +// Copyright © 2016 Luis Padron. All rights reserved. +// + +#import + +//! Project version number for UICircularProgressRing. +FOUNDATION_EXPORT double UICircularProgressRingVersionNumber; + +//! Project version string for UICircularProgressRing. +FOUNDATION_EXPORT const unsigned char UICircularProgressRingVersionString[]; + + + diff --git a/Pods/UICircularProgressRing/src/UICircularProgressRing/UICircularProgressRing.swift b/Pods/UICircularProgressRing/src/UICircularProgressRing/UICircularProgressRing.swift new file mode 100644 index 00000000..6f200f78 --- /dev/null +++ b/Pods/UICircularProgressRing/src/UICircularProgressRing/UICircularProgressRing.swift @@ -0,0 +1,1268 @@ +// +// UICircularProgressRing.swift +// UICircularProgressRing +// +// Copyright (c) 2016 Luis Padron +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is furnished +// to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT +// OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +import UIKit + +/// Helper enum for animation key +private enum AnimationKeys: String { + case value +} + +/// Helper extension to allow removing layer animation based on AnimationKeys enum +fileprivate extension CALayer { + func removeAnimation(forKey key: AnimationKeys) { + removeAnimation(forKey: key.rawValue) + } + + func animation(forKey key: AnimationKeys) -> CAAnimation? { + return animation(forKey: key.rawValue) + } + + func value(forKey key: AnimationKeys) -> Any? { + return value(forKey: key.rawValue) + } +} + +/** + + # UICircularProgressRing + + This is the UIView subclass that creates and handles everything + to do with the progress ring + + This class has a custom CAShapeLayer (UICircularProgressRingLayer) which + handels the drawing and animating of the view + + The properties in this class correspond with the + properties in UICircularProgressRingLayer. + When they are set in here, they are also set for the layer and drawn accordingly + + Read the docs for what each property does and what can be customized. + + ## Author + Luis Padron + + */ +@IBDesignable open class UICircularProgressRing: UIView { + + // MARK: Delegate + /** + The delegate for the UICircularProgressRing + + ## Important ## + When progress is done updating via UICircularProgressRing.setValue(_:), the + finishedUpdatingProgressFor(_ ring: UICircularProgressRing) will be called. + + The ring will be passed to the delegate in order to keep track of + multiple ring updates if needed. + + ## Author + Luis Padron + */ + @objc open weak var delegate: UICircularProgressRingDelegate? + + // MARK: Circle Properties + + /** + Whether or not the progress ring should be a full circle. + + What this means is that the outer ring will always go from 0 - 360 degrees and + the inner ring will be calculated accordingly depending on current value. + + ## Important ## + Default = true + + When this property is true any value set for `endAngle` will be ignored. + + ## Author + Luis Padron + + */ + @IBInspectable open var fullCircle: Bool = true { + didSet { + ringLayer.fullCircle = fullCircle + } + } + + // MARK: Value Properties + + /** + The value property for the progress ring. + + ## Important ## + Default = 0 + + Must be a non-negative value. If this value falls below `minValue` it will be + clamped and set equal to `minValue`. + + This cannot be used to get the value while the ring is animating, to get + current value while animating use `currentValue`. + + The current value of the progress ring after animating, use startProgress(value:) + to alter the value with the option to animate and have a completion handler. + + ## Author + Luis Padron + */ + @IBInspectable open var value: ProgressValue = 0 { + didSet { + if value < minValue { + #if DEBUG + print("Warning in: \(#file):\(#line)") + print("Attempted to set a value less than minValue, value has been set to minValue.\n") + #endif + value = minValue + } + if value > maxValue { + #if DEBUG + print("Warning in: \(#file):\(#line)") + print("Attempted to set a value greater than maxValue, value has been set to maxValue.\n") + #endif + value = maxValue + } + ringLayer.value = value + } + } + + /** + The current value of the progress ring + + This will return the current value of the progress ring, + if the ring is animating it will be updated in real time. + If the ring is not currently animating then the value returned + will be the `value` property of the ring + + ## Author + Luis Padron + */ + open var currentValue: ProgressValue? { + if isAnimating { + return layer.presentation()?.value(forKey: .value) as? ProgressValue + } else { + return value + } + } + + /** + The minimum value for the progress ring. ex: (0) -> 100. + + ## Important ## + Default = 100 + + Must be a non-negative value, the absolute value is taken when setting this property. + + The `value` of the progress ring must NOT fall below `minValue` if it does the `value` property is clamped + and will be set equal to `value`, you will receive a warning message in the console. + + Making this value greater than + + ## Author + Luis Padron + */ + @IBInspectable open var minValue: ProgressValue = 0.0 { + didSet { + ringLayer.minValue = abs(minValue) + } + } + + /** + The maximum value for the progress ring. ex: 0 -> (100) + + ## Important ## + Default = 100 + + Must be a non-negative value, the absolute value is taken when setting this property. + + Unlike the `minValue` member `value` can extend beyond `maxValue`. What happens in this case + is the inner ring will do an extra loop through the outer ring, this is not noticible however. + + + ## Author + Luis Padron + */ + @IBInspectable open var maxValue: ProgressValue = 100.0 { + didSet { + ringLayer.maxValue = abs(maxValue) + } + } + + // MARK: View Style + + /** + Variable for the style of the progress ring. + + Range: [1,5] + + The four styles are + + - 1: Radius of the inner ring is smaller (inner ring inside outer ring) + - 2: Radius of inner ring is equal to outer ring (both at same location) + - 3: Radius of inner ring is equal to outer ring, and the outer ring is dashed + - 4: Radius of inner ring is equal to outer ring, and the outer ring is dotted + - 5: Radius of inner ring is equal to outer ring, and inner ring has gradient + + ## Important ## + THIS IS ONLY TO BE USED WITH INTERFACE BUILDER + + The reason for this is IB has no support for enumerations as of yet + + + ## Author + Luis Padron + */ + @available(*, unavailable, + message: "This property is reserved for Interface Builder, use 'ringStyle' instead") + @IBInspectable open var ibRingStyle: Int = 1 { + willSet { + let style = UICircularProgressRingStyle(rawValue: newValue) + ringStyle = style ?? .inside + } + } + + /** + The style of the progress ring. + + Type: `UICircularProgressRingStyle` + + The five styles include `inside`, `ontop`, `dashed`, `dotted`, and `gradient` + + ## Important ## + Default = UICircularProgressRingStyle.inside + + ## Author + Luis Padron + */ + @objc open var ringStyle: UICircularProgressRingStyle = .inside { + didSet { + ringLayer.ringStyle = ringStyle + if ringStyle != .bordered { + outerBorderWidth = 0 + } + } + } + + /** + Whether or not the value knob is shown + + ## Important ## + Default = false + + ## Author + Luis Padron + */ + @IBInspectable open var showsValueKnob: Bool = false { + didSet { + ringLayer.showsValueKnob = showsValueKnob + } + } + + /** + The size of the value knob (diameter) + + ## Important ## + Default = 15 + + ## Author + Luis Padron + */ + @IBInspectable open var valueKnobSize: CGFloat = 15.0 { + didSet { + ringLayer.valueKnobSize = valueKnobSize + } + } + + /** + The color of the value knob + + ## Important ## + Default = UIColor.lightGray + + ## Author + Luis Padron + */ + @IBInspectable open var valueKnobColor: UIColor = .lightGray { + didSet { + ringLayer.valueKnobColor = valueKnobColor + } + } + + /** + The blur (size) of the value knob's shadow + + ## Important ## + Default = 2 + + ## Author + Makan Houston + */ + @IBInspectable open var valueKnobShadowBlur: CGFloat = 2.0 { + didSet { + ringLayer.valueKnobShadowBlur = valueKnobShadowBlur + } + } + + /** + The offset of the value knob's shadow + + ## Important ## + Default = CGSize.zero + + ## Author + Makan Houston + */ + @IBInspectable open var valueKnobShadowOffset: CGSize = .zero { + didSet { + ringLayer.valueKnobShadowOffset = valueKnobShadowOffset + } + } + + /** + The color of the value knob's shadow + + ## Important ## + Default = UIColor.lightGray + + ## Author + Makan Houston + */ + @IBInspectable open var valueKnobShadowColor: UIColor = UIColor.black.withAlphaComponent(0.8) { + didSet { + ringLayer.valueKnobShadowColor = valueKnobShadowColor + } + } + + /** + An array of CGFloats, used to calculate the dash length for viewStyle = 3 + + ## Important ## + Default = [7.0, 7.0] + + ## Author + Luis Padron + */ + @objc open var patternForDashes: [CGFloat] = [7.0, 7.0] { + didSet { + ringLayer.patternForDashes = patternForDashes + } + } + + /** + The start angle for the entire progress ring view. + + Please note that Cocoa Touch uses a clockwise rotating unit circle. + I.e: 90 degrees is at the bottom and 270 degrees is at the top + + ## Important ## + Default = 0 (degrees) + + Values should be in degrees (they're converted to radians internally) + + ## Author + Luis Padron + */ + @IBInspectable open var startAngle: CGFloat = 0 { + didSet { + ringLayer.startAngle = startAngle + } + } + + /** + The end angle for the entire progress ring + + Please note that Cocoa Touch uses a clockwise rotating unit circle. + I.e: 90 degrees is at the bottom and 270 degrees is at the top + + ## Important ## + Default = 360 (degrees) + + Values should be in degrees (they're converted to radians internally) + + ## Author + Luis Padron + */ + @IBInspectable open var endAngle: CGFloat = 360 { + didSet { + ringLayer.endAngle = endAngle + } + } + + /** + The colors which will be used to create the gradient. + + Only used when `ringStyle` is `.gradient` + + The colors should be in the order they will be drawn in. + + ## Important ## + By default this property will be an empty array. + + If this array is empty, no gradient will be drawn. + + ## Author + Luis Padron + */ + @objc open var gradientColors: [UIColor] = [UIColor]() { + didSet { + ringLayer.gradientColors = gradientColors + } + } + + /** + The location for each color provided in `gradientColors`; each location must be + a CGFloat value in the range of 0 to 1, inclusive. If 0 and 1 are not in the + locations array, Quartz uses the colors provided that are closest to 0 and 1 for + those locations. + + If locations is nil, the first color in `gradientColors` is assigned to location 0, + the last color in `gradientColors` is assigned to location 1, and intervening + colors are assigned locations that are at equal intervals in between. + + The locations array should contain the same number of items as the `gradientColors` + array. + + ## Important ## + By default this property will be nil + + ## Author + Luis Padron + */ + @objc open var gradientColorLocations: [CGFloat]? = nil { + didSet { + ringLayer.gradientColorLocations = gradientColorLocations + } + } + + /** + The start location for the gradient. + This property determines where the gradient will begin to draw, + for all possible values see `UICircularProgressRingGradientPosition`. + + ## Important ## + By default this property is `.topRight` + + ## Author + Luis Padron + */ + @objc open var gradientStartPosition: UICircularProgressRingGradientPosition = .topRight { + didSet { + ringLayer.gradientStartPosition = gradientStartPosition + } + } + + /** + The end location for the gradient. + This property determines where the gradient will end drawing, + for all possible values see `UICircularProgressRingGradientPosition`. + + ## Important ## + By default this property is `.bottomLeft` + + ## Author + Luis Padron + */ + @objc open var gradientEndPosition: UICircularProgressRingGradientPosition = .bottomLeft { + didSet { + ringLayer.gradientEndPosition = gradientEndPosition + } + } + + // MARK: Outer Ring properties + + /** + The width of the outer ring for the progres bar + + ## Important ## + Default = 10.0 + + ## Author + Luis Padron + */ + @IBInspectable open var outerRingWidth: CGFloat = 10.0 { + didSet { + ringLayer.outerRingWidth = outerRingWidth + } + } + + /** + The color for the outer ring + + ## Important ## + Default = UIColor.gray + + ## Author + Luis Padron + */ + @IBInspectable open var outerRingColor: UIColor = UIColor.gray { + didSet { + ringLayer.outerRingColor = outerRingColor + } + } + + /** + The color for the outer ring border + + ## Important ## + Default = UIColor.gray + + ## Author + Abdulla Allaith + */ + @IBInspectable open var outerBorderColor: UIColor = UIColor.gray { + didSet { + ringLayer.outerBorderColor = outerBorderColor + } + } + + /** + The width for the outer ring border + + ## Important ## + Default = 2 + + ## Author + Abdulla Allaith + */ + @IBInspectable open var outerBorderWidth: CGFloat = 2 { + didSet { + ringLayer.outerBorderWidth = outerBorderWidth + } + } + + /** + The style for the outer ring end cap (how it is drawn on screen) + Range [1,3] + - 1: Line with a squared off end + - 2: Line with a rounded off end + - 3: Line with a square end + - <1 & >3: Defaults to style 1 + + ## Important ## + THIS IS ONLY TO BE USED WITH INTERFACE BUILDER + + Default = 1 + + ## Author + Luis Padron + */ + @available(*, unavailable, + message: "This property is reserved for Interface Builder, use 'outerCapStyle' instead") + @IBInspectable open var outerRingCapStyle: Int32 = 1 { + willSet { + switch newValue { + case 1: + outerCapStyle = .butt + case 2: + outerCapStyle = .round + case 3: + outerCapStyle = .square + default: + outerCapStyle = .butt + } + } + } + + /** + The style for the tip/cap of the outer ring + + Type: `CGLineCap` + + ## Important ## + Default = CGLineCap.butt + + This is only noticible when ring is not a full circle. + + ## Author + Luis Padron + */ + @objc open var outerCapStyle: CGLineCap = .butt { + didSet { + ringLayer.outerCapStyle = outerCapStyle + } + } + + // MARK: Inner Ring properties + + /** + The width of the inner ring for the progres bar + + ## Important ## + Default = 5.0 + + ## Author + Luis Padron + */ + @IBInspectable open var innerRingWidth: CGFloat = 5.0 { + didSet { + ringLayer.innerRingWidth = innerRingWidth + } + } + + /** + The color of the inner ring for the progres bar + + ## Important ## + Default = UIColor.blue + + ## Author + Luis Padron + */ + @IBInspectable open var innerRingColor: UIColor = UIColor.blue { + didSet { + ringLayer.innerRingColor = innerRingColor + } + } + + /** + The spacing between the outer ring and inner ring + + ## Important ## + This only applies when using progressRingStyle = 1 + + Default = 1 + + ## Author + Luis Padron + */ + @IBInspectable open var innerRingSpacing: CGFloat = 1 { + didSet { + ringLayer.innerRingSpacing = innerRingSpacing + } + } + + /** + The style for the inner ring end cap (how it is drawn on screen) + + Range [1,3] + + - 1: Line with a squared off end + - 2: Line with a rounded off end + - 3: Line with a square end + - <1 & >3: Defaults to style 2 + + ## Important ## + THIS IS ONLY TO BE USED WITH INTERFACE BUILDER + + Default = 2 + + ## Author + Luis Padron + */ + @available(*, unavailable, + message: "This property is reserved for Interface Builder, use 'innerCapStyle' instead") + @IBInspectable open var innerRingCapStyle: Int32 = 2 { + willSet { + switch newValue { + case 1: + innerCapStyle = .butt + case 2: + innerCapStyle = .round + case 3: + innerCapStyle = .square + default: + innerCapStyle = .round + } + } + } + + /** + The style for the tip/cap of the inner ring + + Type: `CGLineCap` + + ## Important ## + Default = CGLineCap.round + + ## Author + Luis Padron + */ + @objc open var innerCapStyle: CGLineCap = .round { + didSet { + ringLayer.innerCapStyle = innerCapStyle + } + } + + // MARK: Label + + /** + A toggle for showing or hiding the value label. + If false the current value will not be shown. + + ## Important ## + Default = true + + ## Author + Luis Padron + */ + @IBInspectable open var shouldShowValueText: Bool = true { + didSet { + ringLayer.shouldShowValueText = shouldShowValueText + } + } + + /** + The text color for the value label field + + ## Important ## + Default = UIColor.black + + + ## Author + Luis Padron + */ + @IBInspectable open var fontColor: UIColor = UIColor.black { + didSet { + ringLayer.fontColor = fontColor + } + } + + /** + The font to be used for the progress indicator. + All font attributes are specified here except for font color, which is done + using `fontColor`. + + + ## Important ## + Default = UIFont.systemFont(ofSize: 18) + + + ## Author + Luis Padron + */ + @IBInspectable open var font: UIFont = UIFont.systemFont(ofSize: 18) { + didSet { + ringLayer.font = font + } + } + + /** + The name of the value indicator the value label will + appened to the value + Example: " GB" -> "100 GB" + + ## Important ## + Default = "%" + + ## Author + Luis Padron + */ + @IBInspectable open var valueIndicator: String = "%" { + didSet { + ringLayer.valueIndicator = valueIndicator + } + } + + /** + A toggle for either placing the value indicator right or left to the value + Example: true -> "GB 100" (instead of 100 GB) + + ## Important ## + Default = false (place value indicator to the right) + + ## Author + Elad Hayun + */ + @IBInspectable open var rightToLeft: Bool = false { + didSet { + ringLayer.rightToLeft = rightToLeft + } + } + + /** + A toggle for showing or hiding floating points from + the value in the value label + + ## Important ## + Default = false (dont show) + + To customize number of decmial places to show, assign a value to decimalPlaces. + + ## Author + Luis Padron + */ + @IBInspectable open var showFloatingPoint: Bool = false { + didSet { + ringLayer.showFloatingPoint = showFloatingPoint + } + } + + /** + The amount of decimal places to show in the value label + + ## Important ## + Default = 2 + + Only used when showFloatingPoint = true + + ## Author + Luis Padron + */ + @IBInspectable open var decimalPlaces: Int = 2 { + didSet { + ringLayer.decimalPlaces = decimalPlaces + } + } + + // MARK: Animation properties + + /** + The type of animation function the ring view will use + + ## Important ## + Default = .easeInEaseOut + + ## Author + Luis Padron + */ + @objc open var animationTimingFunction: CAMediaTimingFunctionName = .easeInEaseOut { + didSet { + ringLayer.animationTimingFunction = animationTimingFunction + } + } + + /** + This returns whether or not the ring is currently animating + + ## Important ## + Get only property + + ## Author + Luis Padron + */ + @objc open var isAnimating: Bool { + return completionTimer?.isValid ?? false + } + + /** + The direction the circle is drawn in + Example: true -> clockwise + + ## Important ## + Default = true (draw the circle clockwise) + + ## Author + Pete Walker + */ + @IBInspectable open var isClockwise: Bool = true { + didSet { + ringLayer.isClockwise = isClockwise + } + } + + /// This stores the animation when the timer is paused. We use this variable to continue the animation where it left off. + /// See https://stackoverflow.com/questions/7568567/restoring-animation-where-it-left-off-when-app-resumes-from-background + private var snapshottedAnimation: CAAnimation? + + /// This variable stores how long remains on the timer when it's paused + private var pausedTimeRemaining: TimeInterval = 0 + + /// Used to determine when the animation was paused + private var animationPauseTime: CFTimeInterval? + + /// The completion timer, also indicates wether or not the view is animating + private var completionTimer: Timer? + + /// The completion block to call after the animation is done + private var completion: ProgressCompletion? + + // MARK: Layer + + /** + Set the ring layer to the default layer, cated as custom layer + */ + internal var ringLayer: UICircularProgressRingLayer { + // swiftlint:disable:next force_cast + return layer as! UICircularProgressRingLayer + } + + /** + Overrides the default layer with the custom UICircularProgressRingLayer class + */ + override open class var layerClass: AnyClass { + return UICircularProgressRingLayer.self + } + + // MARK: Type aliases + + /** + Typealias for the startProgress(:) method closure + */ + public typealias ProgressCompletion = (() -> Void) + + /** + Typealias for animateProperties(duration:animations:completion:) fucntion completion + */ + public typealias PropertyAnimationCompletion = (() -> Void) + + /** + Typealias for the value of the ring + */ + public typealias ProgressValue = CGFloat + + /** + Typealias for the duration of a ring animation + */ + public typealias ProgressDuration = TimeInterval + + // MARK: Methods + + /** + Overriden public init to initialize the layer and view + */ + override public init(frame: CGRect) { + super.init(frame: frame) + // Call the internal initializer + initialize() + } + + /** + Overriden public init to initialize the layer and view + */ + required public init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + // Call the internal initializer + initialize() + } + + /** + This method initializes the custom CALayer to the default values + */ + // swiftlint:disable:next function_body_length + private func initialize() { + // This view will become the value delegate of the layer, which will call the updateValue method when needed + ringLayer.valueDelegate = self + + // Helps with pixelation and blurriness on retina devices + layer.contentsScale = UIScreen.main.scale + layer.shouldRasterize = true + layer.rasterizationScale = UIScreen.main.scale * 2 + layer.masksToBounds = false + + ringLayer.fullCircle = fullCircle + ringLayer.isClockwise = isClockwise + + ringLayer.value = value + ringLayer.maxValue = maxValue + ringLayer.minValue = minValue + + ringLayer.ringStyle = ringStyle + ringLayer.showsValueKnob = showsValueKnob + ringLayer.valueKnobSize = valueKnobSize + ringLayer.valueKnobColor = valueKnobColor + ringLayer.valueKnobShadowBlur = valueKnobShadowBlur + ringLayer.valueKnobShadowOffset = valueKnobShadowOffset + ringLayer.valueKnobShadowColor = valueKnobShadowColor + ringLayer.patternForDashes = patternForDashes + ringLayer.gradientColors = gradientColors + ringLayer.gradientColorLocations = gradientColorLocations + ringLayer.gradientStartPosition = gradientStartPosition + ringLayer.gradientEndPosition = gradientEndPosition + + ringLayer.startAngle = startAngle + ringLayer.endAngle = endAngle + + ringLayer.outerRingWidth = outerRingWidth + ringLayer.outerRingColor = outerRingColor + ringLayer.outerBorderWidth = outerBorderWidth + ringLayer.outerBorderColor = outerBorderColor + ringLayer.outerCapStyle = outerCapStyle + + ringLayer.innerRingWidth = innerRingWidth + ringLayer.innerRingColor = innerRingColor + ringLayer.innerCapStyle = innerCapStyle + ringLayer.innerRingSpacing = innerRingSpacing + + ringLayer.shouldShowValueText = shouldShowValueText + ringLayer.valueIndicator = valueIndicator + ringLayer.fontColor = fontColor + ringLayer.font = font + ringLayer.showFloatingPoint = showFloatingPoint + ringLayer.decimalPlaces = decimalPlaces + + backgroundColor = UIColor.clear + ringLayer.backgroundColor = UIColor.clear.cgColor + + NotificationCenter.default.addObserver(self, + selector: #selector(restoreProgress), + name: UIApplication.willEnterForegroundNotification, + object: nil) + + NotificationCenter.default.addObserver(self, + selector: #selector(snapshotProgress), + name: UIApplication.willResignActiveNotification, + object: nil) + } + + /** + Overriden because of custom layer drawing in UICircularProgressRingLayer + */ + open override func draw(_ rect: CGRect) { + super.draw(rect) + } + + /** + Called whenever the layer updates its `value` keypath, this method will then simply call its delegate with + the `newValue` so that it notifies any delegates who may need to know about value updates in real time + */ + internal func didUpdateValue(newValue: ProgressValue) { + delegate?.didUpdateProgressValue?(for: self, to: newValue) + } + + internal func willDisplayLabel(label: UILabel) { + delegate?.willDisplayLabel?(for: self, label) + } + + // MARK: API + + /** + Sets the current value for the progress ring, calling this method while ring is + animating will cancel the previously set animation and start a new one. + + - Parameter to: The value to be set for the progress ring + - Parameter duration: The time interval duration for the animation + - Parameter completion: The completion closure block that will be called when + animtion is finished (also called when animationDuration = 0), default is nil + + ## Important ## + Animation duration = 0 will cause no animation to occur, and value will instantly + be set. + + Calling this method again while a current progress animation is in progress will **not** + cause the animation to be restarted. The old animation will be removed (calling the completion and delegate) + and a new animation will start from where the old one left off at. If you wish to instead reset an animation + consider `resetProgress`. + + ## Author + Luis Padron + */ + @objc open func startProgress(to value: ProgressValue, duration: ProgressDuration, completion: ProgressCompletion? = nil) { + if isAnimating { + animationPauseTime = nil + self.value = currentValue ?? value + ringLayer.removeAnimation(forKey: .value) + } + + ringLayer.timeOffset = 0.0 + ringLayer.beginTime = 0.0 + ringLayer.speed = 1.0 + ringLayer.animated = duration > 0 + ringLayer.animationDuration = duration + + // Store the completion event locally + self.completion = completion + + // Check if a completion timer is still active and if so stop it + completionTimer?.invalidate() + completionTimer = nil + + //Create a new completion timer + completionTimer = Timer.scheduledTimer(timeInterval: duration, + target: self, + selector: #selector(self.animationDidComplete), + userInfo: completion, + repeats: false) + + self.value = value + } + + /** + Pauses the currently running animation and halts all progress. + + ## Important ## + This method has no effect unless called when there is a running animation. + You should call this method manually whenever the progress ring is not in an active view, + for example in `viewWillDisappear` in a parent view controller. + + ## Author + Luis Padron & Nicolai Cornelis + */ + @objc open func pauseProgress() { + guard isAnimating else { + #if DEBUG + print(""" + UICircularProgressRing: Progress was paused without having been started. + This has no effect but may indicate that you're unnecessarily calling this method. + """) + #endif + return + } + + snapshotProgress() + + let pauseTime = ringLayer.convertTime(CACurrentMediaTime(), from: nil) + animationPauseTime = pauseTime + + ringLayer.speed = 0.0 + ringLayer.timeOffset = pauseTime + + if let fireTime = completionTimer?.fireDate { + pausedTimeRemaining = fireTime.timeIntervalSince(Date()) + } else { + pausedTimeRemaining = 0 + } + + completionTimer?.invalidate() + completionTimer = nil + + delegate?.didPauseProgress?(for: self) + } + + /** + Continues the animation with its remaining time from where it left off before it was paused. + This method has no effect unless called when there is a paused animation. + You should call this method when you wish to resume a paused animation. + + ## Author + Luis Padron & Nicolai Cornelis + */ + @objc open func continueProgress() { + guard let pauseTime = animationPauseTime else { + #if DEBUG + print(""" + UICircularProgressRing: Progress was continued without having been paused. + This has no effect but may indicate that you're unnecessarily calling this method. + """) + #endif + return + } + + restoreProgress() + + ringLayer.speed = 1.0 + ringLayer.timeOffset = 0.0 + ringLayer.beginTime = 0.0 + + let timeSincePause = ringLayer.convertTime(CACurrentMediaTime(), from: nil) - pauseTime + + ringLayer.beginTime = timeSincePause + + completionTimer = Timer.scheduledTimer(timeInterval: pausedTimeRemaining, + target: self, + selector: #selector(animationDidComplete), + userInfo: completion, + repeats: false) + + animationPauseTime = nil + + delegate?.didContinueProgress?(for: self) + } + + /** + Resets the progress back to the `minValue` of the progress ring. + Does **not** perform any animations + + ## Author + Luis Padron + */ + @objc open func resetProgress() { + ringLayer.animated = false + ringLayer.removeAnimation(forKey: .value) + snapshottedAnimation = nil + value = minValue + + // Stop the timer and thus make the completion method not get fired + completionTimer?.invalidate() + completionTimer = nil + animationPauseTime = nil + + // Remove reference to the completion block + completion = nil + } + + /** + This function allows animation of the animatable properties of the `UICircularProgressRing`. + These properties include `innerRingColor, innerRingWidth, outerRingColor, outerRingWidth, innerRingSpacing, fontColor`. + + Simply call this function and inside of the animation block change the animatable properties as you would in any `UView` + animation block. + + The completion block is called when all animations finish. + */ + @objc open func animateProperties(duration: TimeInterval, animations: () -> Void) { + animateProperties(duration: duration, animations: animations, completion: nil) + } + + /** + This function allows animation of the animatable properties of the `UICircularProgressRing`. + These properties include `innerRingColor, innerRingWidth, outerRingColor, outerRingWidth, innerRingSpacing, fontColor`. + + Simply call this function and inside of the animation block change the animatable properties as you would in any `UView` + animation block. + + The completion block is called when all animations finish. + */ + @objc open func animateProperties(duration: TimeInterval, animations: () -> Void, + completion: PropertyAnimationCompletion? = nil) { + ringLayer.shouldAnimateProperties = true + ringLayer.propertyAnimationDuration = duration + CATransaction.begin() + CATransaction.setCompletionBlock { + // Reset and call completion + self.ringLayer.shouldAnimateProperties = false + self.ringLayer.propertyAnimationDuration = 0.0 + completion?() + } + // Commit and perform animations + animations() + CATransaction.commit() + } +} + +// MARK: Helpers methods + +extension UICircularProgressRing { + /// Called when the animation timer is complete + @objc private func animationDidComplete(withTimer timer: Timer) { + delegate?.didFinishProgress?(for: self) + (timer.userInfo as? ProgressCompletion)?() + } + + /** + This method is called when the application goes into the background or when the + ProgressRing is paused using the pauseProgress method. + This is necessary for the animation to properly pick up where it left off. + Triggered by UIApplicationWillResignActive. + + ## Author + Nicolai Cornelis + */ + @objc private func snapshotProgress() { + guard let animation = ringLayer.animation(forKey: .value) else { return } + snapshottedAnimation = animation + } + + /** + This method is called when the application comes back into the foreground or + when the ProgressRing is resumed using the continueProgress method. + This is necessary for the animation to properly pick up where it left off. + Triggered by UIApplicationWillEnterForeground. + + ## Author + Nicolai Cornelis + */ + @objc private func restoreProgress() { + guard let animation = snapshottedAnimation else { return } + ringLayer.add(animation, forKey: AnimationKeys.value.rawValue) + } +} diff --git a/Pods/UICircularProgressRing/src/UICircularProgressRing/UICircularProgressRingDelegate.swift b/Pods/UICircularProgressRing/src/UICircularProgressRing/UICircularProgressRingDelegate.swift new file mode 100644 index 00000000..b7f93690 --- /dev/null +++ b/Pods/UICircularProgressRing/src/UICircularProgressRing/UICircularProgressRingDelegate.swift @@ -0,0 +1,92 @@ +// +// UICircularProgressRingDelegate.swift +// UICircularProgressRing +// +// Copyright (c) 2016 Luis Padron +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is furnished +// to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT +// OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +import UIKit + +/** + This is the protocol declaration for the UICircularProgressRing delegate property + + ## Important ## + When progress is done updating via UICircularProgressRing.setValue(_:), the + finishedUpdatingProgress(forRing: UICircularProgressRing) will be called. + + The ring will be passed to the delegate in order to keep + track of multiple ring updates if needed. + + ## Author + Luis Padron + */ +@objc public protocol UICircularProgressRingDelegate: class { + /** + Called when progress ring is done animating for current value + + - Paramater + - ring: The ring which finished animating + + */ + @objc optional func didFinishProgress(for ring: UICircularProgressRing) + + /** + Called when progress has paused + + - Parameter: + - ring: The ring which has paused + */ + @objc optional func didPauseProgress(for ring: UICircularProgressRing) + + /** + Called when the progress has continued after a pause + + - Parameter: + - ring: The ring which has continued + */ + @objc optional func didContinueProgress(for ring: UICircularProgressRing) + + /** + This method is called whenever the value is updated, this means during animation this method will be called in real time. + This can be used to update another label or do some other work, whenever you need the exact current value of the ring + during animation. + + ## Important: + + This is a very hot method and may be called hundreds of times per second during animations. As such make sure to only + do very simple and non-intensive work in this method. Doing any work that takes time will considerably slow down your application. + + - Paramater + - ring: The ring which updated the progress + - newValue: The value which the ring has updated to + */ + @objc optional func didUpdateProgressValue(for ring: UICircularProgressRing, to newValue: UICircularProgressRing.ProgressValue) + + /** + This method is called whenever the label is about to be drawn. + This can be used to modify the label looks e.g. NSAttributedString for text kerning + + - Paramater + - ring: The ring which the label will be displayed in + - label: The label which will be displayed + */ + @objc optional func willDisplayLabel(for ring: UICircularProgressRing, _ label: UILabel) +} diff --git a/Pods/UICircularProgressRing/src/UICircularProgressRing/UICircularProgressRingGradientPosition.swift b/Pods/UICircularProgressRing/src/UICircularProgressRing/UICircularProgressRingGradientPosition.swift new file mode 100644 index 00000000..11e736d9 --- /dev/null +++ b/Pods/UICircularProgressRing/src/UICircularProgressRing/UICircularProgressRingGradientPosition.swift @@ -0,0 +1,82 @@ +// +// UICircularProgressRingGradientPosition.swift +// UICircularProgressRing +// +// Copyright (c) 2016 Luis Padron +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is furnished +// to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT +// OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +/** + + # UICircularProgressRingGradientPosition + + This is an enumeration which is used to determine the position for a + gradient. Used inside the `UICircularProgressRingLayer` to allow customization + for the gradient. + + ## Author + Luis Padron + + */ +@objc public enum UICircularProgressRingGradientPosition: Int { + /// Gradient positioned at the top + case top = 1 + /// Gradient positioned at the bottom + case bottom = 2 + /// Gradient positioned to the left + case left = 3 + /// Gradient positioned to the right + case right = 4 + /// Gradient positioned in the top left corner + case topLeft = 5 + /// Gradient positioned in the top right corner + case topRight = 6 + /// Gradient positioned in the bottom left corner + case bottomLeft = 7 + /// Gradient positioned in the bottom right corner + case bottomRight = 8 + + /** + + Returns a `CGPoint` in the coordinates space of the passed in `CGRect` + for the specified position of the gradient. + + */ + func pointForPosition(in rect: CGRect) -> CGPoint { + switch self { + case .top: + return CGPoint(x: rect.midX, y: rect.minY) + case .bottom: + return CGPoint(x: rect.midX, y: rect.maxY) + case .left: + return CGPoint(x: rect.minX, y: rect.midY) + case .right: + return CGPoint(x: rect.maxX, y: rect.midY) + case .topLeft: + return CGPoint(x: rect.minX, y: rect.minY) + case .topRight: + return CGPoint(x: rect.maxX, y: rect.minY) + case .bottomLeft: + return CGPoint(x: rect.minX, y: rect.maxY) + case .bottomRight: + return CGPoint(x: rect.maxX, y: rect.maxY) + } + } +} diff --git a/Pods/UICircularProgressRing/src/UICircularProgressRing/UICircularProgressRingLayer.swift b/Pods/UICircularProgressRing/src/UICircularProgressRing/UICircularProgressRingLayer.swift new file mode 100644 index 00000000..11e10b9c --- /dev/null +++ b/Pods/UICircularProgressRing/src/UICircularProgressRing/UICircularProgressRingLayer.swift @@ -0,0 +1,432 @@ +// +// UICircularProgressRingLayer.swift +// UICircularProgressRing +// +// Copyright (c) 2016 Luis Padron +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is furnished +// to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT +// OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +import UIKit + +/** + A private extension to CGFloat in order to provide simple + conversion from degrees to radians, used when drawing the rings. + */ +private extension CGFloat { + var toRads: CGFloat { return self * CGFloat.pi / 180 } +} + +/** + A private extension to UILabel, in order to cut down on code repeation. + This function will update the value of the progress label, depending on the + parameters sent. + At the end sizeToFit() is called in order to ensure text gets drawn correctly + */ +private extension UILabel { + // swiftlint:disable function_parameter_count next_line + func update(withValue value: CGFloat, valueIndicator: String, rightToLeft: Bool, + showsDecimal: Bool, decimalPlaces: Int, valueDelegate: UICircularProgressRing?) { + if rightToLeft { + if showsDecimal { + text = "\(valueIndicator)" + String(format: "%.\(decimalPlaces)f", value) + } else { + text = "\(valueIndicator)\(Int(value))" + } + + } else { + if showsDecimal { + text = String(format: "%.\(decimalPlaces)f", value) + "\(valueIndicator)" + } else { + text = "\(Int(value))\(valueIndicator)" + } + } + valueDelegate?.willDisplayLabel(label: self) + sizeToFit() + } +} + +/** + The internal subclass for CAShapeLayer. + This is the class that handles all the drawing and animation. + This class is not interacted with, instead + properties are set in UICircularProgressRing and those are delegated to here. + + */ +class UICircularProgressRingLayer: CAShapeLayer { + + // MARK: Properties + + /** + The NSManaged properties for the layer. + These properties are initialized in UICircularProgressRing. + They're also assigned by mutating UICircularProgressRing properties. + */ + @NSManaged var fullCircle: Bool + + @NSManaged var value: CGFloat + @NSManaged var minValue: CGFloat + @NSManaged var maxValue: CGFloat + + @NSManaged var ringStyle: UICircularProgressRingStyle + @NSManaged var showsValueKnob: Bool + @NSManaged var valueKnobSize: CGFloat + @NSManaged var valueKnobColor: UIColor + @NSManaged var valueKnobShadowBlur: CGFloat + @NSManaged var valueKnobShadowOffset: CGSize + @NSManaged var valueKnobShadowColor: UIColor + @NSManaged var patternForDashes: [CGFloat] + + @NSManaged var gradientColors: [UIColor] + @NSManaged var gradientColorLocations: [CGFloat]? + @NSManaged var gradientStartPosition: UICircularProgressRingGradientPosition + @NSManaged var gradientEndPosition: UICircularProgressRingGradientPosition + + @NSManaged var startAngle: CGFloat + @NSManaged var endAngle: CGFloat + + @NSManaged var outerRingWidth: CGFloat + @NSManaged var outerRingColor: UIColor + @NSManaged var outerCapStyle: CGLineCap + @NSManaged var outerBorderColor: UIColor + @NSManaged var outerBorderWidth: CGFloat + + @NSManaged var innerRingWidth: CGFloat + @NSManaged var innerRingColor: UIColor + @NSManaged var innerCapStyle: CGLineCap + @NSManaged var innerRingSpacing: CGFloat + + @NSManaged var shouldShowValueText: Bool + @NSManaged var fontColor: UIColor + @NSManaged var font: UIFont + @NSManaged var valueIndicator: String + @NSManaged var rightToLeft: Bool + @NSManaged var showFloatingPoint: Bool + @NSManaged var decimalPlaces: Int + @NSManaged var isClockwise: Bool + + var animationDuration: TimeInterval = 1.0 + var animationTimingFunction: CAMediaTimingFunctionName = .easeInEaseOut + var animated = false + @NSManaged weak var valueDelegate: UICircularProgressRing? + + // The value label which draws the text for the current value + lazy private var valueLabel: UILabel = UILabel(frame: .zero) + + // MARK: Animatable properties + + // Whether or not animatable properties should be animated when changed + internal var shouldAnimateProperties: Bool = false + + // The animation duration for a animatable property animation + internal var propertyAnimationDuration: TimeInterval = 0.0 + + // The properties which are animatable + private static let animatableProperties: [String] = ["innerRingWidth", "innerRingColor", + "outerRingWidth", "outerRingColor", + "fontColor", "innerRingSpacing"] + + // Returns whether or not a given property key is animatable + private static func isAnimatableProperty(_ key: String) -> Bool { + return animatableProperties.index(of: key) != nil + } + + // MARK: Draw + + /** + Overriden for custom drawing. + Draws the outer ring, inner ring and value label. + */ + override func draw(in ctx: CGContext) { + super.draw(in: ctx) + UIGraphicsPushContext(ctx) + // Draw the rings + drawOuterRing() + drawInnerRing(in: ctx) + // Draw the label + drawValueLabel() + // Call the delegate and notifiy of updated value + if let updatedValue = value(forKey: "value") as? CGFloat { + valueDelegate?.didUpdateValue(newValue: updatedValue) + } + UIGraphicsPopContext() + + } + + // MARK: Animation methods + + /** + Watches for changes in the value property, and setNeedsDisplay accordingly + */ + override class func needsDisplay(forKey key: String) -> Bool { + if key == "value" || isAnimatableProperty(key) { + return true + } else { + return super.needsDisplay(forKey: key) + } + } + + /** + Creates animation when value property is changed + */ + override func action(forKey event: String) -> CAAction? { + if event == "value" && animated { + let animation = CABasicAnimation(keyPath: "value") + animation.fromValue = presentation()?.value(forKey: "value") + animation.timingFunction = CAMediaTimingFunction(name: animationTimingFunction) + animation.duration = animationDuration + return animation + } else if UICircularProgressRingLayer.isAnimatableProperty(event) && shouldAnimateProperties { + let animation = CABasicAnimation(keyPath: event) + animation.fromValue = presentation()?.value(forKey: event) + animation.timingFunction = CAMediaTimingFunction(name: animationTimingFunction) + animation.duration = propertyAnimationDuration + return animation + } else { + return super.action(forKey: event) + } + } + + // MARK: Helpers + + /** + Draws the outer ring for the view. + Sets path properties according to how the user has decided to customize the view. + */ + private func drawOuterRing() { + guard outerRingWidth > 0 else { return } + let center: CGPoint = CGPoint(x: bounds.midX, y: bounds.midY) + let offSet = max(outerRingWidth, innerRingWidth) / 2 + (showsValueKnob ? valueKnobSize / 4 : 0) + (outerBorderWidth*2) + let outerRadius: CGFloat = min(bounds.width, bounds.height) / 2 - offSet + let start: CGFloat = fullCircle ? 0 : startAngle.toRads + let end: CGFloat = fullCircle ? .pi * 2 : endAngle.toRads + let outerPath = UIBezierPath(arcCenter: center, + radius: outerRadius, + startAngle: start, + endAngle: end, + clockwise: true) + outerPath.lineWidth = outerRingWidth + outerPath.lineCapStyle = outerCapStyle + // Update path depending on style of the ring + updateOuterRingPath(outerPath, radius: outerRadius, style: ringStyle) + + outerRingColor.setStroke() + outerPath.stroke() + } + + /** + Draws the inner ring for the view. + Sets path properties according to how the user has decided to customize the view. + */ + private func drawInnerRing(in ctx: CGContext) { + guard innerRingWidth > 0 else { return } + + let center: CGPoint = CGPoint(x: bounds.midX, y: bounds.midY) + + let innerEndAngle = calculateInnerEndAngle() + let radiusIn = calculateInnerRadius() + + // Start drawing + let innerPath: UIBezierPath = UIBezierPath(arcCenter: center, + radius: radiusIn, + startAngle: startAngle.toRads, + endAngle: innerEndAngle.toRads, + clockwise: isClockwise) + + // Draw path + ctx.setLineWidth(innerRingWidth) + ctx.setLineJoin(.round) + ctx.setLineCap(innerCapStyle) + ctx.setStrokeColor(innerRingColor.cgColor) + ctx.addPath(innerPath.cgPath) + ctx.drawPath(using: .stroke) + + if ringStyle == .gradient && gradientColors.count > 1 { + // Create gradient and draw it + var cgColors: [CGColor] = [CGColor]() + for color: UIColor in gradientColors { + cgColors.append(color.cgColor) + } + + guard let gradient: CGGradient = CGGradient(colorsSpace: nil, + colors: cgColors as CFArray, + locations: gradientColorLocations) + else { + fatalError("\nUnable to create gradient for progress ring.\n" + + "Check values of gradientColors and gradientLocations.\n") + } + + ctx.saveGState() + ctx.addPath(innerPath.cgPath) + ctx.replacePathWithStrokedPath() + ctx.clip() + + drawGradient(gradient, start: gradientStartPosition, + end: gradientEndPosition, in: ctx) + + ctx.restoreGState() + } + + if showsValueKnob && value > minValue { + let knobOffset = valueKnobSize / 2 + drawValueKnob(in: ctx, origin: CGPoint(x: innerPath.currentPoint.x - knobOffset, + y: innerPath.currentPoint.y - knobOffset)) + } + } + + /// Updates the outer ring path depending on the ring's style + private func updateOuterRingPath(_ path: UIBezierPath, radius: CGFloat, style: UICircularProgressRingStyle) { + switch style { + case .dashed: + path.setLineDash(patternForDashes, count: patternForDashes.count, phase: 0.0) + + case .dotted: + path.setLineDash([0, path.lineWidth * 2], count: 2, phase: 0) + path.lineCapStyle = .round + + case .bordered: + let center: CGPoint = CGPoint(x: bounds.midX, y: bounds.midY) + let offSet = max(outerRingWidth, innerRingWidth) / 2 + (showsValueKnob ? valueKnobSize / 4 : 0) + (outerBorderWidth*2) + let outerRadius: CGFloat = min(bounds.width, bounds.height) / 2 - offSet + let borderStartAngle = outerCapStyle == .butt ? startAngle-outerBorderWidth : startAngle + let borderEndAngle = outerCapStyle == .butt ? endAngle+outerBorderWidth : endAngle + let start: CGFloat = fullCircle ? 0 : borderStartAngle.toRads + let end: CGFloat = fullCircle ? .pi * 2 : borderEndAngle.toRads + let borderPath = UIBezierPath(arcCenter: center, + radius: outerRadius, + startAngle: start, + endAngle: end, + clockwise: true) + UIColor.clear.setFill() + borderPath.fill() + borderPath.lineWidth = (outerBorderWidth*2) + outerRingWidth + borderPath.lineCapStyle = outerCapStyle + outerBorderColor.setStroke() + borderPath.stroke() + default: + break + } + } + + /// Returns the end angle of the inner ring + private func calculateInnerEndAngle() -> CGFloat { + let innerEndAngle: CGFloat + + if fullCircle { + if !isClockwise { + innerEndAngle = startAngle - ((value - minValue) / (maxValue - minValue) * 360.0) + } else { + innerEndAngle = (value - minValue) / (maxValue - minValue) * 360.0 + startAngle + } + } else { + // Calculate the center difference between the end and start angle + let angleDiff: CGFloat = (startAngle > endAngle) ? (360.0 - startAngle + endAngle) : (endAngle - startAngle) + // Calculate how much we should draw depending on the value set + if !isClockwise { + innerEndAngle = startAngle - ((value - minValue) / (maxValue - minValue) * angleDiff) + } else { + innerEndAngle = (value - minValue) / (maxValue - minValue) * angleDiff + startAngle + } + } + + return innerEndAngle + } + + /// Returns the raidus of the inner ring + private func calculateInnerRadius() -> CGFloat { + // The radius for style 1 is set below + // The radius for style 1 is a bit less than the outer, + // this way it looks like its inside the circle + let radiusIn: CGFloat + + switch ringStyle { + case .inside: + let difference = outerRingWidth * 2 + innerRingSpacing + (showsValueKnob ? valueKnobSize / 2 : 0) + let offSet = innerRingWidth / 2 + (showsValueKnob ? valueKnobSize / 2 : 0) + radiusIn = (min(bounds.width - difference, bounds.height - difference) / 2) - offSet + case .bordered: + let offSet = (max(outerRingWidth, innerRingWidth) / 2) + (showsValueKnob ? valueKnobSize / 4 : 0) + (outerBorderWidth*2) + radiusIn = (min(bounds.width, bounds.height) / 2) - offSet + default: + let offSet = (max(outerRingWidth, innerRingWidth) / 2) + (showsValueKnob ? valueKnobSize / 4 : 0) + radiusIn = (min(bounds.width, bounds.height) / 2) - offSet + } + + return radiusIn + } + + /** + Draws a gradient with a start and end position inside the provided context + */ + private func drawGradient(_ gradient: CGGradient, + start: UICircularProgressRingGradientPosition, + end: UICircularProgressRingGradientPosition, + in context: CGContext) { + + context.drawLinearGradient(gradient, + start: start.pointForPosition(in: bounds), + end: end.pointForPosition(in: bounds), + options: .drawsBeforeStartLocation) + } + + /** + Draws the value knob inside the provided context + */ + private func drawValueKnob(in context: CGContext, origin: CGPoint) { + context.saveGState() + + let rect = CGRect(origin: origin, size: CGSize(width: valueKnobSize, height: valueKnobSize)) + let knobPath = UIBezierPath(ovalIn: rect) + + context.setShadow(offset: valueKnobShadowOffset, blur: valueKnobShadowBlur, color: valueKnobShadowColor.cgColor) + context.addPath(knobPath.cgPath) + context.setFillColor(valueKnobColor.cgColor) + context.setLineCap(.round) + context.setLineWidth(12) + context.drawPath(using: .fill) + + context.restoreGState() + } + + /** + Draws the value label for the view. + Only drawn if shouldShowValueText = true + */ + private func drawValueLabel() { + guard shouldShowValueText else { return } + + // Draws the text field + // Some basic label properties are set + valueLabel.font = font + valueLabel.textAlignment = .center + valueLabel.textColor = fontColor + + valueLabel.update(withValue: value, + valueIndicator: valueIndicator, + rightToLeft: rightToLeft, + showsDecimal: showFloatingPoint, + decimalPlaces: decimalPlaces, + valueDelegate: valueDelegate) + + // Deterime what should be the center for the label + valueLabel.center = CGPoint(x: bounds.midX, y: bounds.midY) + + valueLabel.drawText(in: bounds) + } +} diff --git a/Pods/UICircularProgressRing/src/UICircularProgressRing/UICircularProgressRingStyle.swift b/Pods/UICircularProgressRing/src/UICircularProgressRing/UICircularProgressRingStyle.swift new file mode 100644 index 00000000..521451b1 --- /dev/null +++ b/Pods/UICircularProgressRing/src/UICircularProgressRing/UICircularProgressRingStyle.swift @@ -0,0 +1,49 @@ +// +// UICircularProgressRingStyle.swift +// UICircularProgressRing +// +// Copyright (c) 2016 Luis Padron +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is furnished +// to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT +// OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +/** + + # UICircularProgressRingStyle + + This is an enumeration which is used to determine the style of the progress ring. + + ## Author + Luis Padron + + */ +@objc public enum UICircularProgressRingStyle: Int { + /// Inner ring is inside the circle + case inside = 1 + /// Inner ring is placed ontop of the outer ring + case ontop = 2 + /// Outer ring is dashed + case dashed = 3 + /// Outer ring is dotted + case dotted = 4 + /// Inner ring is placed ontop of the outer ring and it has a gradient + case gradient = 5 + /// Inner ring is placed ontop of the outer ring and outer ring has border + case bordered = 6 +} diff --git a/Pods/WYPopoverController/LICENSE b/Pods/WYPopoverController/LICENSE new file mode 100644 index 00000000..6e765e33 --- /dev/null +++ b/Pods/WYPopoverController/LICENSE @@ -0,0 +1,9 @@ +WYPopoverController is available under the MIT license. + +Copyright © 2013 Nicolas CHENG + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/Pods/WYPopoverController/README.md b/Pods/WYPopoverController/README.md new file mode 100644 index 00000000..9e10af4a --- /dev/null +++ b/Pods/WYPopoverController/README.md @@ -0,0 +1,347 @@ +WYPopoverController +=================== + +WYPopoverController is for the presentation of content in popover on iPhone / iPad devices. Very customizable. + +### Screenshots + +--- + +![](https://raw.github.com/nicolaschengdev/WYPopoverController/master/screenshots/wypopover_screenshot_1.png) ![](https://raw.github.com/nicolaschengdev/WYPopoverController/master/screenshots/wypopover_screenshot_2.png) + +### Features + +--- + +* UIAppearance support +* Works like UIPopoverController +* Works also with blocks +* Animation options +* Automatic orientation support +* UIStoryboard support +* Keyboard show / hide support +* iOS 6 & 7 support +* UIAccessibility support +* Theme support + +### UIAppearance support + +--- + +| Property | Type | Default value (iOS 6) | Default value (iOS 7) | +| ----------------------------- | -------------- | ---------------------: | ---------------------: | +| tintColor | `UIColor` | *nil* | *nil* | +| arrowBase | `CGFloat` | 42 | 25 | +| arrowHeight | `CGFloat` | 18 | 13 | +| borderWidth | `CGFloat` | 6 | 0 | +| outerCornerRadius | `CGFloat` | 8 | 5 | +| innerCornerRadius | `CGFloat` | 6 | 0 | +| viewContentInsets | `UIEdgeInsets` | { 3, 0, 0, 0 } | UIEdgeInsetsZero | +| fillTopColor | `UIColor` | #373f47ff | #f4f4f4ff | +| fillBottomColor | `UIColor` | #3b434cff | #f4f4f4ff | +| glossShadowColor | `UIColor` | #c3c5c77f | #transparent | +| glossShadowBlurRadius | `CGFloat` | 0 | 0 | +| glossShadowOffset | `CGSize` | { 0, 1.5 } | CGSizeZero | +| outerShadowColor | `UIColor` | #000000bf | #transparent | +| outerShadowBlurRadius | `CGFloat` | 8 | 0 | +| outerShadowOffset | `CGSize` | { 0, 2 } | CGSizeZero | +| innerShadowColor | `UIColor` | #000000bf | #transparent | +| innerShadowBlurRadius | `CGFloat` | 2 | 0 | +| innerShadowOffset | `CGSize` | { 0, 1 } | CGSizeZero | +| minOuterCornerRadius | `CGFloat` | 0 | 0 | +| innerStrokeColor | `UIColor` | #262c31ff | #transparent | +| outerStrokeColor | `UIColor` | #262c31ff | #transparent | + +##### Arrow & Border + +![](https://raw.github.com/nicolaschengdev/WYPopoverController/master/screenshots/appearance/small/wypopover_arrowbase.png "arrowBase: 42") , ![](https://raw.github.com/nicolaschengdev/WYPopoverController/master/screenshots/appearance/small/wypopover_arrowheight.png "arrowHeight: 18") , ![](https://raw.github.com/nicolaschengdev/WYPopoverController/master/screenshots/appearance/small/wypopover_borderwidth.png "borderWidth: 6") + +##### Corner radius & View content insets + +![](https://raw.github.com/nicolaschengdev/WYPopoverController/master/screenshots/appearance/small/wypopover_outercornerradius_0.png "outerCornerRadius: 0") , ![](https://raw.github.com/nicolaschengdev/WYPopoverController/master/screenshots/appearance/small/wypopover_innercornerradius_14.png "innerCornerRadius: 14") , ![](https://raw.github.com/nicolaschengdev/WYPopoverController/master/screenshots/appearance/small/wypopover_viewcontentinsets_4-4-4-4.png "viewContentInsets: {4, 4, 4, 4}") + +##### Stroke & Fill + +![](https://raw.github.com/nicolaschengdev/WYPopoverController/master/screenshots/appearance/small/wypopover_innerstrokecolor.png "innerStrokeColor: #c3045e") , ![](https://raw.github.com/nicolaschengdev/WYPopoverController/master/screenshots/appearance/small/wypopover_outerstrokecolor.png "outerStrokeColor: #c3045e") , ![](https://raw.github.com/nicolaschengdev/WYPopoverController/master/screenshots/appearance/small/wypopover_filltopcolor.png "fillTopColor: #c3045e") , ![](https://raw.github.com/nicolaschengdev/WYPopoverController/master/screenshots/appearance/small/wypopover_fillbottomcolor.png "fillBottomColor: #c3045e") + +##### Gloss + +![](https://raw.github.com/nicolaschengdev/WYPopoverController/master/screenshots/appearance/small/wypopover_glossshadowcolor.png "glossShadowColor: #c3045e, glossShadowOffset: {0, 1.5}, glossShadowBlurRadius: 0") , ![](https://raw.github.com/nicolaschengdev/WYPopoverController/master/screenshots/appearance/small/wypopover_glossshadowblurradius_2.png "glossShadowColor: #c3045e, glossShadowOffset: {0, 1.5}, glossShadowBlurRadius: 2") , ![](https://raw.github.com/nicolaschengdev/WYPopoverController/master/screenshots/appearance/small/wypopover_glossshadowoffset_0-3.png "glossShadowColor: #c3045e, glossShadowOffset: {0, 3}, glossShadowBlurRadius: 0") + +##### Outer + +![](https://raw.github.com/nicolaschengdev/WYPopoverController/master/screenshots/appearance/small/wypopover_outershadowcolor.png "outerShadowColor: #c3045e, outerShadowOffset: {0, 2}, outerShadowBlurRadius: 8") , ![](https://raw.github.com/nicolaschengdev/WYPopoverController/master/screenshots/appearance/small/wypopover_outershadowblurradius_2.png "outerShadowColor: #c3045e, outerShadowOffset: {0, 2}, outerShadowBlurRadius: 2") , ![](https://raw.github.com/nicolaschengdev/WYPopoverController/master/screenshots/appearance/small/wypopover_outershadowoffset_0--2.png "outerShadowColor: #c3045e, outerShadowOffset: {0, -2}, outerShadowBlurRadius: 2") + +##### Inner + +![](https://raw.github.com/nicolaschengdev/WYPopoverController/master/screenshots/appearance/small/wypopover_innershadowcolor.png "innerShadowColor: #c3045e, innerShadowOffset: {0, 1}, innerShadowBlurRadius: 2") , ![](https://raw.github.com/nicolaschengdev/WYPopoverController/master/screenshots/appearance/small/wypopover_innershadowoffset_0--1.png "innerShadowColor: #c3045e, innerShadowOffset: {0, -1}, innerShadowBlurRadius: 2") , ![](https://raw.github.com/nicolaschengdev/WYPopoverController/master/screenshots/appearance/small/wypopover_innershadowblurradius_0.png "innerShadowColor: #c3045e, innerShadowOffset: {0, 1}, innerShadowBlurRadius: 0") + +### Works like UIPopoverController + +--- + +#### passthroughViews + +An array of views that the user can interact with while the popover is visible. + +#### wantsDefaultContentAppearance + +![](https://raw.github.com/nicolaschengdev/WYPopoverController/master/screenshots/wypopover_wantsdefaultcontentappearance.png "") + +Determines whether the default content appearance should be used for the popover. + +#### popoverLayoutMargins + +![](https://raw.github.com/nicolaschengdev/WYPopoverController/master/screenshots/wypopover_popoverlayoutmargins.png "") + +The margins that define the portion of the screen in which it is permissible to display the popover. + +### Works also with blocks + +--- + +A block object can be executed when animation sequences ends. This parameter may be `nil`. + +**Important :** If a block object is defined then correspondent delegate methods is not called. + +#### Example + +```objective-c + +popover = [[WYPopoverController alloc] initWithContentViewController:contentViewController]; +[popover presentPopoverAsDialogAnimated:YES + completion:^{ + // Code executed after popover presentation animation sequence ends + }]; +``` + +### Animation options + +--- + +There are 3 styles of animation : +* Fade *(by default)* +* Scale +* Fade with Scale + +#### Example + +```objective-c + +popover = [[WYPopoverController alloc] initWithContentViewController:contentViewController]; +[popover presentPopoverFromRect:btn.bounds + inView:btn + permittedArrowDirections:WYPopoverArrowDirectionAny + animated:YES + options:WYPopoverAnimationOptionFadeWithScale]; +``` + +### ARC + +--- + +WYPopoverController uses ARC. + +### Installation + +--- + +~~iOS SDK 7.0 (with Xcode 5) is required.~~ + +#### Cocoapods + +Add this line `pod 'WYPopoverController', '~> 0.2.0'` to your PodFile. + +Your PodFile should look like : + +```Ruby +platform :ios, '6.0' +pod 'WYPopoverController', '~> 0.2.2' +``` + +To use the `master` branch of the repo : + +```Ruby +platform :ios, '6.0' +pod 'WYPopoverController', :git => 'https://github.com/nicolaschengdev/WYPopoverController.git' +``` + +#### Manually + +Add these files to your project : +* `WYPopoverController.h` and `WYPopoverController.m` +* `WYStoryboardPopoverSegue.h` and `WYStoryboardPopoverSegue.m` + +And link `QuartzCore.framework` library in the *Build Phases* of your project targets. + +### Examples + +--- + +##### Simple + +In the implementation of your view controller + +```objective-c +// YourViewController.m + +@interface YourViewController () +{ + WYPopoverController* popoverController; +} + +- (IBAction)showPopover:(id)sender; + +@end + +@implementation YourViewController + +- (IBAction)showPopover:(id)sender +{ + popoverController = [[WYPopoverController alloc] initWithContentViewController:controller]; + popoverController.delegate = self; + [popoverController presentPopoverFromRect:button.bounds inView:button permittedArrowDirections:WYPopoverArrowDirectionAny animated:YES]; +} + +- (BOOL)popoverControllerShouldDismissPopover:(WYPopoverController *)controller +{ + return YES; +} + +- (void)popoverControllerDidDismissPopover:(WYPopoverController *)controller +{ + popoverController.delegate = nil; + popoverController = nil; +} + +@end +``` + +##### Appearance (Tint Color) + +```objective-c +WYPopoverBackgroundView* appearance = [WYPopoverBackgroundView appearance]; +[appearance setTintColor:[UIColor orangeColor]]; +``` + +##### Appearance (Flat Popover) + +```objective-c +UIColor* greenColor = [UIColor colorWithRed:26.f/255.f green:188.f/255.f blue:156.f/255.f alpha:1]; + +WYPopoverBackgroundView* popoverAppearance = [WYPopoverBackgroundView appearance]; + +[popoverAppearance setOuterCornerRadius:4]; +[popoverAppearance setOuterShadowBlurRadius:0]; +[popoverAppearance setOuterShadowColor:[UIColor clearColor]]; +[popoverAppearance setOuterShadowOffset:CGSizeMake(0, 0)]; + +[popoverAppearance setGlossShadowColor:[UIColor clearColor]]; +[popoverAppearance setGlossShadowOffset:CGSizeMake(0, 0)]; + +[popoverAppearance setBorderWidth:8]; +[popoverAppearance setArrowHeight:10]; +[popoverAppearance setArrowBase:20]; + +[popoverAppearance setInnerCornerRadius:4]; +[popoverAppearance setInnerShadowBlurRadius:0]; +[popoverAppearance setInnerShadowColor:[UIColor clearColor]]; +[popoverAppearance setInnerShadowOffset:CGSizeMake(0, 0)]; + +[popoverAppearance setFillTopColor:greenColor]; +[popoverAppearance setFillBottomColor:greenColor]; +[popoverAppearance setOuterStrokeColor:greenColor]; +[popoverAppearance setInnerStrokeColor:greenColor]; + +UINavigationBar* navBarInPopoverAppearance = [UINavigationBar appearanceWhenContainedIn:[UINavigationController class], [WYPopoverController class], nil]; +[navBarInPopoverAppearance setTitleTextAttributes: @{ + UITextAttributeTextColor : [UIColor whiteColor], + UITextAttributeTextShadowColor : [UIColor clearColor], + UITextAttributeTextShadowOffset : [NSValue valueWithUIOffset:UIOffsetMake(0, -1)]}]; +``` + +##### Storyboard + +```objective-c +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender +{ + if ([segue.identifier isEqualToString:@"[YOUR_SEGUE_IDENTIFIER]"]) + { + WYStoryboardPopoverSegue* popoverSegue = (WYStoryboardPopoverSegue*)segue; + + UIViewController* destinationViewController = (UIViewController *)segue.destinationViewController; + destinationViewController.contentSizeForViewInPopover = CGSizeMake(280, 280); // Deprecated in iOS7. Use 'preferredContentSize' instead. + + popoverController = [popoverSegue popoverControllerWithSender:sender permittedArrowDirections:WYPopoverArrowDirectionAny animated:YES]; + popoverController.delegate = self; + } +} +``` + +##### Theme + +Introduced in 0.2.1 release, you can change appearance of your popovers with themes. + +```objective-c +- (void)changePopoverTheme +{ + popover.theme = [WYPopoverTheme themeForIOS6]; // you set a new theme + + // use beginThemeUpdates and endThemeUpdates methods if you have to change several values which compose your current theme + + [popover beginThemeUpdates]; + popover.theme.arrowHeight = 30; + popover.theme.arrowBase = 40; + [popover endThemeUpdates]; +} +``` + +##### Keyboard + +By default, when keyboard is shown, popover will be repositionned if it is (partially) hidden. +Introduced in 0.2.1 release, you can control value of y offset when keyboard is shown with the following `delegate` method : + +```objective-c +- (void)popoverController:(WYPopoverController *)popoverController willTranslatePopoverWithYOffset:(CGFloat *)value +{ + *value = 0; // if value is setted to 0 then popover will not be translated +} +``` + +### Handling popover controllers during orientation changes + +--- + +When showing a popover controller, there are times when you will need to handle how the popover controller appears after a change in device orientation. + +Situations when handling is required: + +* If the popover controller is presented from a target rectangle using the `-presentPopoverFromRect:inView:permittedArrowDirections:animated` method of WYPopoverController. You can use `-popoverController:willRepositionPopoverToRect:inView:` method introduced in the **0.1.6 release** . +* If the popover controller is presented from a bar button item that is removed after the rotation has finished . + +### Change logs + +--- + +A brief summary of each WYPopoverController release can be found on the [wiki](https://github.com/nicolaschengdev/WYPopoverController/wiki/Change-logs). + +### Contact + +--- + +* [@mikl_jeo](https://twitter.com/mikl_jeo) on Twitter +* [@nicolaschengdev](https://github.com/nicolaschengdev) on Github + +### License + +--- + +WYPopoverController is available under the MIT license. + +Copyright © 2013 Nicolas CHENG + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/Pods/WYPopoverController/WYPopoverController/WYPopoverController.h b/Pods/WYPopoverController/WYPopoverController/WYPopoverController.h new file mode 100644 index 00000000..ce70335f --- /dev/null +++ b/Pods/WYPopoverController/WYPopoverController/WYPopoverController.h @@ -0,0 +1,254 @@ +/* + Version 0.2.2 + + WYPopoverController is available under the MIT license. + + Copyright © 2013 Nicolas CHENG + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#import +#import +#import + +@protocol WYPopoverControllerDelegate; +@class WYPopoverTheme; + +#ifndef WY_POPOVER_DEFAULT_ANIMATION_DURATION + #define WY_POPOVER_DEFAULT_ANIMATION_DURATION .25f +#endif + +#ifndef WY_POPOVER_MIN_SIZE + #define WY_POPOVER_MIN_SIZE CGSizeMake(240, 160) +#endif + +typedef NS_OPTIONS(NSUInteger, WYPopoverArrowDirection) { + WYPopoverArrowDirectionUp = 1UL << 0, + WYPopoverArrowDirectionDown = 1UL << 1, + WYPopoverArrowDirectionLeft = 1UL << 2, + WYPopoverArrowDirectionRight = 1UL << 3, + WYPopoverArrowDirectionNone = 1UL << 4, + WYPopoverArrowDirectionAny = WYPopoverArrowDirectionUp | WYPopoverArrowDirectionDown | WYPopoverArrowDirectionLeft | WYPopoverArrowDirectionRight, + WYPopoverArrowDirectionUnknown = NSUIntegerMax +}; + +typedef NS_OPTIONS(NSUInteger, WYPopoverAnimationOptions) { + WYPopoverAnimationOptionFade = 1UL << 0, // default + WYPopoverAnimationOptionScale = 1UL << 1, + WYPopoverAnimationOptionFadeWithScale = WYPopoverAnimationOptionFade | WYPopoverAnimationOptionScale +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface WYPopoverBackgroundView : UIView + +@property (nonatomic, strong) UIColor *tintColor UI_APPEARANCE_SELECTOR; +@property (nonatomic, strong) UIColor *fillTopColor UI_APPEARANCE_SELECTOR; +@property (nonatomic, strong) UIColor *fillBottomColor UI_APPEARANCE_SELECTOR; + +@property (nonatomic, strong) UIColor *glossShadowColor UI_APPEARANCE_SELECTOR; +@property (nonatomic, assign) CGSize glossShadowOffset UI_APPEARANCE_SELECTOR; +@property (nonatomic, assign) CGFloat glossShadowBlurRadius UI_APPEARANCE_SELECTOR; + +@property (nonatomic, assign) CGFloat borderWidth UI_APPEARANCE_SELECTOR; +@property (nonatomic, assign) CGFloat arrowBase UI_APPEARANCE_SELECTOR; +@property (nonatomic, assign) CGFloat arrowHeight UI_APPEARANCE_SELECTOR; + +@property (nonatomic, strong) UIColor *outerShadowColor UI_APPEARANCE_SELECTOR; +@property (nonatomic, strong) UIColor *outerStrokeColor UI_APPEARANCE_SELECTOR; +@property (nonatomic, assign) CGFloat outerShadowBlurRadius UI_APPEARANCE_SELECTOR; +@property (nonatomic, assign) CGSize outerShadowOffset UI_APPEARANCE_SELECTOR; +@property (nonatomic, assign) CGFloat outerCornerRadius UI_APPEARANCE_SELECTOR; +@property (nonatomic, assign) CGFloat minOuterCornerRadius UI_APPEARANCE_SELECTOR; + +@property (nonatomic, strong) UIColor *innerShadowColor UI_APPEARANCE_SELECTOR; +@property (nonatomic, strong) UIColor *innerStrokeColor UI_APPEARANCE_SELECTOR; +@property (nonatomic, assign) CGFloat innerShadowBlurRadius UI_APPEARANCE_SELECTOR; +@property (nonatomic, assign) CGSize innerShadowOffset UI_APPEARANCE_SELECTOR; +@property (nonatomic, assign) CGFloat innerCornerRadius UI_APPEARANCE_SELECTOR; + +@property (nonatomic, assign) UIEdgeInsets viewContentInsets UI_APPEARANCE_SELECTOR; + +@property (nonatomic, strong) UIColor *overlayColor UI_APPEARANCE_SELECTOR; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface WYPopoverController : NSObject + +@property (nonatomic, weak) id delegate; + +@property (nonatomic, copy) NSArray *passthroughViews; +@property (nonatomic, assign) BOOL wantsDefaultContentAppearance; +@property (nonatomic, assign) UIEdgeInsets popoverLayoutMargins; +@property (nonatomic, readonly, getter=isPopoverVisible) BOOL popoverVisible; +@property (nonatomic, strong, readonly) UIViewController *contentViewController; +@property (nonatomic, assign) CGSize popoverContentSize; +@property (nonatomic, assign) CGFloat animationDuration; + +@property (nonatomic, strong) WYPopoverTheme *theme; + ++ (void)setDefaultTheme:(WYPopoverTheme *)theme; ++ (WYPopoverTheme *)defaultTheme; + +// initialization + +- (id)initWithContentViewController:(UIViewController *)viewController; + +// theme + +- (void)beginThemeUpdates; +- (void)endThemeUpdates; + +// Present popover from classic views methods + +- (void)presentPopoverFromRect:(CGRect)rect + inView:(UIView *)view + permittedArrowDirections:(WYPopoverArrowDirection)arrowDirections + animated:(BOOL)animated; + +- (void)presentPopoverFromRect:(CGRect)rect + inView:(UIView *)view + permittedArrowDirections:(WYPopoverArrowDirection)arrowDirections + animated:(BOOL)animated + completion:(void (^)(void))completion; + +- (void)presentPopoverFromRect:(CGRect)rect + inView:(UIView *)view + permittedArrowDirections:(WYPopoverArrowDirection)arrowDirections + animated:(BOOL)animated + options:(WYPopoverAnimationOptions)options; + +- (void)presentPopoverFromRect:(CGRect)rect + inView:(UIView *)view + permittedArrowDirections:(WYPopoverArrowDirection)arrowDirections + animated:(BOOL)animated + options:(WYPopoverAnimationOptions)options + completion:(void (^)(void))completion; + +// Present popover from bar button items methods + +- (void)presentPopoverFromBarButtonItem:(UIBarButtonItem *)item + permittedArrowDirections:(WYPopoverArrowDirection)arrowDirections + animated:(BOOL)animated; + +- (void)presentPopoverFromBarButtonItem:(UIBarButtonItem *)item + permittedArrowDirections:(WYPopoverArrowDirection)arrowDirections + animated:(BOOL)animated + completion:(void (^)(void))completion; + +- (void)presentPopoverFromBarButtonItem:(UIBarButtonItem *)item + permittedArrowDirections:(WYPopoverArrowDirection)arrowDirections + animated:(BOOL)animated + options:(WYPopoverAnimationOptions)options; + +- (void)presentPopoverFromBarButtonItem:(UIBarButtonItem *)item + permittedArrowDirections:(WYPopoverArrowDirection)arrowDirections + animated:(BOOL)animated + options:(WYPopoverAnimationOptions)options + completion:(void (^)(void))completion; + +// Present popover as dialog methods + +- (void)presentPopoverAsDialogAnimated:(BOOL)animated; + +- (void)presentPopoverAsDialogAnimated:(BOOL)animated + completion:(void (^)(void))completion; + +- (void)presentPopoverAsDialogAnimated:(BOOL)animated + options:(WYPopoverAnimationOptions)options; + +- (void)presentPopoverAsDialogAnimated:(BOOL)animated + options:(WYPopoverAnimationOptions)options + completion:(void (^)(void))completion; + +// Dismiss popover methods + +- (void)dismissPopoverAnimated:(BOOL)animated; + +- (void)dismissPopoverAnimated:(BOOL)animated + completion:(void (^)(void))completion; + +- (void)dismissPopoverAnimated:(BOOL)animated + options:(WYPopoverAnimationOptions)aOptions; + +- (void)dismissPopoverAnimated:(BOOL)animated + options:(WYPopoverAnimationOptions)aOptions + completion:(void (^)(void))completion; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +@protocol WYPopoverControllerDelegate +@optional + +- (BOOL)popoverControllerShouldDismissPopover:(WYPopoverController *)popoverController; + +- (void)popoverControllerDidPresentPopover:(WYPopoverController *)popoverController; + +- (void)popoverControllerDidDismissPopover:(WYPopoverController *)popoverController; + +- (void)popoverController:(WYPopoverController *)popoverController willRepositionPopoverToRect:(inout CGRect *)rect inView:(inout UIView **)view; + +- (BOOL)popoverControllerShouldIgnoreKeyboardBounds:(WYPopoverController *)popoverController; + +- (void)popoverController:(WYPopoverController *)popoverController willTranslatePopoverWithYOffset:(CGFloat *)value; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface WYPopoverTheme : NSObject + +@property (nonatomic, strong) UIColor *tintColor; +@property (nonatomic, strong) UIColor *fillTopColor; +@property (nonatomic, strong) UIColor *fillBottomColor; + +@property (nonatomic, strong) UIColor *glossShadowColor; +@property (nonatomic, assign) CGSize glossShadowOffset; +@property (nonatomic, assign) CGFloat glossShadowBlurRadius; + +@property (nonatomic, assign) CGFloat borderWidth; +@property (nonatomic, assign) CGFloat arrowBase; +@property (nonatomic, assign) CGFloat arrowHeight; + +@property (nonatomic, strong) UIColor *outerShadowColor; +@property (nonatomic, strong) UIColor *outerStrokeColor; +@property (nonatomic, assign) CGFloat outerShadowBlurRadius; +@property (nonatomic, assign) CGSize outerShadowOffset; +@property (nonatomic, assign) CGFloat outerCornerRadius; +@property (nonatomic, assign) CGFloat minOuterCornerRadius; + +@property (nonatomic, strong) UIColor *innerShadowColor; +@property (nonatomic, strong) UIColor *innerStrokeColor; +@property (nonatomic, assign) CGFloat innerShadowBlurRadius; +@property (nonatomic, assign) CGSize innerShadowOffset; +@property (nonatomic, assign) CGFloat innerCornerRadius; + +@property (nonatomic, assign) UIEdgeInsets viewContentInsets; + +@property (nonatomic, strong) UIColor *overlayColor; + ++ (instancetype)theme; ++ (instancetype)themeForIOS6; ++ (instancetype)themeForIOS7; + +@end diff --git a/Pods/WYPopoverController/WYPopoverController/WYPopoverController.m b/Pods/WYPopoverController/WYPopoverController/WYPopoverController.m new file mode 100644 index 00000000..e6fd5ce8 --- /dev/null +++ b/Pods/WYPopoverController/WYPopoverController/WYPopoverController.m @@ -0,0 +1,3171 @@ +/* + Version 0.2.2 + + WYPopoverController is available under the MIT license. + + Copyright © 2013 Nicolas CHENG + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#import "WYPopoverController.h" + +#import + +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 +#define WY_BASE_SDK_7_ENABLED +#endif + +#ifdef DEBUG +#define WY_LOG(fmt, ...) NSLog((@"%s (%d) : " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__) +#else +#define WY_LOG(...) +#endif + +#define WY_IS_IOS_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame) + +#define WY_IS_IOS_GREATER_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending) + +#define WY_IS_IOS_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending) + +#define WY_IS_IOS_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending) + + +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface UIColor (WYPopover) + +- (BOOL)getValueOfRed:(CGFloat*)red green:(CGFloat*)green blue:(CGFloat*)blue alpha:(CGFloat*)apha; +- (NSString *)hexString; +- (UIColor *)colorByLighten:(CGFloat)d; +- (UIColor *)colorByDarken:(CGFloat)d; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation UIColor (WYPopover) + +- (BOOL)getValueOfRed:(CGFloat *)red green:(CGFloat *)green blue:(CGFloat *)blue alpha:(CGFloat *)alpha +{ + // model: kCGColorSpaceModelRGB, num_comps: 4 + // model: kCGColorSpaceModelMonochrome, num_comps: 2 + + CGColorSpaceRef colorSpace = CGColorSpaceRetain(CGColorGetColorSpace([self CGColor])); + CGColorSpaceModel colorSpaceModel = CGColorSpaceGetModel(colorSpace); + CGColorSpaceRelease(colorSpace); + + CGFloat rFloat = 0, gFloat = 0, bFloat = 0, aFloat = 0; + BOOL result = NO; + + if (colorSpaceModel == kCGColorSpaceModelRGB) + { + result = [self getRed:&rFloat green:&gFloat blue:&bFloat alpha:&aFloat]; + } + else if (colorSpaceModel == kCGColorSpaceModelMonochrome) + { + result = [self getWhite:&rFloat alpha:&aFloat]; + gFloat = rFloat; + bFloat = rFloat; + } + + if (red) *red = rFloat; + if (green) *green = gFloat; + if (blue) *blue = bFloat; + if (alpha) *alpha = aFloat; + + return result; +} + +- (NSString *)hexString +{ + CGFloat rFloat, gFloat, bFloat, aFloat; + int r, g, b, a; + [self getValueOfRed:&rFloat green:&gFloat blue:&bFloat alpha:&aFloat]; + + r = (int)(255.0 * rFloat); + g = (int)(255.0 * gFloat); + b = (int)(255.0 * bFloat); + a = (int)(255.0 * aFloat); + + return [NSString stringWithFormat:@"#%02x%02x%02x%02x", r, g, b, a]; +} + +- (UIColor *)colorByLighten:(CGFloat)d +{ + CGFloat rFloat, gFloat, bFloat, aFloat; + [self getValueOfRed:&rFloat green:&gFloat blue:&bFloat alpha:&aFloat]; + + return [UIColor colorWithRed:MIN(rFloat + d, 1.0) + green:MIN(gFloat + d, 1.0) + blue:MIN(bFloat + d, 1.0) + alpha:1.0]; +} + +- (UIColor *)colorByDarken:(CGFloat)d +{ + CGFloat rFloat, gFloat, bFloat, aFloat; + [self getValueOfRed:&rFloat green:&gFloat blue:&bFloat alpha:&aFloat]; + + return [UIColor colorWithRed:MAX(rFloat - d, 0.0) + green:MAX(gFloat - d, 0.0) + blue:MAX(bFloat - d, 0.0) + alpha:1.0]; +} + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface UINavigationController (WYPopover) + +@property(nonatomic, assign, getter = isEmbedInPopover) BOOL embedInPopover; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation UINavigationController (WYPopover) + +static char const * const UINavigationControllerEmbedInPopoverTagKey = "UINavigationControllerEmbedInPopoverTagKey"; + +@dynamic embedInPopover; + ++ (void)load +{ + Method original, swizzle; + + original = class_getInstanceMethod(self, @selector(pushViewController:animated:)); + swizzle = class_getInstanceMethod(self, @selector(sizzled_pushViewController:animated:)); + + method_exchangeImplementations(original, swizzle); + + original = class_getInstanceMethod(self, @selector(setViewControllers:animated:)); + swizzle = class_getInstanceMethod(self, @selector(sizzled_setViewControllers:animated:)); + + method_exchangeImplementations(original, swizzle); +} + +- (BOOL)isEmbedInPopover +{ + BOOL result = NO; + + NSNumber *value = objc_getAssociatedObject(self, UINavigationControllerEmbedInPopoverTagKey); + + if (value) + { + result = [value boolValue]; + } + + return result; +} + +- (void)setEmbedInPopover:(BOOL)value +{ + objc_setAssociatedObject(self, UINavigationControllerEmbedInPopoverTagKey, [NSNumber numberWithBool:value], OBJC_ASSOCIATION_RETAIN_NONATOMIC); +} + +- (CGSize)contentSize:(UIViewController *)aViewController +{ + CGSize result = CGSizeZero; + +#pragma clang diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated" + if ([aViewController respondsToSelector:@selector(contentSizeForViewInPopover)]) + { + result = aViewController.contentSizeForViewInPopover; + } +#pragma clang diagnostic pop + +#ifdef WY_BASE_SDK_7_ENABLED + if ([aViewController respondsToSelector:@selector(preferredContentSize)]) + { + result = aViewController.preferredContentSize; + } +#endif + + return result; +} + +- (void)setContentSize:(CGSize)aContentSize +{ +#pragma clang diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated" + [self setContentSizeForViewInPopover:aContentSize]; +#pragma clang diagnostic pop + +#ifdef WY_BASE_SDK_7_ENABLED + [self setPreferredContentSize:aContentSize]; +#endif +} + +- (void)sizzled_pushViewController:(UIViewController *)aViewController animated:(BOOL)aAnimated +{ + if (self.isEmbedInPopover) + { +#ifdef WY_BASE_SDK_7_ENABLED + aViewController.edgesForExtendedLayout = UIRectEdgeNone; +#endif + CGSize contentSize = [self contentSize:aViewController]; + [self setContentSize:contentSize]; + } + + [self sizzled_pushViewController:aViewController animated:aAnimated]; + + if (self.isEmbedInPopover) + { + CGSize contentSize = [self contentSize:aViewController]; + [self setContentSize:contentSize]; + } +} + +- (void)sizzled_setViewControllers:(NSArray *)aViewControllers animated:(BOOL)aAnimated +{ + NSUInteger count = [aViewControllers count]; + +#ifdef WY_BASE_SDK_7_ENABLED + if (self.isEmbedInPopover && count > 0) + { + for (UIViewController *viewController in aViewControllers) { + if ([viewController respondsToSelector:@selector(setEdgesForExtendedLayout:)]) + { + viewController.edgesForExtendedLayout = UIRectEdgeNone; + } + } + } +#endif + + [self sizzled_setViewControllers:aViewControllers animated:aAnimated]; + + if (self.isEmbedInPopover && count > 0) + { + UIViewController *topViewController = [aViewControllers objectAtIndex:(count - 1)]; + CGSize contentSize = [self contentSize:topViewController]; + [self setContentSize:contentSize]; + } +} + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface UIViewController (WYPopover) +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation UIViewController (WYPopover) + ++ (void)load +{ + Method original, swizzle; + +#pragma clang diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated" + original = class_getInstanceMethod(self, @selector(setContentSizeForViewInPopover:)); + swizzle = class_getInstanceMethod(self, @selector(sizzled_setContentSizeForViewInPopover:)); + method_exchangeImplementations(original, swizzle); +#pragma clang diagnostic pop + +#ifdef WY_BASE_SDK_7_ENABLED + original = class_getInstanceMethod(self, @selector(setPreferredContentSize:)); + swizzle = class_getInstanceMethod(self, @selector(sizzled_setPreferredContentSize:)); + + if (original != NULL) { + method_exchangeImplementations(original, swizzle); + } +#endif +} + +- (void)sizzled_setContentSizeForViewInPopover:(CGSize)aSize +{ + [self sizzled_setContentSizeForViewInPopover:aSize]; + + if ([self isKindOfClass:[UINavigationController class]] == NO && self.navigationController != nil) + { +#pragma clang diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated" + [self.navigationController setContentSizeForViewInPopover:aSize]; +#pragma clang diagnostic pop + } +} + +- (void)sizzled_setPreferredContentSize:(CGSize)aSize +{ + [self sizzled_setPreferredContentSize:aSize]; + + if ([self isKindOfClass:[UINavigationController class]] == NO && self.navigationController != nil) + { +#ifdef WY_BASE_SDK_7_ENABLED + if ([self respondsToSelector:@selector(setPreferredContentSize:)]) { + [self.navigationController setPreferredContentSize:aSize]; + } +#endif + } +} + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface WYPopoverArea : NSObject +{ +} + +@property (nonatomic, assign) WYPopoverArrowDirection arrowDirection; +@property (nonatomic, assign) CGSize areaSize; +@property (nonatomic, assign, readonly) CGFloat value; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +#pragma mark +#pragma mark - WYPopoverArea + +@implementation WYPopoverArea + +@synthesize arrowDirection; +@synthesize areaSize; +@synthesize value; + +- (NSString*)description +{ + NSString* direction = @""; + + if (arrowDirection == WYPopoverArrowDirectionUp) + { + direction = @"UP"; + } + else if (arrowDirection == WYPopoverArrowDirectionDown) + { + direction = @"DOWN"; + } + else if (arrowDirection == WYPopoverArrowDirectionLeft) + { + direction = @"LEFT"; + } + else if (arrowDirection == WYPopoverArrowDirectionRight) + { + direction = @"RIGHT"; + } + else if (arrowDirection == WYPopoverArrowDirectionNone) + { + direction = @"NONE"; + } + + return [NSString stringWithFormat:@"%@ [ %f x %f ]", direction, areaSize.width, areaSize.height]; +} + +- (CGFloat)value +{ + CGFloat result = 0; + + if (areaSize.width > 0 && areaSize.height > 0) + { + CGFloat w1 = ceilf(areaSize.width / 10.0); + CGFloat h1 = ceilf(areaSize.height / 10.0); + + result = (w1 * h1); + } + + return result; +} + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface WYPopoverTheme () + +- (NSArray *)observableKeypaths; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation WYPopoverTheme + +@synthesize tintColor; +@synthesize fillTopColor; +@synthesize fillBottomColor; + +@synthesize glossShadowColor; +@synthesize glossShadowOffset; +@synthesize glossShadowBlurRadius; + +@synthesize borderWidth; +@synthesize arrowBase; +@synthesize arrowHeight; + +@synthesize outerShadowColor; +@synthesize outerStrokeColor; +@synthesize outerShadowBlurRadius; +@synthesize outerShadowOffset; +@synthesize outerCornerRadius; +@synthesize minOuterCornerRadius; + +@synthesize innerShadowColor; +@synthesize innerStrokeColor; +@synthesize innerShadowBlurRadius; +@synthesize innerShadowOffset; +@synthesize innerCornerRadius; + +@synthesize viewContentInsets; + +@synthesize overlayColor; + ++ (id)theme { + + WYPopoverTheme *result = nil; + + if (WY_IS_IOS_LESS_THAN(@"7.0")) { + result = [WYPopoverTheme themeForIOS6]; + } else { + result = [WYPopoverTheme themeForIOS7]; + } + + return result; +} + ++ (id)themeForIOS6 { + + WYPopoverTheme *result = [[WYPopoverTheme alloc] init]; + + result.tintColor = [UIColor colorWithRed:55./255. green:63./255. blue:71./255. alpha:1.0]; + result.outerStrokeColor = nil; + result.innerStrokeColor = nil; + result.fillTopColor = result.tintColor; + result.fillBottomColor = [result.tintColor colorByDarken:0.4]; + result.glossShadowColor = nil; + result.glossShadowOffset = CGSizeMake(0, 1.5); + result.glossShadowBlurRadius = 0; + result.borderWidth = 6; + result.arrowBase = 42; + result.arrowHeight = 18; + result.outerShadowColor = [UIColor colorWithWhite:0 alpha:0.75]; + result.outerShadowBlurRadius = 8; + result.outerShadowOffset = CGSizeMake(0, 2); + result.outerCornerRadius = 8; + result.minOuterCornerRadius = 0; + result.innerShadowColor = [UIColor colorWithWhite:0 alpha:0.75]; + result.innerShadowBlurRadius = 2; + result.innerShadowOffset = CGSizeMake(0, 1); + result.innerCornerRadius = 6; + result.viewContentInsets = UIEdgeInsetsMake(3, 0, 0, 0); + result.overlayColor = [UIColor clearColor]; + + return result; +} + ++ (id)themeForIOS7 { + + WYPopoverTheme *result = [[WYPopoverTheme alloc] init]; + + result.tintColor = [UIColor colorWithRed:244./255. green:244./255. blue:244./255. alpha:1.0]; + result.outerStrokeColor = [UIColor clearColor]; + result.innerStrokeColor = [UIColor clearColor]; + result.fillTopColor = nil; + result.fillBottomColor = nil; + result.glossShadowColor = nil; + result.glossShadowOffset = CGSizeZero; + result.glossShadowBlurRadius = 0; + result.borderWidth = 0; + result.arrowBase = 25; + result.arrowHeight = 13; + result.outerShadowColor = [UIColor clearColor]; + result.outerShadowBlurRadius = 0; + result.outerShadowOffset = CGSizeZero; + result.outerCornerRadius = 5; + result.minOuterCornerRadius = 0; + result.innerShadowColor = [UIColor clearColor]; + result.innerShadowBlurRadius = 0; + result.innerShadowOffset = CGSizeZero; + result.innerCornerRadius = 0; + result.viewContentInsets = UIEdgeInsetsZero; + result.overlayColor = [UIColor colorWithWhite:0 alpha:0.15]; + + return result; +} + +- (CGFloat)innerCornerRadius +{ + CGFloat result = innerCornerRadius; + + if (borderWidth == 0) + { + result = 0; + + if (outerCornerRadius > 0) + { + result = outerCornerRadius; + } + } + + return result; +} + +- (CGSize)outerShadowOffset +{ + CGSize result = outerShadowOffset; + + result.width = MIN(result.width, outerShadowBlurRadius); + result.height = MIN(result.height, outerShadowBlurRadius); + + return result; +} + +- (UIColor *)innerStrokeColor +{ + UIColor *result = innerStrokeColor; + + if (result == nil) + { + result = [self.fillTopColor colorByDarken:0.6]; + } + + return result; +} + +- (UIColor *)outerStrokeColor +{ + UIColor *result = outerStrokeColor; + + if (result == nil) + { + result = [self.fillTopColor colorByDarken:0.6]; + } + + return result; +} + +- (UIColor *)glossShadowColor +{ + UIColor *result = glossShadowColor; + + if (result == nil) + { + result = [self.fillTopColor colorByLighten:0.2]; + } + + return result; +} + +- (UIColor *)fillTopColor +{ + UIColor *result = fillTopColor; + + if (result == nil) + { + result = tintColor; + } + + return result; +} + +- (UIColor *)fillBottomColor +{ + UIColor *result = fillBottomColor; + + if (result == nil) + { + result = self.fillTopColor; + } + + return result; +} + +- (NSArray *)observableKeypaths { + return [NSArray arrayWithObjects:@"tintColor", @"outerStrokeColor", @"innerStrokeColor", @"fillTopColor", @"fillBottomColor", @"glossShadowColor", @"glossShadowOffset", @"glossShadowBlurRadius", @"borderWidth", @"arrowBase", @"arrowHeight", @"outerShadowColor", @"outerShadowBlurRadius", @"outerShadowOffset", @"outerCornerRadius", @"innerShadowColor", @"innerShadowBlurRadius", @"innerShadowOffset", @"innerCornerRadius", @"viewContentInsets", @"overlayColor", nil]; +} + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface UIImage (WYPopover) + ++ (UIImage *)imageWithColor:(UIColor *)color; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +#pragma mark +#pragma mark - UIImage (WYPopover) + +@implementation UIImage (WYPopover) + +static CGFloat edgeSizeFromCornerRadius(CGFloat cornerRadius) { + return cornerRadius * 2 + 1; +} + ++ (UIImage *)imageWithColor:(UIColor *)color +{ + return [self imageWithColor:color size:CGSizeMake(8, 8) cornerRadius:0]; +} + ++ (UIImage *)imageWithColor:(UIColor *)color + cornerRadius:(CGFloat)cornerRadius +{ + CGFloat min = edgeSizeFromCornerRadius(cornerRadius); + + CGSize minSize = CGSizeMake(min, min); + + return [self imageWithColor:color size:minSize cornerRadius:cornerRadius]; +} + ++ (UIImage *)imageWithColor:(UIColor *)color + size:(CGSize)aSize + cornerRadius:(CGFloat)cornerRadius +{ + CGRect rect = CGRectMake(0, 0, aSize.width, aSize.height); + UIBezierPath *roundedRect = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:cornerRadius]; + roundedRect.lineWidth = 0; + UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0.0f); + [color setFill]; + [roundedRect fill]; + //[roundedRect stroke]; + //[roundedRect addClip]; + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + return [image resizableImageWithCapInsets:UIEdgeInsetsMake(cornerRadius, cornerRadius, cornerRadius, cornerRadius)]; +} + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface WYPopoverBackgroundInnerView : UIView + +@property (nonatomic, strong) UIColor *innerStrokeColor; + +@property (nonatomic, strong) UIColor *gradientTopColor; +@property (nonatomic, strong) UIColor *gradientBottomColor; +@property (nonatomic, assign) CGFloat gradientHeight; +@property (nonatomic, assign) CGFloat gradientTopPosition; + +@property (nonatomic, strong) UIColor *innerShadowColor; +@property (nonatomic, assign) CGSize innerShadowOffset; +@property (nonatomic, assign) CGFloat innerShadowBlurRadius; +@property (nonatomic, assign) CGFloat innerCornerRadius; + +@property (nonatomic, assign) CGFloat navigationBarHeight; +@property (nonatomic, assign) BOOL wantsDefaultContentAppearance; +@property (nonatomic, assign) CGFloat borderWidth; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +#pragma mark +#pragma mark - WYPopoverInnerView + +@implementation WYPopoverBackgroundInnerView + +@synthesize innerStrokeColor; + +@synthesize gradientTopColor; +@synthesize gradientBottomColor; +@synthesize gradientHeight; +@synthesize gradientTopPosition; + +@synthesize innerShadowColor; +@synthesize innerShadowOffset; +@synthesize innerShadowBlurRadius; +@synthesize innerCornerRadius; + +@synthesize navigationBarHeight; +@synthesize wantsDefaultContentAppearance; +@synthesize borderWidth; + +- (id)initWithFrame:(CGRect)frame +{ + self = [super initWithFrame:frame]; + if (self) + { + self.backgroundColor = [UIColor clearColor]; + self.userInteractionEnabled = NO; + } + return self; +} + +- (void)drawRect:(CGRect)rect +{ + CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); + CGContextRef context = UIGraphicsGetCurrentContext(); + + //// Gradient Declarations + NSArray* fillGradientColors = [NSArray arrayWithObjects: + (id)gradientTopColor.CGColor, + (id)gradientBottomColor.CGColor, nil]; + CGFloat fillGradientLocations[] = {0, 1}; + CGGradientRef fillGradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef)fillGradientColors, fillGradientLocations); + + //// innerRect Drawing + CGFloat barHeight = (wantsDefaultContentAppearance == NO) ? navigationBarHeight : 0; + CGFloat cornerRadius = (wantsDefaultContentAppearance == NO) ? innerCornerRadius : 0; + + CGRect innerRect = CGRectMake(CGRectGetMinX(rect), CGRectGetMinY(rect) + barHeight, CGRectGetWidth(rect) , CGRectGetHeight(rect) - barHeight); + + UIBezierPath* rectPath = [UIBezierPath bezierPathWithRect:innerRect]; + + UIBezierPath* roundedRectPath = [UIBezierPath bezierPathWithRoundedRect:innerRect cornerRadius:cornerRadius + 1]; + + if (wantsDefaultContentAppearance == NO && borderWidth > 0) + { + CGContextSaveGState(context); + { + [rectPath appendPath:roundedRectPath]; + rectPath.usesEvenOddFillRule = YES; + [rectPath addClip]; + + CGContextDrawLinearGradient(context, fillGradient, + CGPointMake(0, -gradientTopPosition), + CGPointMake(0, -gradientTopPosition + gradientHeight), + 0); + } + CGContextRestoreGState(context); + } + + CGContextSaveGState(context); + { + if (wantsDefaultContentAppearance == NO && borderWidth > 0) + { + [roundedRectPath addClip]; + CGContextSetShadowWithColor(context, innerShadowOffset, innerShadowBlurRadius, innerShadowColor.CGColor); + } + + UIBezierPath* inRoundedRectPath = [UIBezierPath bezierPathWithRoundedRect:CGRectInset(innerRect, 0.5, 0.5) cornerRadius:cornerRadius]; + + if (borderWidth == 0) + { + inRoundedRectPath = [UIBezierPath bezierPathWithRoundedRect:CGRectInset(innerRect, 0.5, 0.5) byRoundingCorners:UIRectCornerBottomLeft|UIRectCornerBottomRight cornerRadii:CGSizeMake(cornerRadius, cornerRadius)]; + } + + [self.innerStrokeColor setStroke]; + inRoundedRectPath.lineWidth = 1; + [inRoundedRectPath stroke]; + } + + CGContextRestoreGState(context); + + CGGradientRelease(fillGradient); + CGColorSpaceRelease(colorSpace); +} + +- (void)dealloc +{ + innerShadowColor = nil; + innerStrokeColor = nil; + gradientTopColor = nil; + gradientBottomColor = nil; +} + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +@protocol WYPopoverOverlayViewDelegate; + +@interface WYPopoverOverlayView : UIView +{ + BOOL _isAccessible; +} + +@property(nonatomic, assign) id delegate; +@property(nonatomic, assign) BOOL testHits; +@property(nonatomic, unsafe_unretained) NSArray *passthroughViews; + +@end + + +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +#pragma mark +#pragma mark - WYPopoverOverlayViewDelegate + +@protocol WYPopoverOverlayViewDelegate + +@optional +//- (void)popoverOverlayView:(WYPopoverOverlayView *)overlayView didTouchAtPoint:(CGPoint)point; +- (void)popoverOverlayViewDidTouch:(WYPopoverOverlayView *)overlayView; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +#pragma mark +#pragma mark - WYPopoverOverlayView + +@implementation WYPopoverOverlayView + +- (id)initWithFrame:(CGRect)aFrame +{ + self = [super initWithFrame:aFrame]; + if (self) + { + self.autoresizesSubviews = NO; + self.accessibilityTraits = UIAccessibilityTraitNone; + } + return self; +} + +- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event +{ + //UITouch *oneTouch = [touches anyObject]; + + //if ([self.delegate respondsToSelector:@selector(popoverOverlayView:didTouchAtPoint:)]) + //{ + // [self.delegate popoverOverlayView:self didTouchAtPoint:[oneTouch locationInView:self]]; + //} + + if ([self.delegate respondsToSelector:@selector(popoverOverlayViewDidTouch:)]) + { + [self.delegate popoverOverlayViewDidTouch:self]; + } +} + +- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event +{ + if (self.testHits) + { + return NO; + } + + UIView *view = [super hitTest:point withEvent:event]; + + if (view == self) + { + self.testHits = YES; + UIView *superHitView = [self.superview hitTest:point withEvent:event]; + self.testHits = NO; + + if ([self isPassthroughView:superHitView]) + { + return superHitView; + } + } + + return view; +} + +- (BOOL)isPassthroughView:(UIView *)view +{ + if (view == nil) + { + return NO; + } + + if ([self.passthroughViews containsObject:view]) + { + return YES; + } + + return [self isPassthroughView:view.superview]; +} + +#pragma mark - UIAccessibility + +- (void)accessibilityElementDidBecomeFocused { + self.accessibilityLabel = NSLocalizedString(@"Double-tap to dismiss pop-up window.", nil); +} + +- (void)accessibilityElementDidLoseFocus { + +} + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +#pragma mark +#pragma mark - WYPopoverBackgroundViewDelegate + +@protocol WYPopoverBackgroundViewDelegate + +@optional +- (void)popoverBackgroundViewDidTouchOutside:(WYPopoverBackgroundView *)backgroundView; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface WYPopoverBackgroundView () +{ + WYPopoverBackgroundInnerView *innerView; + CGSize contentSize; +} + +@property(nonatomic, assign) id delegate; + +@property (nonatomic, assign) WYPopoverArrowDirection arrowDirection; + +@property (nonatomic, strong, readonly) UIView *contentView; +@property (nonatomic, assign, readonly) CGFloat navigationBarHeight; +@property (nonatomic, assign, readonly) UIEdgeInsets outerShadowInsets; +@property (nonatomic, assign) CGFloat arrowOffset; +@property (nonatomic, assign) BOOL wantsDefaultContentAppearance; + +- (void)setViewController:(UIViewController *)viewController; + +- (CGRect)outerRect; +- (CGRect)innerRect; +- (CGRect)arrowRect; + +- (CGRect)outerRect:(CGRect)rect arrowDirection:(WYPopoverArrowDirection)aArrowDirection; +- (CGRect)innerRect:(CGRect)rect arrowDirection:(WYPopoverArrowDirection)aArrowDirection; +- (CGRect)arrowRect:(CGRect)rect arrowDirection:(WYPopoverArrowDirection)aArrowDirection; + +- (id)initWithContentSize:(CGSize)contentSize; + +- (BOOL)isTouchedAtPoint:(CGPoint)point; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +#pragma mark +#pragma mark - WYPopoverBackgroundView + +@implementation WYPopoverBackgroundView + +@synthesize tintColor; + +@synthesize fillTopColor; +@synthesize fillBottomColor; +@synthesize glossShadowColor; +@synthesize glossShadowOffset; +@synthesize glossShadowBlurRadius; +@synthesize borderWidth; +@synthesize arrowBase; +@synthesize arrowHeight; +@synthesize outerShadowColor; +@synthesize outerStrokeColor; +@synthesize outerShadowBlurRadius; +@synthesize outerShadowOffset; +@synthesize outerCornerRadius; +@synthesize minOuterCornerRadius; +@synthesize innerShadowColor; +@synthesize innerStrokeColor; +@synthesize innerShadowBlurRadius; +@synthesize innerShadowOffset; +@synthesize innerCornerRadius; +@synthesize viewContentInsets; + +@synthesize arrowDirection; +@synthesize contentView; +@synthesize arrowOffset; +@synthesize navigationBarHeight; +@synthesize wantsDefaultContentAppearance; + +@synthesize outerShadowInsets; + +- (id)initWithContentSize:(CGSize)aContentSize +{ + self = [super initWithFrame:CGRectMake(0, 0, aContentSize.width, aContentSize.height)]; + + if (self != nil) + { + contentSize = aContentSize; + + self.autoresizesSubviews = NO; + self.backgroundColor = [UIColor clearColor]; + + self.arrowDirection = WYPopoverArrowDirectionDown; + self.arrowOffset = 0; + + self.layer.name = @"parent"; + + if (WY_IS_IOS_GREATER_THAN_OR_EQUAL_TO(@"6.0")) + { + self.layer.drawsAsynchronously = YES; + } + + self.layer.contentsScale = [UIScreen mainScreen].scale; + //self.layer.edgeAntialiasingMask = kCALayerLeftEdge | kCALayerRightEdge | kCALayerBottomEdge | kCALayerTopEdge; + self.layer.delegate = self; + } + + return self; +} + +- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event +{ + UITouch *oneTouch = [touches anyObject]; + + if ([self isTouchedAtPoint:[oneTouch locationInView:self]] == NO) + { + if ([self.delegate respondsToSelector:@selector(popoverBackgroundViewDidTouchOutside:)]) + { + [self.delegate popoverBackgroundViewDidTouchOutside:self]; + } + } +} + +- (UIEdgeInsets)outerShadowInsets +{ + UIEdgeInsets result = UIEdgeInsetsMake(outerShadowBlurRadius, outerShadowBlurRadius, outerShadowBlurRadius, outerShadowBlurRadius); + + result.top -= self.outerShadowOffset.height; + result.bottom += self.outerShadowOffset.height; + result.left -= self.outerShadowOffset.width; + result.right += self.outerShadowOffset.width; + + return result; +} + +- (void)setArrowOffset:(CGFloat)value +{ + CGFloat coef = 1; + + if (value != 0) + { + coef = value / ABS(value); + + value = ABS(value); + + CGRect outerRect = [self outerRect]; + + CGFloat delta = self.arrowBase / 2. + .5; + + delta += MIN(minOuterCornerRadius, outerCornerRadius); + + outerRect = CGRectInset(outerRect, delta, delta); + + if (arrowDirection == WYPopoverArrowDirectionUp || arrowDirection == WYPopoverArrowDirectionDown) + { + value += coef * self.outerShadowOffset.width; + value = MIN(value, CGRectGetWidth(outerRect) / 2); + } + + if (arrowDirection == WYPopoverArrowDirectionLeft || arrowDirection == WYPopoverArrowDirectionRight) + { + value += coef * self.outerShadowOffset.height; + value = MIN(value, CGRectGetHeight(outerRect) / 2); + } + } + else + { + if (arrowDirection == WYPopoverArrowDirectionUp || arrowDirection == WYPopoverArrowDirectionDown) + { + value += self.outerShadowOffset.width; + } + + if (arrowDirection == WYPopoverArrowDirectionLeft || arrowDirection == WYPopoverArrowDirectionRight) + { + value += self.outerShadowOffset.height; + } + } + + arrowOffset = value * coef; +} + +- (void)setViewController:(UIViewController *)viewController +{ + contentView = viewController.view; + + contentView.frame = CGRectIntegral(CGRectMake(0, 0, self.bounds.size.width, 100)); + + [self addSubview:contentView]; + + navigationBarHeight = 0; + + if ([viewController isKindOfClass:[UINavigationController class]]) + { + UINavigationController* navigationController = (UINavigationController*)viewController; + navigationBarHeight = navigationController.navigationBar.bounds.size.height; + } + + contentView.frame = CGRectIntegral([self innerRect]); + + if (innerView == nil) + { + innerView = [[WYPopoverBackgroundInnerView alloc] initWithFrame:contentView.frame]; + innerView.userInteractionEnabled = NO; + + innerView.gradientTopColor = self.fillTopColor; + innerView.gradientBottomColor = self.fillBottomColor; + innerView.innerShadowColor = innerShadowColor; + innerView.innerStrokeColor = self.innerStrokeColor; + innerView.innerShadowOffset = innerShadowOffset; + innerView.innerCornerRadius = self.innerCornerRadius; + innerView.innerShadowBlurRadius = innerShadowBlurRadius; + innerView.borderWidth = self.borderWidth; + } + + innerView.navigationBarHeight = navigationBarHeight; + innerView.gradientHeight = self.frame.size.height - 2 * outerShadowBlurRadius; + innerView.gradientTopPosition = contentView.frame.origin.y - self.outerShadowInsets.top; + innerView.wantsDefaultContentAppearance = wantsDefaultContentAppearance; + + [self insertSubview:innerView aboveSubview:contentView]; + + innerView.frame = CGRectIntegral(contentView.frame); + + [self.layer setNeedsDisplay]; +} + +- (CGSize)sizeThatFits:(CGSize)size +{ + CGSize result = size; + + result.width += 2 * (borderWidth + outerShadowBlurRadius); + result.height += borderWidth + 2 * outerShadowBlurRadius; + + if (navigationBarHeight == 0) + { + result.height += borderWidth; + } + + if (arrowDirection == WYPopoverArrowDirectionUp || arrowDirection == WYPopoverArrowDirectionDown) + { + result.height += arrowHeight; + } + + if (arrowDirection == WYPopoverArrowDirectionLeft || arrowDirection == WYPopoverArrowDirectionRight) + { + result.width += arrowHeight; + } + + return result; +} + +- (void)sizeToFit +{ + CGSize size = [self sizeThatFits:contentSize]; + self.bounds = CGRectMake(0, 0, size.width, size.height); +} + +#pragma mark Drawing + +- (void)setNeedsDisplay +{ + [super setNeedsDisplay]; + + [self.layer setNeedsDisplay]; + + if (innerView) + { + innerView.gradientTopColor = self.fillTopColor; + innerView.gradientBottomColor = self.fillBottomColor; + innerView.innerShadowColor = innerShadowColor; + innerView.innerStrokeColor = self.innerStrokeColor; + innerView.innerShadowOffset = innerShadowOffset; + innerView.innerCornerRadius = self.innerCornerRadius; + innerView.innerShadowBlurRadius = innerShadowBlurRadius; + innerView.borderWidth = self.borderWidth; + + innerView.navigationBarHeight = navigationBarHeight; + innerView.gradientHeight = self.frame.size.height - 2 * outerShadowBlurRadius; + innerView.gradientTopPosition = contentView.frame.origin.y - self.outerShadowInsets.top; + innerView.wantsDefaultContentAppearance = wantsDefaultContentAppearance; + + [innerView setNeedsDisplay]; + } +} + +#pragma mark CALayerDelegate + +- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)context +{ + if ([layer.name isEqualToString:@"parent"]) + { + UIGraphicsPushContext(context); + //CGContextSetShouldAntialias(context, YES); + //CGContextSetAllowsAntialiasing(context, YES); + + //// General Declarations + CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); + + //// Gradient Declarations + NSArray* fillGradientColors = [NSArray arrayWithObjects: + (id)self.fillTopColor.CGColor, + (id)self.fillBottomColor.CGColor, nil]; + CGFloat fillGradientLocations[] = {0, 1}; + CGGradientRef fillGradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef)fillGradientColors, fillGradientLocations); + + // Frames + CGRect rect = self.bounds; + + CGRect outerRect = [self outerRect:rect arrowDirection:self.arrowDirection]; + outerRect = CGRectInset(outerRect, 0.5, 0.5); + + // Inner Path + CGMutablePathRef outerPathRef = CGPathCreateMutable(); + + CGPoint origin = CGPointZero; + + CGFloat reducedOuterCornerRadius = 0; + + if (arrowDirection == WYPopoverArrowDirectionUp || arrowDirection == WYPopoverArrowDirectionDown) + { + if (arrowOffset >= 0) + { + reducedOuterCornerRadius = CGRectGetMaxX(outerRect) - (CGRectGetMidX(outerRect) + arrowOffset + arrowBase / 2); + } + else + { + reducedOuterCornerRadius = (CGRectGetMidX(outerRect) + arrowOffset - arrowBase / 2) - CGRectGetMinX(outerRect); + } + } + else if (arrowDirection == WYPopoverArrowDirectionLeft || arrowDirection == WYPopoverArrowDirectionRight) + { + if (arrowOffset >= 0) + { + reducedOuterCornerRadius = CGRectGetMaxY(outerRect) - (CGRectGetMidY(outerRect) + arrowOffset + arrowBase / 2); + } + else + { + reducedOuterCornerRadius = (CGRectGetMidY(outerRect) + arrowOffset - arrowBase / 2) - CGRectGetMinY(outerRect); + } + } + + reducedOuterCornerRadius = MIN(reducedOuterCornerRadius, outerCornerRadius); + + if (arrowDirection == WYPopoverArrowDirectionUp) + { + origin = CGPointMake(CGRectGetMidX(outerRect) + arrowOffset - arrowBase / 2, CGRectGetMinY(outerRect)); + + CGPathMoveToPoint(outerPathRef, NULL, origin.x, origin.y); + + CGPathAddLineToPoint(outerPathRef, NULL, CGRectGetMidX(outerRect) + arrowOffset, CGRectGetMinY(outerRect) - arrowHeight); + CGPathAddLineToPoint(outerPathRef, NULL, CGRectGetMidX(outerRect) + arrowOffset + arrowBase / 2, CGRectGetMinY(outerRect)); + + CGPathAddArcToPoint(outerPathRef, NULL, CGRectGetMaxX(outerRect), CGRectGetMinY(outerRect), CGRectGetMaxX(outerRect), CGRectGetMaxY(outerRect), (arrowOffset >= 0) ? reducedOuterCornerRadius : outerCornerRadius); + CGPathAddArcToPoint(outerPathRef, NULL, CGRectGetMaxX(outerRect), CGRectGetMaxY(outerRect), CGRectGetMinX(outerRect), CGRectGetMaxY(outerRect), outerCornerRadius); + CGPathAddArcToPoint(outerPathRef, NULL, CGRectGetMinX(outerRect), CGRectGetMaxY(outerRect), CGRectGetMinX(outerRect), CGRectGetMinY(outerRect), outerCornerRadius); + CGPathAddArcToPoint(outerPathRef, NULL, CGRectGetMinX(outerRect), CGRectGetMinY(outerRect), CGRectGetMaxX(outerRect), CGRectGetMinY(outerRect), (arrowOffset < 0) ? reducedOuterCornerRadius : outerCornerRadius); + + CGPathAddLineToPoint(outerPathRef, NULL, origin.x, origin.y); + } + + if (arrowDirection == WYPopoverArrowDirectionDown) + { + origin = CGPointMake(CGRectGetMidX(outerRect) + arrowOffset + arrowBase / 2, CGRectGetMaxY(outerRect)); + + CGPathMoveToPoint(outerPathRef, NULL, origin.x, origin.y); + + CGPathAddLineToPoint(outerPathRef, NULL, CGRectGetMidX(outerRect) + arrowOffset, CGRectGetMaxY(outerRect) + arrowHeight); + CGPathAddLineToPoint(outerPathRef, NULL, CGRectGetMidX(outerRect) + arrowOffset - arrowBase / 2, CGRectGetMaxY(outerRect)); + + CGPathAddArcToPoint(outerPathRef, NULL, CGRectGetMinX(outerRect), CGRectGetMaxY(outerRect), CGRectGetMinX(outerRect), CGRectGetMinY(outerRect), (arrowOffset < 0) ? reducedOuterCornerRadius : outerCornerRadius); + CGPathAddArcToPoint(outerPathRef, NULL, CGRectGetMinX(outerRect), CGRectGetMinY(outerRect), CGRectGetMaxX(outerRect), CGRectGetMinY(outerRect), outerCornerRadius); + CGPathAddArcToPoint(outerPathRef, NULL, CGRectGetMaxX(outerRect), CGRectGetMinY(outerRect), CGRectGetMaxX(outerRect), CGRectGetMaxY(outerRect), outerCornerRadius); + CGPathAddArcToPoint(outerPathRef, NULL, CGRectGetMaxX(outerRect), CGRectGetMaxY(outerRect), CGRectGetMinX(outerRect), CGRectGetMaxY(outerRect), (arrowOffset >= 0) ? reducedOuterCornerRadius : outerCornerRadius); + + CGPathAddLineToPoint(outerPathRef, NULL, origin.x, origin.y); + } + + if (arrowDirection == WYPopoverArrowDirectionLeft) + { + origin = CGPointMake(CGRectGetMinX(outerRect), CGRectGetMidY(outerRect) + arrowOffset + arrowBase / 2); + + CGPathMoveToPoint(outerPathRef, NULL, origin.x, origin.y); + + CGPathAddLineToPoint(outerPathRef, NULL, CGRectGetMinX(outerRect) - arrowHeight, CGRectGetMidY(outerRect) + arrowOffset); + CGPathAddLineToPoint(outerPathRef, NULL, CGRectGetMinX(outerRect), CGRectGetMidY(outerRect) + arrowOffset - arrowBase / 2); + + CGPathAddArcToPoint(outerPathRef, NULL, CGRectGetMinX(outerRect), CGRectGetMinY(outerRect), CGRectGetMaxX(outerRect), CGRectGetMinY(outerRect), (arrowOffset < 0) ? reducedOuterCornerRadius : outerCornerRadius); + CGPathAddArcToPoint(outerPathRef, NULL, CGRectGetMaxX(outerRect), CGRectGetMinY(outerRect), CGRectGetMaxX(outerRect), CGRectGetMaxY(outerRect), outerCornerRadius); + CGPathAddArcToPoint(outerPathRef, NULL, CGRectGetMaxX(outerRect), CGRectGetMaxY(outerRect), CGRectGetMinX(outerRect), CGRectGetMaxY(outerRect), outerCornerRadius); + CGPathAddArcToPoint(outerPathRef, NULL, CGRectGetMinX(outerRect), CGRectGetMaxY(outerRect), CGRectGetMinX(outerRect), CGRectGetMinY(outerRect), (arrowOffset >= 0) ? reducedOuterCornerRadius : outerCornerRadius); + + CGPathAddLineToPoint(outerPathRef, NULL, origin.x, origin.y); + } + + if (arrowDirection == WYPopoverArrowDirectionRight) + { + origin = CGPointMake(CGRectGetMaxX(outerRect), CGRectGetMidY(outerRect) + arrowOffset - arrowBase / 2); + + CGPathMoveToPoint(outerPathRef, NULL, origin.x, origin.y); + + CGPathAddLineToPoint(outerPathRef, NULL, CGRectGetMaxX(outerRect) + arrowHeight, CGRectGetMidY(outerRect) + arrowOffset); + CGPathAddLineToPoint(outerPathRef, NULL, CGRectGetMaxX(outerRect), CGRectGetMidY(outerRect) + arrowOffset + arrowBase / 2); + + CGPathAddArcToPoint(outerPathRef, NULL, CGRectGetMaxX(outerRect), CGRectGetMaxY(outerRect), CGRectGetMinX(outerRect), CGRectGetMaxY(outerRect), (arrowOffset >= 0) ? reducedOuterCornerRadius : outerCornerRadius); + CGPathAddArcToPoint(outerPathRef, NULL, CGRectGetMinX(outerRect), CGRectGetMaxY(outerRect), CGRectGetMinX(outerRect), CGRectGetMinY(outerRect), outerCornerRadius); + CGPathAddArcToPoint(outerPathRef, NULL, CGRectGetMinX(outerRect), CGRectGetMinY(outerRect), CGRectGetMaxX(outerRect), CGRectGetMinY(outerRect), outerCornerRadius); + CGPathAddArcToPoint(outerPathRef, NULL, CGRectGetMaxX(outerRect), CGRectGetMinY(outerRect), CGRectGetMaxX(outerRect), CGRectGetMaxY(outerRect), (arrowOffset < 0) ? reducedOuterCornerRadius : outerCornerRadius); + + CGPathAddLineToPoint(outerPathRef, NULL, origin.x, origin.y); + } + + if (arrowDirection == WYPopoverArrowDirectionNone) + { + origin = CGPointMake(CGRectGetMaxX(outerRect), CGRectGetMidY(outerRect)); + + CGPathMoveToPoint(outerPathRef, NULL, origin.x, origin.y); + + CGPathAddLineToPoint(outerPathRef, NULL, CGRectGetMaxX(outerRect), CGRectGetMidY(outerRect)); + CGPathAddLineToPoint(outerPathRef, NULL, CGRectGetMaxX(outerRect), CGRectGetMidY(outerRect)); + + CGPathAddArcToPoint(outerPathRef, NULL, CGRectGetMaxX(outerRect), CGRectGetMaxY(outerRect), CGRectGetMinX(outerRect), CGRectGetMaxY(outerRect), outerCornerRadius); + CGPathAddArcToPoint(outerPathRef, NULL, CGRectGetMinX(outerRect), CGRectGetMaxY(outerRect), CGRectGetMinX(outerRect), CGRectGetMinY(outerRect), outerCornerRadius); + CGPathAddArcToPoint(outerPathRef, NULL, CGRectGetMinX(outerRect), CGRectGetMinY(outerRect), CGRectGetMaxX(outerRect), CGRectGetMinY(outerRect), outerCornerRadius); + CGPathAddArcToPoint(outerPathRef, NULL, CGRectGetMaxX(outerRect), CGRectGetMinY(outerRect), CGRectGetMaxX(outerRect), CGRectGetMaxY(outerRect), outerCornerRadius); + + CGPathAddLineToPoint(outerPathRef, NULL, origin.x, origin.y); + } + + CGPathCloseSubpath(outerPathRef); + + UIBezierPath* outerRectPath = [UIBezierPath bezierPathWithCGPath:outerPathRef]; + + CGContextSaveGState(context); + { + CGContextSetShadowWithColor(context, self.outerShadowOffset, outerShadowBlurRadius, outerShadowColor.CGColor); + CGContextBeginTransparencyLayer(context, NULL); + [outerRectPath addClip]; + CGRect outerRectBounds = CGPathGetPathBoundingBox(outerRectPath.CGPath); + CGContextDrawLinearGradient(context, fillGradient, + CGPointMake(CGRectGetMidX(outerRectBounds), CGRectGetMinY(outerRectBounds)), + CGPointMake(CGRectGetMidX(outerRectBounds), CGRectGetMaxY(outerRectBounds)), + 0); + CGContextEndTransparencyLayer(context); + } + CGContextRestoreGState(context); + + ////// outerRect Inner Shadow + CGRect outerRectBorderRect = CGRectInset([outerRectPath bounds], -glossShadowBlurRadius, -glossShadowBlurRadius); + outerRectBorderRect = CGRectOffset(outerRectBorderRect, -glossShadowOffset.width, -glossShadowOffset.height); + outerRectBorderRect = CGRectInset(CGRectUnion(outerRectBorderRect, [outerRectPath bounds]), -1, -1); + + UIBezierPath* outerRectNegativePath = [UIBezierPath bezierPathWithRect: outerRectBorderRect]; + [outerRectNegativePath appendPath: outerRectPath]; + outerRectNegativePath.usesEvenOddFillRule = YES; + + CGContextSaveGState(context); + { + CGFloat xOffset = glossShadowOffset.width + round(outerRectBorderRect.size.width); + CGFloat yOffset = glossShadowOffset.height; + CGContextSetShadowWithColor(context, + CGSizeMake(xOffset + copysign(0.1, xOffset), yOffset + copysign(0.1, yOffset)), + glossShadowBlurRadius, + self.glossShadowColor.CGColor); + + [outerRectPath addClip]; + CGAffineTransform transform = CGAffineTransformMakeTranslation(-round(outerRectBorderRect.size.width), 0); + [outerRectNegativePath applyTransform: transform]; + [[UIColor grayColor] setFill]; + [outerRectNegativePath fill]; + } + CGContextRestoreGState(context); + + [self.outerStrokeColor setStroke]; + outerRectPath.lineWidth = 1; + [outerRectPath stroke]; + + //// Cleanup + CFRelease(outerPathRef); + CGGradientRelease(fillGradient); + CGColorSpaceRelease(colorSpace); + + UIGraphicsPopContext(); + } +} + +#pragma mark Private + +- (CGRect)outerRect +{ + return [self outerRect:self.bounds arrowDirection:self.arrowDirection]; +} + +- (CGRect)innerRect +{ + return [self innerRect:self.bounds arrowDirection:self.arrowDirection]; +} + +- (CGRect)arrowRect +{ + return [self arrowRect:self.bounds arrowDirection:self.arrowDirection]; +} + +- (CGRect)outerRect:(CGRect)rect arrowDirection:(WYPopoverArrowDirection)aArrowDirection +{ + CGRect result = rect; + + if (aArrowDirection == WYPopoverArrowDirectionUp || arrowDirection == WYPopoverArrowDirectionDown) + { + result.size.height -= arrowHeight; + + if (aArrowDirection == WYPopoverArrowDirectionUp) + { + result = CGRectOffset(result, 0, arrowHeight); + } + } + + if (aArrowDirection == WYPopoverArrowDirectionLeft || arrowDirection == WYPopoverArrowDirectionRight) + { + result.size.width -= arrowHeight; + + if (aArrowDirection == WYPopoverArrowDirectionLeft) + { + result = CGRectOffset(result, arrowHeight, 0); + } + } + + result = CGRectInset(result, outerShadowBlurRadius, outerShadowBlurRadius); + result.origin.x -= self.outerShadowOffset.width; + result.origin.y -= self.outerShadowOffset.height; + + return result; +} + +- (CGRect)innerRect:(CGRect)rect arrowDirection:(WYPopoverArrowDirection)aArrowDirection +{ + CGRect result = [self outerRect:rect arrowDirection:aArrowDirection]; + + result.origin.x += borderWidth; + result.origin.y += 0; + result.size.width -= 2 * borderWidth; + result.size.height -= borderWidth; + + if (navigationBarHeight == 0 || wantsDefaultContentAppearance) + { + result.origin.y += borderWidth; + result.size.height -= borderWidth; + } + + result.origin.x += viewContentInsets.left; + result.origin.y += viewContentInsets.top; + result.size.width = result.size.width - viewContentInsets.left - viewContentInsets.right; + result.size.height = result.size.height - viewContentInsets.top - viewContentInsets.bottom; + + if (borderWidth > 0) + { + result = CGRectInset(result, -1, -1); + } + + return result; +} + +- (CGRect)arrowRect:(CGRect)rect arrowDirection:(WYPopoverArrowDirection)aArrowDirection +{ + CGRect result = CGRectZero; + + if (arrowHeight > 0) + { + result.size = CGSizeMake(arrowBase, arrowHeight); + + if (aArrowDirection == WYPopoverArrowDirectionLeft || arrowDirection == WYPopoverArrowDirectionRight) + { + result.size = CGSizeMake(arrowHeight, arrowBase); + } + + CGRect outerRect = [self outerRect:rect arrowDirection:aArrowDirection]; + + if (aArrowDirection == WYPopoverArrowDirectionDown) + { + result.origin.x = CGRectGetMidX(outerRect) - result.size.width / 2 + arrowOffset; + result.origin.y = CGRectGetMaxY(outerRect); + } + + if (aArrowDirection == WYPopoverArrowDirectionUp) + { + result.origin.x = CGRectGetMidX(outerRect) - result.size.width / 2 + arrowOffset; + result.origin.y = CGRectGetMinY(outerRect) - result.size.height; + } + + if (aArrowDirection == WYPopoverArrowDirectionRight) + { + result.origin.x = CGRectGetMaxX(outerRect); + result.origin.y = CGRectGetMidY(outerRect) - result.size.height / 2 + arrowOffset; + } + + if (aArrowDirection == WYPopoverArrowDirectionLeft) + { + result.origin.x = CGRectGetMinX(outerRect) - result.size.width; + result.origin.y = CGRectGetMidY(outerRect) - result.size.height / 2 + arrowOffset; + } + } + + return result; +} + +- (BOOL)isTouchedAtPoint:(CGPoint)point +{ + BOOL result = NO; + + CGRect outerRect = [self outerRect]; + CGRect arrowRect = [self arrowRect]; + + result = (CGRectContainsPoint(outerRect, point) || CGRectContainsPoint(arrowRect, point)); + + return result; +} + +#pragma mark Memory Management + +- (void)dealloc +{ + contentView = nil; + innerView = nil; + tintColor = nil; + outerStrokeColor = nil; + innerStrokeColor = nil; + fillTopColor = nil; + fillBottomColor = nil; + glossShadowColor = nil; + outerShadowColor = nil; + innerShadowColor = nil; +} + +@end + +//////////////////////////////////////////////////////////////////////////// + +@interface WYPopoverController () +{ + UIViewController *viewController; + CGRect rect; + UIView *inView; + WYPopoverOverlayView *overlayView; + WYPopoverBackgroundView *backgroundView; + WYPopoverArrowDirection permittedArrowDirections; + BOOL animated; + BOOL isListeningNotifications; + BOOL isInterfaceOrientationChanging; + __weak UIBarButtonItem *barButtonItem; + CGRect keyboardRect; + + WYPopoverAnimationOptions options; + + BOOL themeUpdatesEnabled; + BOOL themeIsUpdating; +} + +- (void)dismissPopoverAnimated:(BOOL)aAnimated + options:(WYPopoverAnimationOptions)aAptions + completion:(void (^)(void))aCompletion + callDelegate:(BOOL)aCallDelegate; + +- (WYPopoverArrowDirection)arrowDirectionForRect:(CGRect)aRect + inView:(UIView*)aView + contentSize:(CGSize)aContentSize + arrowHeight:(CGFloat)aArrowHeight + permittedArrowDirections:(WYPopoverArrowDirection)aArrowDirections; + +- (CGSize)sizeForRect:(CGRect)aRect + inView:(UIView *)aView + arrowHeight:(CGFloat)aArrowHeight + arrowDirection:(WYPopoverArrowDirection)aArrowDirection; + +- (void)registerTheme; +- (void)unregisterTheme; +- (void)updateThemeUI; + +- (CGSize)topViewControllerContentSize; + +@end + +//////////////////////////////////////////////////////////////////////////// + +#pragma mark +#pragma mark - WYPopoverController + +@implementation WYPopoverController + +@synthesize delegate; +@synthesize passthroughViews; +@synthesize wantsDefaultContentAppearance; +@synthesize popoverVisible; +@synthesize popoverLayoutMargins; +@synthesize popoverContentSize = popoverContentSize_; +@synthesize animationDuration; +@synthesize theme; + +static WYPopoverTheme *defaultTheme_ = nil; + ++ (void)setDefaultTheme:(WYPopoverTheme *)aTheme +{ + defaultTheme_ = aTheme; + + @autoreleasepool { + WYPopoverBackgroundView *appearance = [WYPopoverBackgroundView appearance]; + appearance.tintColor = aTheme.tintColor; + appearance.outerStrokeColor = aTheme.outerStrokeColor; + appearance.innerStrokeColor = aTheme.innerStrokeColor; + appearance.fillTopColor = aTheme.fillTopColor; + appearance.fillBottomColor = aTheme.fillBottomColor; + appearance.glossShadowColor = aTheme.glossShadowColor; + appearance.glossShadowOffset = aTheme.glossShadowOffset; + appearance.glossShadowBlurRadius = aTheme.glossShadowBlurRadius; + appearance.borderWidth = aTheme.borderWidth; + appearance.arrowBase = aTheme.arrowBase; + appearance.arrowHeight = aTheme.arrowHeight; + appearance.outerShadowColor = aTheme.outerShadowColor; + appearance.outerShadowBlurRadius = aTheme.outerShadowBlurRadius; + appearance.outerShadowOffset = aTheme.outerShadowOffset; + appearance.outerCornerRadius = aTheme.outerCornerRadius; + appearance.minOuterCornerRadius = aTheme.minOuterCornerRadius; + appearance.innerShadowColor = aTheme.innerShadowColor; + appearance.innerShadowBlurRadius = aTheme.innerShadowBlurRadius; + appearance.innerShadowOffset = aTheme.innerShadowOffset; + appearance.innerCornerRadius = aTheme.innerCornerRadius; + appearance.viewContentInsets = aTheme.viewContentInsets; + appearance.overlayColor = aTheme.overlayColor; + } +} + ++ (WYPopoverTheme *)defaultTheme +{ + return defaultTheme_; +} + ++ (void)initialize +{ + [WYPopoverController setDefaultTheme:[WYPopoverTheme theme]]; +} + +- (id)init +{ + self = [super init]; + + if (self) + { + popoverLayoutMargins = UIEdgeInsetsMake(10, 10, 10, 10); + keyboardRect = CGRectZero; + animationDuration = WY_POPOVER_DEFAULT_ANIMATION_DURATION; + + themeUpdatesEnabled = NO; + + [self setTheme:[WYPopoverController defaultTheme]]; + + themeIsUpdating = YES; + + WYPopoverBackgroundView *appearance = [WYPopoverBackgroundView appearance]; + theme.tintColor = appearance.tintColor; + theme.outerStrokeColor = appearance.outerStrokeColor; + theme.innerStrokeColor = appearance.innerStrokeColor; + theme.fillTopColor = appearance.fillTopColor; + theme.fillBottomColor = appearance.fillBottomColor; + theme.glossShadowColor = appearance.glossShadowColor; + theme.glossShadowOffset = appearance.glossShadowOffset; + theme.glossShadowBlurRadius = appearance.glossShadowBlurRadius; + theme.borderWidth = appearance.borderWidth; + theme.arrowBase = appearance.arrowBase; + theme.arrowHeight = appearance.arrowHeight; + theme.outerShadowColor = appearance.outerShadowColor; + theme.outerShadowBlurRadius = appearance.outerShadowBlurRadius; + theme.outerShadowOffset = appearance.outerShadowOffset; + theme.outerCornerRadius = appearance.outerCornerRadius; + theme.minOuterCornerRadius = appearance.minOuterCornerRadius; + theme.innerShadowColor = appearance.innerShadowColor; + theme.innerShadowBlurRadius = appearance.innerShadowBlurRadius; + theme.innerShadowOffset = appearance.innerShadowOffset; + theme.innerCornerRadius = appearance.innerCornerRadius; + theme.viewContentInsets = appearance.viewContentInsets; + theme.overlayColor = appearance.overlayColor; + + themeIsUpdating = NO; + themeUpdatesEnabled = YES; + + popoverContentSize_ = CGSizeZero; + } + + return self; +} + +- (id)initWithContentViewController:(UIViewController *)aViewController +{ + self = [self init]; + + if (self) + { + viewController = aViewController; + } + + return self; +} + +- (void)setTheme:(WYPopoverTheme *)value +{ + [self unregisterTheme]; + theme = value; + [self registerTheme]; + [self updateThemeUI]; + + themeIsUpdating = NO; +} + +- (void)registerTheme +{ + if (theme == nil) return; + + NSArray *keypaths = [theme observableKeypaths]; + for (NSString *keypath in keypaths) { + [theme addObserver:self forKeyPath:keypath options:NSKeyValueObservingOptionNew context:NULL]; + } +} + +- (void)unregisterTheme +{ + if (theme == nil) return; + + @try { + NSArray *keypaths = [theme observableKeypaths]; + for (NSString *keypath in keypaths) { + [theme removeObserver:self forKeyPath:keypath]; + } + } + @catch (NSException * __unused exception) {} +} + +- (void)updateThemeUI +{ + if (theme == nil || themeUpdatesEnabled == NO || themeIsUpdating == YES) return; + + if (backgroundView != nil) { + backgroundView.tintColor = theme.tintColor; + backgroundView.outerStrokeColor = theme.outerStrokeColor; + backgroundView.innerStrokeColor = theme.innerStrokeColor; + backgroundView.fillTopColor = theme.fillTopColor; + backgroundView.fillBottomColor = theme.fillBottomColor; + backgroundView.glossShadowColor = theme.glossShadowColor; + backgroundView.glossShadowOffset = theme.glossShadowOffset; + backgroundView.glossShadowBlurRadius = theme.glossShadowBlurRadius; + backgroundView.borderWidth = theme.borderWidth; + backgroundView.arrowBase = theme.arrowBase; + backgroundView.arrowHeight = theme.arrowHeight; + backgroundView.outerShadowColor = theme.outerShadowColor; + backgroundView.outerShadowBlurRadius = theme.outerShadowBlurRadius; + backgroundView.outerShadowOffset = theme.outerShadowOffset; + backgroundView.outerCornerRadius = theme.outerCornerRadius; + backgroundView.minOuterCornerRadius = theme.minOuterCornerRadius; + backgroundView.innerShadowColor = theme.innerShadowColor; + backgroundView.innerShadowBlurRadius = theme.innerShadowBlurRadius; + backgroundView.innerShadowOffset = theme.innerShadowOffset; + backgroundView.innerCornerRadius = theme.innerCornerRadius; + backgroundView.viewContentInsets = theme.viewContentInsets; + [backgroundView setNeedsDisplay]; + } + + if (overlayView != nil) { + overlayView.backgroundColor = theme.overlayColor; + } + + [self positionPopover:NO]; + + [self setPopoverNavigationBarBackgroundImage]; +} + +- (void)beginThemeUpdates +{ + themeIsUpdating = YES; +} + +- (void)endThemeUpdates +{ + themeIsUpdating = NO; + [self updateThemeUI]; +} + +- (BOOL)isPopoverVisible +{ + BOOL result = (overlayView != nil); + return result; +} + +- (UIViewController *)contentViewController +{ + return viewController; +} + +- (CGSize)topViewControllerContentSize +{ + CGSize result = CGSizeZero; + + UIViewController *topViewController = viewController; + + if ([viewController isKindOfClass:[UINavigationController class]] == YES) + { + UINavigationController *navigationController = (UINavigationController *)viewController; + topViewController = [navigationController topViewController]; + } + +#ifdef WY_BASE_SDK_7_ENABLED + if ([topViewController respondsToSelector:@selector(preferredContentSize)]) + { + result = topViewController.preferredContentSize; + } +#endif + + if (CGSizeEqualToSize(result, CGSizeZero)) + { +#pragma clang diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated" + result = topViewController.contentSizeForViewInPopover; +#pragma clang diagnostic pop + } + + if (CGSizeEqualToSize(result, CGSizeZero)) + { + CGSize windowSize = [[UIApplication sharedApplication] keyWindow].bounds.size; + + UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation]; + + result = CGSizeMake(320, UIDeviceOrientationIsLandscape(orientation) ? windowSize.width : windowSize.height); + } + + return result; +} + +- (CGSize)popoverContentSize +{ + CGSize result = popoverContentSize_; + + if (CGSizeEqualToSize(result, CGSizeZero)) + { + result = [self topViewControllerContentSize]; + } + + return result; +} + +- (void)setPopoverContentSize:(CGSize)size +{ + popoverContentSize_ = size; + [self positionPopover:YES]; +} + +- (void)presentPopoverFromRect:(CGRect)aRect + inView:(UIView *)aView + permittedArrowDirections:(WYPopoverArrowDirection)aArrowDirections + animated:(BOOL)aAnimated +{ + [self presentPopoverFromRect:aRect + inView:aView + permittedArrowDirections:aArrowDirections + animated:aAnimated + completion:nil]; +} + +- (void)presentPopoverFromRect:(CGRect)aRect + inView:(UIView *)aView + permittedArrowDirections:(WYPopoverArrowDirection)aArrowDirections + animated:(BOOL)aAnimated + completion:(void (^)(void))completion +{ + [self presentPopoverFromRect:aRect + inView:aView + permittedArrowDirections:aArrowDirections + animated:aAnimated + options:WYPopoverAnimationOptionFade + completion:completion]; +} + +- (void)presentPopoverFromRect:(CGRect)aRect + inView:(UIView *)aView + permittedArrowDirections:(WYPopoverArrowDirection)aArrowDirections + animated:(BOOL)aAnimated + options:(WYPopoverAnimationOptions)aOptions +{ + [self presentPopoverFromRect:aRect + inView:aView + permittedArrowDirections:aArrowDirections + animated:aAnimated + options:aOptions + completion:nil]; +} + +- (void)presentPopoverFromRect:(CGRect)aRect + inView:(UIView *)aView + permittedArrowDirections:(WYPopoverArrowDirection)aArrowDirections + animated:(BOOL)aAnimated + options:(WYPopoverAnimationOptions)aOptions + completion:(void (^)(void))completion +{ + NSAssert((aArrowDirections != WYPopoverArrowDirectionUnknown), @"WYPopoverArrowDirection must not be UNKNOWN"); + + rect = aRect; + inView = aView; + permittedArrowDirections = aArrowDirections; + animated = aAnimated; + options = aOptions; + + CGSize contentViewSize = self.popoverContentSize; + + if (overlayView == nil) + { + overlayView = [[WYPopoverOverlayView alloc] initWithFrame:inView.window.bounds]; + overlayView.delegate = self; + overlayView.userInteractionEnabled = YES; + overlayView.passthroughViews = passthroughViews; + + backgroundView = [[WYPopoverBackgroundView alloc] initWithContentSize:contentViewSize]; + backgroundView.delegate = self; + backgroundView.hidden = YES; + backgroundView.accessibilityViewIsModal = YES; + + [inView.window addSubview:backgroundView]; + [inView.window insertSubview:overlayView belowSubview:backgroundView]; + } + + [self updateThemeUI]; + + __weak __typeof__(self) weakSelf = self; + + void (^completionBlock)(BOOL) = ^(BOOL animated) { + + __typeof__(self) strongSelf = weakSelf; + + if (strongSelf) + { + if ([strongSelf->viewController isKindOfClass:[UINavigationController class]] == NO) + { + [strongSelf->viewController viewDidAppear:YES]; + } + + strongSelf->backgroundView.accessibilityViewIsModal = NO; + + if ([strongSelf->viewController respondsToSelector:@selector(preferredContentSize)]) + { + [strongSelf->viewController addObserver:self forKeyPath:NSStringFromSelector(@selector(preferredContentSize)) options:0 context:nil]; + } + else + { + [strongSelf->viewController addObserver:self forKeyPath:NSStringFromSelector(@selector(contentSizeForViewInPopover)) options:0 context:nil]; + } + } + + if (completion) + { + completion(); + } + else if (strongSelf && strongSelf->delegate && [strongSelf->delegate respondsToSelector:@selector(popoverControllerDidPresentPopover:)]) + { + [strongSelf->delegate popoverControllerDidPresentPopover:strongSelf]; + } + + + }; + +#ifdef WY_BASE_SDK_7_ENABLED + if ([inView.window respondsToSelector:@selector(setTintAdjustmentMode:)]) { + for (UIView *subview in inView.window.subviews) { + if (subview != backgroundView) { + [subview setTintAdjustmentMode:UIViewTintAdjustmentModeDimmed]; + } + } + } +#endif + + backgroundView.hidden = NO; + + if (animated) + { + if ((options & WYPopoverAnimationOptionFade) == WYPopoverAnimationOptionFade) + { + overlayView.alpha = 0; + backgroundView.alpha = 0; + } + + [viewController viewWillAppear:YES]; + + CGAffineTransform endTransform = backgroundView.transform; + + if ((options & WYPopoverAnimationOptionScale) == WYPopoverAnimationOptionScale) + { + CGAffineTransform startTransform = [self transformForArrowDirection:backgroundView.arrowDirection]; + backgroundView.transform = startTransform; + } + + [UIView animateWithDuration:animationDuration animations:^{ + __typeof__(self) strongSelf = weakSelf; + + if (strongSelf) + { + strongSelf->overlayView.alpha = 1; + strongSelf->backgroundView.alpha = 1; + strongSelf->backgroundView.transform = endTransform; + } + } completion:^(BOOL finished) { + completionBlock(YES); + }]; + } + else + { + [viewController viewWillAppear:NO]; + completionBlock(NO); + } + + if (isListeningNotifications == NO) + { + isListeningNotifications = YES; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(didChangeStatusBarOrientation:) + name:UIApplicationDidChangeStatusBarOrientationNotification + object:nil]; + + [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(didChangeDeviceOrientation:) + name:UIDeviceOrientationDidChangeNotification + object:nil]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(keyboardWillShow:) + name:UIKeyboardWillShowNotification object:nil]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(keyboardWillHide:) + name:UIKeyboardWillHideNotification object:nil]; + } + + overlayView.isAccessibilityElement = YES; +} + +- (void)presentPopoverFromBarButtonItem:(UIBarButtonItem *)aItem + permittedArrowDirections:(WYPopoverArrowDirection)aArrowDirections + animated:(BOOL)aAnimated +{ + [self presentPopoverFromBarButtonItem:aItem + permittedArrowDirections:aArrowDirections + animated:aAnimated + completion:nil]; +} + +- (void)presentPopoverFromBarButtonItem:(UIBarButtonItem *)aItem + permittedArrowDirections:(WYPopoverArrowDirection)aArrowDirections + animated:(BOOL)aAnimated + completion:(void (^)(void))completion +{ + [self presentPopoverFromBarButtonItem:aItem + permittedArrowDirections:aArrowDirections + animated:aAnimated + options:WYPopoverAnimationOptionFade + completion:completion]; +} + +- (void)presentPopoverFromBarButtonItem:(UIBarButtonItem *)aItem + permittedArrowDirections:(WYPopoverArrowDirection)aArrowDirections + animated:(BOOL)aAnimated + options:(WYPopoverAnimationOptions)aOptions +{ + [self presentPopoverFromBarButtonItem:aItem + permittedArrowDirections:aArrowDirections + animated:aAnimated + options:aOptions + completion:nil]; +} + +- (void)presentPopoverFromBarButtonItem:(UIBarButtonItem *)aItem + permittedArrowDirections:(WYPopoverArrowDirection)aArrowDirections + animated:(BOOL)aAnimated + options:(WYPopoverAnimationOptions)aOptions + completion:(void (^)(void))completion +{ + barButtonItem = aItem; + UIView *itemView = [barButtonItem valueForKey:@"view"]; + aArrowDirections = WYPopoverArrowDirectionDown | WYPopoverArrowDirectionUp; + [self presentPopoverFromRect:itemView.bounds + inView:itemView + permittedArrowDirections:aArrowDirections + animated:aAnimated + options:aOptions + completion:completion]; +} + +- (void)presentPopoverAsDialogAnimated:(BOOL)aAnimated +{ + [self presentPopoverAsDialogAnimated:aAnimated + completion:nil]; +} + +- (void)presentPopoverAsDialogAnimated:(BOOL)aAnimated + completion:(void (^)(void))completion +{ + [self presentPopoverAsDialogAnimated:aAnimated + options:WYPopoverAnimationOptionFade + completion:completion]; +} + +- (void)presentPopoverAsDialogAnimated:(BOOL)aAnimated + options:(WYPopoverAnimationOptions)aOptions +{ + [self presentPopoverAsDialogAnimated:aAnimated + options:aOptions + completion:nil]; +} + +- (void)presentPopoverAsDialogAnimated:(BOOL)aAnimated + options:(WYPopoverAnimationOptions)aOptions + completion:(void (^)(void))completion +{ + [self presentPopoverFromRect:CGRectZero + inView:nil + permittedArrowDirections:WYPopoverArrowDirectionNone + animated:aAnimated + options:aOptions + completion:completion]; +} + +- (CGAffineTransform)transformForArrowDirection:(WYPopoverArrowDirection)arrowDirection +{ + CGAffineTransform transform = backgroundView.transform; + + UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation]; + + CGSize containerViewSize = backgroundView.frame.size; + + if (backgroundView.arrowHeight > 0) + { + if (UIDeviceOrientationIsLandscape(orientation)) { + containerViewSize.width = backgroundView.frame.size.height; + containerViewSize.height = backgroundView.frame.size.width; + } + + //WY_LOG(@"containerView.arrowOffset = %f", containerView.arrowOffset); + //WY_LOG(@"containerViewSize = %@", NSStringFromCGSize(containerViewSize)); + //WY_LOG(@"orientation = %@", WYStringFromOrientation(orientation)); + + if (arrowDirection == WYPopoverArrowDirectionDown) + { + transform = CGAffineTransformTranslate(transform, backgroundView.arrowOffset, containerViewSize.height / 2); + } + + if (arrowDirection == WYPopoverArrowDirectionUp) + { + transform = CGAffineTransformTranslate(transform, backgroundView.arrowOffset, -containerViewSize.height / 2); + } + + if (arrowDirection == WYPopoverArrowDirectionRight) + { + transform = CGAffineTransformTranslate(transform, containerViewSize.width / 2, backgroundView.arrowOffset); + } + + if (arrowDirection == WYPopoverArrowDirectionLeft) + { + transform = CGAffineTransformTranslate(transform, -containerViewSize.width / 2, backgroundView.arrowOffset); + } + } + + transform = CGAffineTransformScale(transform, 0.01, 0.01); + + return transform; +} + +- (void)setPopoverNavigationBarBackgroundImage +{ + if ([viewController isKindOfClass:[UINavigationController class]] == YES) + { + UINavigationController *navigationController = (UINavigationController *)viewController; + navigationController.embedInPopover = YES; + +#ifdef WY_BASE_SDK_7_ENABLED + if ([navigationController respondsToSelector:@selector(setEdgesForExtendedLayout:)]) + { + UIViewController *topViewController = [navigationController topViewController]; + [topViewController setEdgesForExtendedLayout:UIRectEdgeNone]; + } +#endif + + if (wantsDefaultContentAppearance == NO) + { + [navigationController.navigationBar setBackgroundImage:[UIImage imageWithColor:[UIColor clearColor]] forBarMetrics:UIBarMetricsDefault]; + } + } + + viewController.view.clipsToBounds = YES; + + if (backgroundView.borderWidth == 0) + { + viewController.view.layer.cornerRadius = backgroundView.outerCornerRadius; + } +} + +- (void)positionPopover:(BOOL)aAnimated +{ + CGRect savedContainerFrame = backgroundView.frame; + + UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation]; + + CGSize contentViewSize = self.popoverContentSize; + CGSize minContainerSize = WY_POPOVER_MIN_SIZE; + + CGRect viewFrame; + CGRect containerFrame = CGRectZero; + CGFloat minX, maxX, minY, maxY, offset = 0; + CGSize containerViewSize = CGSizeZero; + + CGFloat overlayWidth = UIInterfaceOrientationIsPortrait(orientation) ? overlayView.bounds.size.width : overlayView.bounds.size.height; + CGFloat overlayHeight = UIInterfaceOrientationIsPortrait(orientation) ? overlayView.bounds.size.height : overlayView.bounds.size.width; + + WYPopoverArrowDirection arrowDirection = permittedArrowDirections; + + overlayView.bounds = inView.window.bounds; + backgroundView.transform = CGAffineTransformIdentity; + + viewFrame = [inView convertRect:rect toView:nil]; + + viewFrame = WYRectInWindowBounds(viewFrame, orientation); + + minX = popoverLayoutMargins.left; + maxX = overlayWidth - popoverLayoutMargins.right; + minY = WYStatusBarHeight() + popoverLayoutMargins.top; + maxY = overlayHeight - popoverLayoutMargins.bottom; + + // Which direction ? + // + arrowDirection = [self arrowDirectionForRect:rect + inView:inView + contentSize:contentViewSize + arrowHeight:backgroundView.arrowHeight + permittedArrowDirections:arrowDirection]; + + // Position of the popover + // + CGFloat keyboardHeight = UIInterfaceOrientationIsPortrait(orientation) ? keyboardRect.size.height : keyboardRect.size.width; + + if (delegate && [delegate respondsToSelector:@selector(popoverControllerShouldIgnoreKeyboardBounds:)]) { + BOOL shouldIgnore = [delegate popoverControllerShouldIgnoreKeyboardBounds:self]; + + if (shouldIgnore) { + keyboardHeight = 0; + } + } + + minX -= backgroundView.outerShadowInsets.left; + maxX += backgroundView.outerShadowInsets.right; + minY -= backgroundView.outerShadowInsets.top; + maxY += backgroundView.outerShadowInsets.bottom - keyboardHeight; + + if (arrowDirection == WYPopoverArrowDirectionDown) + { + backgroundView.arrowDirection = WYPopoverArrowDirectionDown; + containerViewSize = [backgroundView sizeThatFits:contentViewSize]; + + containerFrame = CGRectZero; + containerFrame.size = containerViewSize; + containerFrame.size.width = MIN(maxX - minX, containerFrame.size.width); + containerFrame.size.height = MIN(maxY - minY, containerFrame.size.height); + + backgroundView.frame = CGRectIntegral(containerFrame); + + backgroundView.center = CGPointMake(viewFrame.origin.x + viewFrame.size.width / 2, viewFrame.origin.y + viewFrame.size.height / 2); + + containerFrame = backgroundView.frame; + + offset = 0; + + if (containerFrame.origin.x < minX) + { + offset = minX - containerFrame.origin.x; + containerFrame.origin.x = minX; + offset = -offset; + } + else if (containerFrame.origin.x + containerFrame.size.width > maxX) + { + offset = (backgroundView.frame.origin.x + backgroundView.frame.size.width) - maxX; + containerFrame.origin.x -= offset; + } + + backgroundView.arrowOffset = offset; + offset = backgroundView.frame.size.height / 2 + viewFrame.size.height / 2 - backgroundView.outerShadowInsets.bottom; + + containerFrame.origin.y -= offset; + + if (containerFrame.origin.y < minY) + { + offset = minY - containerFrame.origin.y; + containerFrame.size.height -= offset; + + if (containerFrame.size.height < minContainerSize.height) + { + // popover is overflowing + offset -= (minContainerSize.height - containerFrame.size.height); + containerFrame.size.height = minContainerSize.height; + } + + containerFrame.origin.y += offset; + } + } + + if (arrowDirection == WYPopoverArrowDirectionUp) + { + backgroundView.arrowDirection = WYPopoverArrowDirectionUp; + containerViewSize = [backgroundView sizeThatFits:contentViewSize]; + + containerFrame = CGRectZero; + containerFrame.size = containerViewSize; + containerFrame.size.width = MIN(maxX - minX, containerFrame.size.width); + containerFrame.size.height = MIN(maxY - minY, containerFrame.size.height); + + backgroundView.frame = containerFrame; + + backgroundView.center = CGPointMake(viewFrame.origin.x + viewFrame.size.width / 2, viewFrame.origin.y + viewFrame.size.height / 2); + + containerFrame = backgroundView.frame; + + offset = 0; + + if (containerFrame.origin.x < minX) + { + offset = minX - containerFrame.origin.x; + containerFrame.origin.x = minX; + offset = -offset; + } + else if (containerFrame.origin.x + containerFrame.size.width > maxX) + { + offset = (backgroundView.frame.origin.x + backgroundView.frame.size.width) - maxX; + containerFrame.origin.x -= offset; + } + + backgroundView.arrowOffset = offset; + offset = backgroundView.frame.size.height / 2 + viewFrame.size.height / 2 - backgroundView.outerShadowInsets.top; + + containerFrame.origin.y += offset; + + if (containerFrame.origin.y + containerFrame.size.height > maxY) + { + offset = (containerFrame.origin.y + containerFrame.size.height) - maxY; + containerFrame.size.height -= offset; + + if (containerFrame.size.height < minContainerSize.height) + { + // popover is overflowing + containerFrame.size.height = minContainerSize.height; + } + } + } + + if (arrowDirection == WYPopoverArrowDirectionRight) + { + backgroundView.arrowDirection = WYPopoverArrowDirectionRight; + containerViewSize = [backgroundView sizeThatFits:contentViewSize]; + + containerFrame = CGRectZero; + containerFrame.size = containerViewSize; + containerFrame.size.width = MIN(maxX - minX, containerFrame.size.width); + containerFrame.size.height = MIN(maxY - minY, containerFrame.size.height); + + backgroundView.frame = CGRectIntegral(containerFrame); + + backgroundView.center = CGPointMake(viewFrame.origin.x + viewFrame.size.width / 2, viewFrame.origin.y + viewFrame.size.height / 2); + + containerFrame = backgroundView.frame; + + offset = backgroundView.frame.size.width / 2 + viewFrame.size.width / 2 - backgroundView.outerShadowInsets.right; + + containerFrame.origin.x -= offset; + + if (containerFrame.origin.x < minX) + { + offset = minX - containerFrame.origin.x; + containerFrame.size.width -= offset; + + if (containerFrame.size.width < minContainerSize.width) + { + // popover is overflowing + offset -= (minContainerSize.width - containerFrame.size.width); + containerFrame.size.width = minContainerSize.width; + } + + containerFrame.origin.x += offset; + } + + offset = 0; + + if (containerFrame.origin.y < minY) + { + offset = minY - containerFrame.origin.y; + containerFrame.origin.y = minY; + offset = -offset; + } + else if (containerFrame.origin.y + containerFrame.size.height > maxY) + { + offset = (backgroundView.frame.origin.y + backgroundView.frame.size.height) - maxY; + containerFrame.origin.y -= offset; + } + + backgroundView.arrowOffset = offset; + } + + if (arrowDirection == WYPopoverArrowDirectionLeft) + { + backgroundView.arrowDirection = WYPopoverArrowDirectionLeft; + containerViewSize = [backgroundView sizeThatFits:contentViewSize]; + + containerFrame = CGRectZero; + containerFrame.size = containerViewSize; + containerFrame.size.width = MIN(maxX - minX, containerFrame.size.width); + containerFrame.size.height = MIN(maxY - minY, containerFrame.size.height); + backgroundView.frame = containerFrame; + + backgroundView.center = CGPointMake(viewFrame.origin.x + viewFrame.size.width / 2, viewFrame.origin.y + viewFrame.size.height / 2); + + containerFrame = CGRectIntegral(backgroundView.frame); + + offset = backgroundView.frame.size.width / 2 + viewFrame.size.width / 2 - backgroundView.outerShadowInsets.left; + + containerFrame.origin.x += offset; + + if (containerFrame.origin.x + containerFrame.size.width > maxX) + { + offset = (containerFrame.origin.x + containerFrame.size.width) - maxX; + containerFrame.size.width -= offset; + + if (containerFrame.size.width < minContainerSize.width) + { + // popover is overflowing + containerFrame.size.width = minContainerSize.width; + } + } + + offset = 0; + + if (containerFrame.origin.y < minY) + { + offset = minY - containerFrame.origin.y; + containerFrame.origin.y = minY; + offset = -offset; + } + else if (containerFrame.origin.y + containerFrame.size.height > maxY) + { + offset = (backgroundView.frame.origin.y + backgroundView.frame.size.height) - maxY; + containerFrame.origin.y -= offset; + } + + backgroundView.arrowOffset = offset; + } + + if (arrowDirection == WYPopoverArrowDirectionNone) + { + backgroundView.arrowDirection = WYPopoverArrowDirectionNone; + containerViewSize = [backgroundView sizeThatFits:contentViewSize]; + + containerFrame = CGRectZero; + containerFrame.size = containerViewSize; + containerFrame.size.width = MIN(maxX - minX, containerFrame.size.width); + containerFrame.size.height = MIN(maxY - minY, containerFrame.size.height); + backgroundView.frame = CGRectIntegral(containerFrame); + + backgroundView.center = CGPointMake(minX + (maxX - minX) / 2, minY + (maxY - minY) / 2); + + containerFrame = backgroundView.frame; + + backgroundView.arrowOffset = offset; + } + + containerFrame = CGRectIntegral(containerFrame); + + backgroundView.frame = containerFrame; + + backgroundView.wantsDefaultContentAppearance = wantsDefaultContentAppearance; + + [backgroundView setViewController:viewController]; + + // keyboard support + // + if (keyboardHeight > 0) { + + CGFloat keyboardY = UIInterfaceOrientationIsPortrait(orientation) ? keyboardRect.origin.y : keyboardRect.origin.x; + + CGFloat yOffset = containerFrame.origin.y + containerFrame.size.height - keyboardY; + + if (yOffset > 0) { + + if (containerFrame.origin.y - yOffset < minY) { + yOffset -= minY - (containerFrame.origin.y - yOffset); + } + + if ([delegate respondsToSelector:@selector(popoverController:willTranslatePopoverWithYOffset:)]) + { + [delegate popoverController:self willTranslatePopoverWithYOffset:&yOffset]; + } + + containerFrame.origin.y -= yOffset; + } + } + + CGPoint containerOrigin = containerFrame.origin; + + backgroundView.transform = CGAffineTransformMakeRotation(WYInterfaceOrientationAngleOfOrientation(orientation)); + + containerFrame = backgroundView.frame; + + containerFrame.origin = WYPointRelativeToOrientation(containerOrigin, containerFrame.size, orientation); + + if (aAnimated == YES) { + backgroundView.frame = savedContainerFrame; + __weak __typeof__(self) weakSelf = self; + [UIView animateWithDuration:0.10f animations:^{ + __typeof__(self) strongSelf = weakSelf; + strongSelf->backgroundView.frame = containerFrame; + }]; + } else { + backgroundView.frame = containerFrame; + } + + WY_LOG(@"popoverContainerView.frame = %@", NSStringFromCGRect(backgroundView.frame)); +} + +- (void)dismissPopoverAnimated:(BOOL)aAnimated +{ + [self dismissPopoverAnimated:aAnimated + options:options + completion:nil]; +} + +- (void)dismissPopoverAnimated:(BOOL)aAnimated + completion:(void (^)(void))completion +{ + [self dismissPopoverAnimated:aAnimated + options:options + completion:completion]; +} + +- (void)dismissPopoverAnimated:(BOOL)aAnimated + options:(WYPopoverAnimationOptions)aOptions +{ + [self dismissPopoverAnimated:aAnimated + options:aOptions + completion:nil]; +} + +- (void)dismissPopoverAnimated:(BOOL)aAnimated + options:(WYPopoverAnimationOptions)aOptions + completion:(void (^)(void))completion +{ + [self dismissPopoverAnimated:aAnimated + options:aOptions + completion:completion + callDelegate:NO]; +} + +- (void)dismissPopoverAnimated:(BOOL)aAnimated + options:(WYPopoverAnimationOptions)aOptions + completion:(void (^)(void))completion + callDelegate:(BOOL)callDelegate +{ + CGFloat duration = self.animationDuration; + WYPopoverAnimationOptions style = aOptions; + + __weak __typeof__(self) weakSelf = self; + + void (^afterCompletionBlock)() = ^() { + +#ifdef WY_BASE_SDK_7_ENABLED + if ([inView.window respondsToSelector:@selector(setTintAdjustmentMode:)]) { + for (UIView *subview in inView.window.subviews) { + if (subview != backgroundView) { + [subview setTintAdjustmentMode:UIViewTintAdjustmentModeAutomatic]; + } + } + } +#endif + + __typeof__(self) strongSelf = weakSelf; + + if (strongSelf) + { + strongSelf->backgroundView = nil; + + [strongSelf->overlayView removeFromSuperview]; + strongSelf->overlayView = nil; + + if ([strongSelf->viewController isKindOfClass:[UINavigationController class]] == NO) + { + [strongSelf->viewController viewDidDisappear:aAnimated]; + } + + if (completion) + { + completion(); + } + else if (callDelegate) + { + if (strongSelf->delegate && [strongSelf->delegate respondsToSelector:@selector(popoverControllerDidDismissPopover:)]) + { + [strongSelf->delegate popoverControllerDidDismissPopover:strongSelf]; + } + } + } + }; + + void (^completionBlock)() = ^() { + + __typeof__(self) strongSelf = weakSelf; + [strongSelf->backgroundView removeFromSuperview]; + + if (aAnimated) + { + [UIView animateWithDuration:duration animations:^{ + __typeof__(self) strongSelf = weakSelf; + + if (strongSelf) + { + strongSelf->overlayView.alpha = 0; + } + } completion:^(BOOL finished) { + afterCompletionBlock(); + }]; + } + else + { + afterCompletionBlock(); + } + }; + + if (isListeningNotifications == YES) + { + isListeningNotifications = NO; + + [[NSNotificationCenter defaultCenter] removeObserver:self + name:UIApplicationDidChangeStatusBarOrientationNotification + object:nil]; + + [[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications]; + [[NSNotificationCenter defaultCenter] removeObserver:self + name:UIDeviceOrientationDidChangeNotification + object:nil]; + + [[NSNotificationCenter defaultCenter] removeObserver:self + name:UIKeyboardWillShowNotification + object:nil]; + + [[NSNotificationCenter defaultCenter] removeObserver:self + name:UIKeyboardWillHideNotification + object:nil]; + } + + if ([viewController isKindOfClass:[UINavigationController class]] == NO) + { + [viewController viewWillDisappear:aAnimated]; + } + + @try { + if ([viewController respondsToSelector:@selector(preferredContentSize)]) { + [viewController removeObserver:self forKeyPath:NSStringFromSelector(@selector(preferredContentSize))]; + } else { + [viewController removeObserver:self forKeyPath:NSStringFromSelector(@selector(contentSizeForViewInPopover))]; + } + } + @catch (NSException * __unused exception) {} + + if (aAnimated) + { + [UIView animateWithDuration:duration animations:^{ + __typeof__(self) strongSelf = weakSelf; + + if (strongSelf) + { + if ((style & WYPopoverAnimationOptionFade) == WYPopoverAnimationOptionFade) + { + strongSelf->backgroundView.alpha = 0; + } + + if ((style & WYPopoverAnimationOptionScale) == WYPopoverAnimationOptionScale) + { + CGAffineTransform endTransform = [self transformForArrowDirection:strongSelf->backgroundView.arrowDirection]; + strongSelf->backgroundView.transform = endTransform; + } + } + } completion:^(BOOL finished) { + completionBlock(); + }]; + } + else + { + completionBlock(); + } + + overlayView.isAccessibilityElement = NO; +} + +#pragma mark KVO + +- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context +{ + if (object == viewController) + { + if ([keyPath isEqualToString:NSStringFromSelector(@selector(preferredContentSize))] + || [keyPath isEqualToString:NSStringFromSelector(@selector(contentSizeForViewInPopover))]) + { + CGSize contentSize = [self topViewControllerContentSize]; + [self setPopoverContentSize:contentSize]; + } + } + else if (object == theme) + { + [self updateThemeUI]; + } +} + +#pragma mark WYPopoverOverlayViewDelegate + +- (void)popoverOverlayViewDidTouch:(WYPopoverOverlayView *)aOverlayView +{ + //BOOL isTouched = [containerView isTouchedAtPoint:[containerView convertPoint:aPoint fromView:aOverlayView]]; + + //if (!isTouched) + //{ + BOOL shouldDismiss = !viewController.modalInPopover; + + if (shouldDismiss && delegate && [delegate respondsToSelector:@selector(popoverControllerShouldDismissPopover:)]) + { + shouldDismiss = [delegate popoverControllerShouldDismissPopover:self]; + } + + if (shouldDismiss) + { + [self dismissPopoverAnimated:animated options:options completion:nil callDelegate:YES]; + } + //} +} + +#pragma mark WYPopoverBackgroundViewDelegate + +- (void)popoverBackgroundViewDidTouchOutside:(WYPopoverBackgroundView *)aBackgroundView +{ + [self popoverOverlayViewDidTouch:nil]; +} + +#pragma mark Private + +- (WYPopoverArrowDirection)arrowDirectionForRect:(CGRect)aRect + inView:(UIView *)aView + contentSize:(CGSize)contentSize + arrowHeight:(CGFloat)arrowHeight + permittedArrowDirections:(WYPopoverArrowDirection)arrowDirections +{ + WYPopoverArrowDirection arrowDirection = WYPopoverArrowDirectionUnknown; + + NSMutableArray *areas = [NSMutableArray arrayWithCapacity:0]; + WYPopoverArea *area; + + if ((arrowDirections & WYPopoverArrowDirectionDown) == WYPopoverArrowDirectionDown) + { + area = [[WYPopoverArea alloc] init]; + area.areaSize = [self sizeForRect:aRect inView:aView arrowHeight:arrowHeight arrowDirection:WYPopoverArrowDirectionDown]; + area.arrowDirection = WYPopoverArrowDirectionDown; + [areas addObject:area]; + } + + if ((arrowDirections & WYPopoverArrowDirectionUp) == WYPopoverArrowDirectionUp) + { + area = [[WYPopoverArea alloc] init]; + area.areaSize = [self sizeForRect:aRect inView:aView arrowHeight:arrowHeight arrowDirection:WYPopoverArrowDirectionUp]; + area.arrowDirection = WYPopoverArrowDirectionUp; + [areas addObject:area]; + } + + if ((arrowDirections & WYPopoverArrowDirectionLeft) == WYPopoverArrowDirectionLeft) + { + area = [[WYPopoverArea alloc] init]; + area.areaSize = [self sizeForRect:aRect inView:aView arrowHeight:arrowHeight arrowDirection:WYPopoverArrowDirectionLeft]; + area.arrowDirection = WYPopoverArrowDirectionLeft; + [areas addObject:area]; + } + + if ((arrowDirections & WYPopoverArrowDirectionRight) == WYPopoverArrowDirectionRight) + { + area = [[WYPopoverArea alloc] init]; + area.areaSize = [self sizeForRect:aRect inView:aView arrowHeight:arrowHeight arrowDirection:WYPopoverArrowDirectionRight]; + area.arrowDirection = WYPopoverArrowDirectionRight; + [areas addObject:area]; + } + + if ((arrowDirections & WYPopoverArrowDirectionNone) == WYPopoverArrowDirectionNone) + { + area = [[WYPopoverArea alloc] init]; + area.areaSize = [self sizeForRect:aRect inView:aView arrowHeight:arrowHeight arrowDirection:WYPopoverArrowDirectionNone]; + area.arrowDirection = WYPopoverArrowDirectionNone; + [areas addObject:area]; + } + + if ([areas count] > 1) + { + NSIndexSet* indexes = [areas indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) { + WYPopoverArea* popoverArea = (WYPopoverArea*)obj; + + BOOL result = (popoverArea.areaSize.width > 0 && popoverArea.areaSize.height > 0); + + return result; + }]; + + areas = [NSMutableArray arrayWithArray:[areas objectsAtIndexes:indexes]]; + } + + [areas sortUsingComparator:^NSComparisonResult(id obj1, id obj2) { + WYPopoverArea *area1 = (WYPopoverArea *)obj1; + WYPopoverArea *area2 = (WYPopoverArea *)obj2; + + CGFloat val1 = area1.value; + CGFloat val2 = area2.value; + + NSComparisonResult result = NSOrderedSame; + + if (val1 > val2) + { + result = NSOrderedAscending; + } + else if (val1 < val2) + { + result = NSOrderedDescending; + } + + return result; + }]; + + for (NSUInteger i = 0; i < [areas count]; i++) + { + WYPopoverArea *popoverArea = (WYPopoverArea *)[areas objectAtIndex:i]; + + if (popoverArea.areaSize.width >= contentSize.width) + { + arrowDirection = popoverArea.arrowDirection; + break; + } + } + + if (arrowDirection == WYPopoverArrowDirectionUnknown) + { + if ([areas count] > 0) + { + arrowDirection = ((WYPopoverArea *)[areas objectAtIndex:0]).arrowDirection; + } + else + { + if ((arrowDirections & WYPopoverArrowDirectionDown) == WYPopoverArrowDirectionDown) + { + arrowDirection = WYPopoverArrowDirectionDown; + } + else if ((arrowDirections & WYPopoverArrowDirectionUp) == WYPopoverArrowDirectionUp) + { + arrowDirection = WYPopoverArrowDirectionUp; + } + else if ((arrowDirections & WYPopoverArrowDirectionLeft) == WYPopoverArrowDirectionLeft) + { + arrowDirection = WYPopoverArrowDirectionLeft; + } + else + { + arrowDirection = WYPopoverArrowDirectionRight; + } + } + } + + return arrowDirection; +} + +- (CGSize)sizeForRect:(CGRect)aRect + inView:(UIView *)aView + arrowHeight:(CGFloat)arrowHeight + arrowDirection:(WYPopoverArrowDirection)arrowDirection +{ + UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation]; + + CGRect viewFrame = [aView convertRect:aRect toView:nil]; + viewFrame = WYRectInWindowBounds(viewFrame, orientation); + + CGFloat minX, maxX, minY, maxY = 0; + + CGFloat keyboardHeight = UIInterfaceOrientationIsPortrait(orientation) ? keyboardRect.size.height : keyboardRect.size.width; + + if (delegate && [delegate respondsToSelector:@selector(popoverControllerShouldIgnoreKeyboardBounds:)]) { + BOOL shouldIgnore = [delegate popoverControllerShouldIgnoreKeyboardBounds:self]; + + if (shouldIgnore) { + keyboardHeight = 0; + } + } + + CGFloat overlayWidth = UIInterfaceOrientationIsPortrait(orientation) ? overlayView.bounds.size.width : overlayView.bounds.size.height; + + CGFloat overlayHeight = UIInterfaceOrientationIsPortrait(orientation) ? overlayView.bounds.size.height : overlayView.bounds.size.width; + + minX = popoverLayoutMargins.left; + maxX = overlayWidth - popoverLayoutMargins.right; + minY = WYStatusBarHeight() + popoverLayoutMargins.top; + maxY = overlayHeight - popoverLayoutMargins.bottom - keyboardHeight; + + CGSize result = CGSizeZero; + + if (arrowDirection == WYPopoverArrowDirectionLeft) + { + result.width = maxX - (viewFrame.origin.x + viewFrame.size.width); + result.width -= arrowHeight; + result.height = maxY - minY; + } + else if (arrowDirection == WYPopoverArrowDirectionRight) + { + result.width = viewFrame.origin.x - minX; + result.width -= arrowHeight; + result.height = maxY - minY; + } + else if (arrowDirection == WYPopoverArrowDirectionDown) + { + result.width = maxX - minX; + result.height = viewFrame.origin.y - minY; + result.height -= arrowHeight; + } + else if (arrowDirection == WYPopoverArrowDirectionUp) + { + result.width = maxX - minX; + result.height = maxY - (viewFrame.origin.y + viewFrame.size.height); + result.height -= arrowHeight; + } + else if (arrowDirection == WYPopoverArrowDirectionNone) + { + result.width = maxX - minX; + result.height = maxY - minY; + } + + return result; +} + +#pragma mark Inline functions + +static NSString* WYStringFromOrientation(NSInteger orientation) { + NSString *result = @"Unknown"; + + switch (orientation) { + case UIInterfaceOrientationPortrait: + result = @"Portrait"; + break; + case UIInterfaceOrientationPortraitUpsideDown: + result = @"Portrait UpsideDown"; + break; + case UIInterfaceOrientationLandscapeLeft: + result = @"Landscape Left"; + break; + case UIInterfaceOrientationLandscapeRight: + result = @"Landscape Right"; + break; + default: + break; + } + + return result; +} + +static CGFloat WYStatusBarHeight() { + UIInterfaceOrientation orienation = [[UIApplication sharedApplication] statusBarOrientation]; + + CGFloat statusBarHeight = 0; + { + CGRect statusBarFrame = [[UIApplication sharedApplication] statusBarFrame]; + statusBarHeight = statusBarFrame.size.height; + + if (UIDeviceOrientationIsLandscape(orienation)) + { + statusBarHeight = statusBarFrame.size.width; + } + } + + return statusBarHeight; +} + +static CGFloat WYInterfaceOrientationAngleOfOrientation(UIInterfaceOrientation orientation) +{ + CGFloat angle; + + switch (orientation) + { + case UIInterfaceOrientationPortraitUpsideDown: + angle = M_PI; + break; + case UIInterfaceOrientationLandscapeLeft: + angle = -M_PI_2; + break; + case UIInterfaceOrientationLandscapeRight: + angle = M_PI_2; + break; + default: + angle = 0.0; + break; + } + + return angle; +} + +static CGRect WYRectInWindowBounds(CGRect rect, UIInterfaceOrientation orientation) { + + UIWindow *keyWindow = [UIApplication sharedApplication].keyWindow; + + CGFloat windowWidth = keyWindow.bounds.size.width; + CGFloat windowHeight = keyWindow.bounds.size.height; + + CGRect result = rect; + + if (orientation == UIInterfaceOrientationLandscapeRight) { + + result.origin.x = rect.origin.y; + result.origin.y = windowWidth - rect.origin.x - rect.size.width; + result.size.width = rect.size.height; + result.size.height = rect.size.width; + } + + if (orientation == UIInterfaceOrientationLandscapeLeft) { + + result.origin.x = windowHeight - rect.origin.y - rect.size.height; + result.origin.y = rect.origin.x; + result.size.width = rect.size.height; + result.size.height = rect.size.width; + } + + if (orientation == UIInterfaceOrientationPortraitUpsideDown) { + + result.origin.x = windowWidth - rect.origin.x - rect.size.width; + result.origin.y = windowHeight - rect.origin.y - rect.size.height; + } + + return result; +} + +static CGPoint WYPointRelativeToOrientation(CGPoint origin, CGSize size, UIInterfaceOrientation orientation) { + + UIWindow *keyWindow = [UIApplication sharedApplication].keyWindow; + + CGFloat windowWidth = keyWindow.bounds.size.width; + CGFloat windowHeight = keyWindow.bounds.size.height; + + CGPoint result = origin; + + if (orientation == UIInterfaceOrientationLandscapeRight) { + result.x = windowWidth - origin.y - size.width; + result.y = origin.x; + } + + if (orientation == UIInterfaceOrientationLandscapeLeft) { + result.x = origin.y; + result.y = windowHeight - origin.x - size.height; + } + + if (orientation == UIInterfaceOrientationPortraitUpsideDown) { + result.x = windowWidth - origin.x - size.width; + result.y = windowHeight - origin.y - size.height; + } + + return result; +} + +#pragma mark Selectors + +- (void)didChangeStatusBarOrientation:(NSNotification *)notification +{ + isInterfaceOrientationChanging = YES; +} + +- (void)didChangeDeviceOrientation:(NSNotification *)notification +{ + if (isInterfaceOrientationChanging == NO) return; + + isInterfaceOrientationChanging = NO; + + if ([viewController isKindOfClass:[UINavigationController class]]) + { + UINavigationController* navigationController = (UINavigationController*)viewController; + + if (navigationController.navigationBarHidden == NO) + { + navigationController.navigationBarHidden = YES; + navigationController.navigationBarHidden = NO; + } + } + + if (barButtonItem) + { + inView = [barButtonItem valueForKey:@"view"]; + rect = inView.bounds; + } + else if ([delegate respondsToSelector:@selector(popoverController:willRepositionPopoverToRect:inView:)]) + { + CGRect anotherRect; + UIView *anotherInView; + + [delegate popoverController:self willRepositionPopoverToRect:&anotherRect inView:&anotherInView]; + + if (&anotherRect != NULL) + { + rect = anotherRect; + } + + if (&anotherInView != NULL) + { + inView = anotherInView; + } + } + + [self positionPopover:NO]; +} + +- (void)keyboardWillShow:(NSNotification *)notification +{ + NSDictionary *info = [notification userInfo]; + keyboardRect = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue]; + + //UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation]; + //WY_LOG(@"orientation = %@", WYStringFromOrientation(orientation)); + //WY_LOG(@"keyboardRect = %@", NSStringFromCGRect(keyboardRect)); + + BOOL shouldIgnore = NO; + + if (delegate && [delegate respondsToSelector:@selector(popoverControllerShouldIgnoreKeyboardBounds:)]) { + shouldIgnore = [delegate popoverControllerShouldIgnoreKeyboardBounds:self]; + } + + if (shouldIgnore == NO) { + [self positionPopover:YES]; + } +} + +- (void)keyboardWillHide:(NSNotification *)notification +{ + keyboardRect = CGRectZero; + + BOOL shouldIgnore = NO; + + if (delegate && [delegate respondsToSelector:@selector(popoverControllerShouldIgnoreKeyboardBounds:)]) { + shouldIgnore = [delegate popoverControllerShouldIgnoreKeyboardBounds:self]; + } + + if (shouldIgnore == NO) { + [self positionPopover:YES]; + } +} + +#pragma mark Memory management + +- (void)dealloc +{ + [[NSNotificationCenter defaultCenter] removeObserver:self]; + + [backgroundView removeFromSuperview]; + [backgroundView setDelegate:nil]; + + [overlayView removeFromSuperview]; + [overlayView setDelegate:nil]; + + barButtonItem = nil; + passthroughViews = nil; + viewController = nil; + inView = nil; + overlayView = nil; + backgroundView = nil; + + [self unregisterTheme]; + theme = nil; +} + +@end + diff --git a/Pods/WYPopoverController/WYPopoverController/WYStoryboardPopoverSegue.h b/Pods/WYPopoverController/WYPopoverController/WYStoryboardPopoverSegue.h new file mode 100644 index 00000000..3a8f34bc --- /dev/null +++ b/Pods/WYPopoverController/WYPopoverController/WYStoryboardPopoverSegue.h @@ -0,0 +1,40 @@ +/* + Version 0.2.2 + + WYPopoverController is available under the MIT license. + + Copyright © 2013 Nicolas CHENG + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#import +#import "WYPopoverController.h" + +@interface WYStoryboardPopoverSegue : UIStoryboardSegue + +- (WYPopoverController*)popoverControllerWithSender:(id)sender + permittedArrowDirections:(WYPopoverArrowDirection)arrowDirections + animated:(BOOL)animated; + +- (WYPopoverController*)popoverControllerWithSender:(id)sender + permittedArrowDirections:(WYPopoverArrowDirection)arrowDirections + animated:(BOOL)animated + options:(WYPopoverAnimationOptions)options; + +@end \ No newline at end of file diff --git a/Pods/WYPopoverController/WYPopoverController/WYStoryboardPopoverSegue.m b/Pods/WYPopoverController/WYPopoverController/WYStoryboardPopoverSegue.m new file mode 100644 index 00000000..b8963cfb --- /dev/null +++ b/Pods/WYPopoverController/WYPopoverController/WYStoryboardPopoverSegue.m @@ -0,0 +1,97 @@ +/* + Version 0.2.2 + + WYPopoverController is available under the MIT license. + + Copyright © 2013 Nicolas CHENG + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#import "WYStoryboardPopoverSegue.h" + + +//////////////////////////////////////////////////////////////////////////// + +@interface WYStoryboardPopoverSegue() +{ + WYPopoverController *popoverController; + id sender; + WYPopoverArrowDirection arrowDirections; + WYPopoverAnimationOptions options; + BOOL animated; +} + +@end + +//////////////////////////////////////////////////////////////////////////// + +@implementation WYStoryboardPopoverSegue + +- (void)perform +{ + if ([sender isKindOfClass:[UIBarButtonItem class]]) + { + [popoverController presentPopoverFromBarButtonItem:(UIBarButtonItem*)sender + permittedArrowDirections:arrowDirections + animated:animated + options:options]; + } + else + { + UIView *view = (UIView *)sender; + [popoverController presentPopoverFromRect:view.bounds + inView:view + permittedArrowDirections:arrowDirections + animated:animated + options:options]; + } +} + +- (WYPopoverController *)popoverControllerWithSender:(id)aSender + permittedArrowDirections:(WYPopoverArrowDirection)aArrowDirections + animated:(BOOL)aAnimated +{ + return [self popoverControllerWithSender:aSender + permittedArrowDirections:aArrowDirections + animated:aAnimated + options:WYPopoverAnimationOptionFade]; +} + +- (WYPopoverController *)popoverControllerWithSender:(id)aSender + permittedArrowDirections:(WYPopoverArrowDirection)aArrowDirections + animated:(BOOL)aAnimated + options:(WYPopoverAnimationOptions)aOptions +{ + sender = aSender; + arrowDirections = aArrowDirections; + animated = aAnimated; + options = aOptions; + + popoverController = [[WYPopoverController alloc] initWithContentViewController:self.destinationViewController]; + + return popoverController; +} + +- (void)dealloc +{ + sender = nil; + popoverController = nil; +} + +@end diff --git a/Pods/XMLDictionary/LICENCE.md b/Pods/XMLDictionary/LICENCE.md new file mode 100755 index 00000000..470fa8e7 --- /dev/null +++ b/Pods/XMLDictionary/LICENCE.md @@ -0,0 +1,19 @@ +XMLDictionary + +Copyright (C) 2011 Charcoal Design + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. \ No newline at end of file diff --git a/Pods/XMLDictionary/README.md b/Pods/XMLDictionary/README.md new file mode 100755 index 00000000..7635658b --- /dev/null +++ b/Pods/XMLDictionary/README.md @@ -0,0 +1,239 @@ +Purpose +-------------- + +XMLDictionary is a class designed to simplify parsing and generating of XML on iOS and Mac OS. XMLDictionary is built on top of the NSXMLParser classes, but behaves more like a DOM-style parser rather than SAX parser, in that it creates a tree of objects rather than generating events at the start and end of each node. + +Unlike other DOM parsers, XMLDictionary does not attempt to replicate all of the nuances of the XML standard such as the ability to nest tags within text. If you need to represent something like an HTML document then XMLDictionary won't work for you. If you want to use XML as a data interchange format for passing nested data structures then XMLDictionary may well provide a simpler solution than other DOM-based parsers. + + +Supported OS & SDK Versions +----------------------------- + +* Supported build target - iOS 10.2 / Mac OS 10.12 (Xcode 8.2, Apple LLVM compiler 8.0) +* Earliest supported deployment target - iOS 8.0 / Mac OS 10.10 +* Earliest compatible deployment target - iOS 4.3 / Mac OS 10.6 + +NOTE: 'Supported' means that the library has been tested with this version. 'Compatible' means that the library should work on this OS version (i.e. it doesn't rely on any unavailable SDK features) but is no longer being tested for compatibility and may require tweaking or bug fixes to run correctly. + + +ARC Compatibility +------------------ + +As of version 1.1, XMLDictionary requires ARC. If you wish to use XMLDictionary in a non-ARC project, just add the -fobjc-arc compiler flag to the XMLDictionary.m class. To do this, go to the Build Phases tab in your target settings, open the Compile Sources group, double-click XMLDictionary.m in the list and type -fobjc-arc into the popover. + +If you wish to convert your whole project to ARC, comment out the #error line in XMLDictionary.m, then run the Edit > Refactor > Convert to Objective-C ARC... tool in Xcode and make sure all files that you wish to use ARC for (including XMLDictionary.m) are checked. + + +Thread Safety +-------------- + +XMLDictionary's methods should all be thread safe. It is safe to use multiple XMLDictionaryParsers concurrently on different threads, but it is not safe to call the same parser concurrently on multiple threads. + + +Installation +-------------- + +To use the XMLDictionary in an app, just drag the class files into your project. + + +XMLDictionaryParser +--------------------- + +The XMLDictionaryParser class is responsible for parsing an XML file into a dictionary. You don't normally need to use this class explicitly as you can just use the utility methods added to NSDictionary, however it can be useful if you want to modify the default parser settings. + +You can create new instances of XMLDictionaryParser if you need to use multiple different settings for different dictionaries. Once you have created an XMLDictionaryParser you can use the following methods to parse XML files using that specific parser instance: + + - (NSDictionary *)dictionaryWithData:(NSData *)data; + - (NSDictionary *)dictionaryWithString:(NSString *)string; + - (NSDictionary *)dictionaryWithFile:(NSString *)path; + - (NSDictionary *)dictionaryWithParser:(NSXMLParser *)parser; + +Alternatively, you can simply modify the settings of `[XMLDictionaryParser sharedInstance]` to affect the settings for all dictionaries parsed subsequently using the NSDictionary category extension methods. + +Use the following properties to tweak the parsing behaviour: + + @property (nonatomic, assign) BOOL collapseTextNodes; + +If YES (the default value), tags that contain only text and have no children, attributes or comments will be collapsed into a single string object, simplifying traversal of the object tree. + + @property (nonatomic, assign) BOOL stripEmptyNodes; + +If YES (the default value), tags that are empty (have no children, attributes, text or comments) will be stripped. + + @property (nonatomic, assign) BOOL trimWhiteSpace; + +If YES (the default value), leading and trailing white space will be trimmed from text nodes, and text nodes containing only white space will be omitted from the dictionary. + + @property (nonatomic, assign) BOOL alwaysUseArrays; + +If `YES`, the every child node will be represented as an array, even if there is only one of them. This simplifies the logic needed to cope with properties that may be duplicated because you don't need to use `[value isKindOfClass:[NSArray class]]` to check the for the singular case. Defaults to `NO`. + + @property (nonatomic, assign) BOOL preserveComments; + +If `YES`, XML comments will be grouped into an array under the key `__comments` and can be accessed via the `comments` method. Defaults to `NO`. + + @property (nonatomic, assign) XMLDictionaryAttributesMode attributesMode; + +This property controls how XML attributes are handled. The default is `XMLDictionaryAttributesModePrefixed` meaning that attributes will be included in the dictionary, with an _ (underscore) prefix to avoid namespace collisions. Alternative values are `XMLDictionaryAttributesModeDictionary`, which will place all the attributes in a separate dictionary, `XMLDictionaryAttributesModeUnprefixed`, which includes the attributes without prefix (which may cause collisions with nodes) and `XMLDictionaryAttributesModeDiscard`, which will strip the attributes. + + @property (nonatomic, assign) XMLDictionaryNodeNameMode nodeNameMode; + +This property controls how the node name is handled. The default value is `XMLDictionaryNodeNameModeRootOnly`, meaning that the node name will only be included in the root dictionary (the names for the children can be inferred from the dictionary keys, but the `nodeName` method won't work for anything except the root node). Alternative values are `XMLDictionaryNodeNameModeAlways`, meaning that the node name will be included in the dictionary with the key `__name` (and can be accessed using the `nodeName`) method, or `XMLDictionaryNodeNameModeNever` which will never include the `__name' key. + + +Category Methods +----------------- + +XMLDictionary extends NSDictionary with the following methods: + + + (NSDictionary *)dictionaryWithXMLParser:(NSParser *)parser; + +Create a new NSDictionary object from an existing NSXMLParser. Useful if fetching data through AFNetworking. + + + (NSDictionary *)dictionaryWithXMLData:(NSData *)data; + +Create a new NSDictionary object from XML-encoded data. + + + (NSDictionary *)dictionaryWithXMLString:(NSString *)string; + +Create a new NSDictionary object from XML-encoded string. + + + (NSDictionary *)dictionaryWithXMLFile:(NSString *)path; + +Create a new NSDictionary object from and XML-encoded file. + + - (NSString *)attributeForKey:(NSString *)key; + +Get the XML attribute for a given key (key name should not include prefix). + + - (NSDictionary *)attributes; + +Get a dictionary of all XML attributes for a given node's dictionary. If the node has no attributes then this will return nil. + + - (NSDictionary *)childNodes; + +Get a dictionary of all child nodes for a given node's dictionary. If multiple nodes have the same name they will be grouped into an array. If the node has no children then this will return nil. + + - (NSArray *)comments; + +Get an array of all comments for a given node. Note that the nesting relative to other nodes is not preserved. If the node has no comments then this will return nil. + + - (NSString *)nodeName; + +Get the name of the node. If the name is not known this will return nil. + + - (NSString *)innerText; + +Get the text content of the node. If the node has no text content, this will return nil; + + - (NSString *)innerXML; + +Get the contents of the node as an XML-encoded string. This XML string will not include the container node itself. + + - (NSString *)XMLString; + +Get the node and its content as an XML-encoded string. If the node name is not known, the top level tag will be called ``. + + - (NSArray *)arrayValueForKeyPath:(NSString *)keyPath; + +Works just like `valueForKeyPath:` except that the value returned will always be an array. So if there is only a single value, it will be returned as `@[value]`. + + - (NSString *)stringValueForKeyPath:(NSString *)keyPath; + +Works just like `valueForKeyPath:` except that the value returned will always be a string. So if the value is a dictionary, the text value of `innerText` will be returned, and if the value is an array, the first item will be returned. + + - (NSDictionary *)dictionaryValueForKeyPath:(NSString *)keyPath; + +Works just like `valueForKeyPath:` except that the value returned will always be a dictionary. So if the collapseTextNodes option is enabled and the value is a string, this will convert it back to a dictionary before returning, and if the value is an array, the first item will be returned. + + +Usage +-------- + +The simplest way to load an XML file is as follows: + + NSString *filePath = [[NSBundle mainBundle] pathForResource:@"someFile" ofType:@"xml"]; + NSDictionary *xmlDoc = [NSDictionary dictionaryWithXMLFile:filePath]; + +You can then iterate over the dictionary as you would with any other object tree, e.g. one loaded from a Plist. + +To access nested nodes and attributes, you can use the valueForKeyPath syntax. For example to get the string value of `` from the following XML: + + + + Hello World + + Was his name-oh + + +You would write: + + NSString *foo = [xmlDoc valueForKeyPath:@"bar.foo"]; + +The above examples assumes that you are using the default setting for `collapseTextNodes` and `alwaysUseArrays`. If `collapseTextNodes` is disabled then you would instead access ``'s value by writing: + + NSString *foo = [[xmlDoc valueForKeyPath:@"bar.foo"] innerText]; + +If the `alwaysUseArrays` option is enabled then would use one of the following, depending on the `collapseTextNodes` property: + + NSString *foo = [[xmlDoc valueForKeyPath:@"bar.foo"] firstObject]; + NSString *foo = [[[xmlDoc valueForKeyPath:@"bar.foo"] firstObject] innerText]; + +To get the cliche attribute of `bar`, you could write: + + NSString *barCliche = [xmlDoc[@"bar] attributes][@"cliche"]; + +If the `attributesMode` is set to the default value of `XMLDictionaryAttributesModePrefixed` then you can also do this: + + NSString *barCliche = [xmlDoc valueForKeyPath:@"bar._cliche"]; + +Or if it is set to `XMLDictionaryAttributesModeUnprefixed` you would simply do this: + + NSString *barCliche = [xmlDoc valueForKeyPath:@"bar.cliche"]; + + +Release Notes +---------------- + +Version 1.4.1 + +- Upgraded for Xcode 8.2 +- Added tvOS and watchOS support to podspec + +Version 1.4 + +- Added dictionaryWithXMLParser: constructor method +- Added wrapRootNode option as a nicer way to preserve root node name +- No longer crashes if non-string values are used as keys or attributes +- Now complies with the -Weverything warning level + +Version 1.3 + +- added stripEmptyNodes property (defaults to YES) +- added arrayValueForKeyPath, stringValueForKeyPath and dictionaryValueForKeyPath methods to simplify working with data + +Version 1.2.2 + +- sharedInstance method no longer returns a new instance each time + +Version 1.2.1 + +- Removed isa reference, deprecated in iOS 7 + +Version 1.2 + +- Exposed XMLDictionaryParser object, which can be used to configure the parser +- Parsing options can now be changed without modifying the library +- Added option to always encode properties as arrays +- `__name` and `__coment` keys are no longer included by default +- Apostrophe is now encoded as `'` +- removed `attributeForKey:` method + +Version 1.1 + +- Updated to use ARC +- Added podspec + +Version 1.0 + +- Initial release diff --git a/Pods/XMLDictionary/XMLDictionary/XMLDictionary.h b/Pods/XMLDictionary/XMLDictionary/XMLDictionary.h new file mode 100644 index 00000000..82a6300e --- /dev/null +++ b/Pods/XMLDictionary/XMLDictionary/XMLDictionary.h @@ -0,0 +1,118 @@ +// +// XMLDictionary.h +// +// Version 1.4.1 +// +// Created by Nick Lockwood on 15/11/2010. +// Copyright 2010 Charcoal Design. All rights reserved. +// +// Get the latest version of XMLDictionary from here: +// +// https://github.com/nicklockwood/XMLDictionary +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// + +#import +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wobjc-missing-property-synthesis" + + +NS_ASSUME_NONNULL_BEGIN + + +typedef NS_ENUM(NSInteger, XMLDictionaryAttributesMode) +{ + XMLDictionaryAttributesModePrefixed = 0, //default + XMLDictionaryAttributesModeDictionary, + XMLDictionaryAttributesModeUnprefixed, + XMLDictionaryAttributesModeDiscard +}; + + +typedef NS_ENUM(NSInteger, XMLDictionaryNodeNameMode) +{ + XMLDictionaryNodeNameModeRootOnly = 0, //default + XMLDictionaryNodeNameModeAlways, + XMLDictionaryNodeNameModeNever +}; + + +static NSString *const XMLDictionaryAttributesKey = @"__attributes"; +static NSString *const XMLDictionaryCommentsKey = @"__comments"; +static NSString *const XMLDictionaryTextKey = @"__text"; +static NSString *const XMLDictionaryNodeNameKey = @"__name"; +static NSString *const XMLDictionaryAttributePrefix = @"_"; + + +@interface XMLDictionaryParser : NSObject + ++ (XMLDictionaryParser *)sharedInstance; + +@property (nonatomic, assign) BOOL collapseTextNodes; // defaults to YES +@property (nonatomic, assign) BOOL stripEmptyNodes; // defaults to YES +@property (nonatomic, assign) BOOL trimWhiteSpace; // defaults to YES +@property (nonatomic, assign) BOOL alwaysUseArrays; // defaults to NO +@property (nonatomic, assign) BOOL preserveComments; // defaults to NO +@property (nonatomic, assign) BOOL wrapRootNode; // defaults to NO + +@property (nonatomic, assign) XMLDictionaryAttributesMode attributesMode; +@property (nonatomic, assign) XMLDictionaryNodeNameMode nodeNameMode; + +- (nullable NSDictionary *)dictionaryWithParser:(NSXMLParser *)parser; +- (nullable NSDictionary *)dictionaryWithData:(NSData *)data; +- (nullable NSDictionary *)dictionaryWithString:(NSString *)string; +- (nullable NSDictionary *)dictionaryWithFile:(NSString *)path; + +@end + + +@interface NSDictionary (XMLDictionary) + ++ (nullable NSDictionary *)dictionaryWithXMLParser:(NSXMLParser *)parser; ++ (nullable NSDictionary *)dictionaryWithXMLData:(NSData *)data; ++ (nullable NSDictionary *)dictionaryWithXMLString:(NSString *)string; ++ (nullable NSDictionary *)dictionaryWithXMLFile:(NSString *)path; + +@property (nonatomic, readonly, copy, nullable) NSDictionary *attributes; +@property (nonatomic, readonly, copy, nullable) NSDictionary *childNodes; +@property (nonatomic, readonly, copy, nullable) NSArray *comments; +@property (nonatomic, readonly, copy, nullable) NSString *nodeName; +@property (nonatomic, readonly, copy, nullable) NSString *innerText; +@property (nonatomic, readonly, copy) NSString *innerXML; +@property (nonatomic, readonly, copy) NSString *XMLString; + +- (nullable NSArray *)arrayValueForKeyPath:(NSString *)keyPath; +- (nullable NSString *)stringValueForKeyPath:(NSString *)keyPath; +- (nullable NSDictionary *)dictionaryValueForKeyPath:(NSString *)keyPath; + +@end + + +@interface NSString (XMLDictionary) + +@property (nonatomic, readonly, copy) NSString *XMLEncodedString; + +@end + + +NS_ASSUME_NONNULL_END + + +#pragma GCC diagnostic pop diff --git a/Pods/XMLDictionary/XMLDictionary/XMLDictionary.m b/Pods/XMLDictionary/XMLDictionary/XMLDictionary.m new file mode 100644 index 00000000..e2b7de39 --- /dev/null +++ b/Pods/XMLDictionary/XMLDictionary/XMLDictionary.m @@ -0,0 +1,564 @@ +// +// XMLDictionary.m +// +// Version 1.4.1 +// +// Created by Nick Lockwood on 15/11/2010. +// Copyright 2010 Charcoal Design. All rights reserved. +// +// Get the latest version of XMLDictionary from here: +// +// https://github.com/nicklockwood/XMLDictionary +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// + +#import "XMLDictionary.h" + + +#pragma GCC diagnostic ignored "-Wobjc-missing-property-synthesis" +#pragma GCC diagnostic ignored "-Wpartial-availability" +#pragma GCC diagnostic ignored "-Wdirect-ivar-access" +#pragma GCC diagnostic ignored "-Wformat-non-iso" +#pragma GCC diagnostic ignored "-Wgnu" + + +#import +#if !__has_feature(objc_arc) +#error This class requires automatic reference counting +#endif + + +@interface XMLDictionaryParser () + +@property (nonatomic, strong) NSMutableDictionary *root; +@property (nonatomic, strong) NSMutableArray *stack; +@property (nonatomic, strong) NSMutableString *text; + +@end + + +@implementation XMLDictionaryParser + ++ (XMLDictionaryParser *)sharedInstance +{ + static dispatch_once_t once; + static XMLDictionaryParser *sharedInstance; + dispatch_once(&once, ^{ + + sharedInstance = [[XMLDictionaryParser alloc] init]; + }); + return sharedInstance; +} + +- (instancetype)init +{ + if ((self = [super init])) + { + _collapseTextNodes = YES; + _stripEmptyNodes = YES; + _trimWhiteSpace = YES; + _alwaysUseArrays = NO; + _preserveComments = NO; + _wrapRootNode = NO; + } + return self; +} + +- (id)copyWithZone:(NSZone *)zone +{ + XMLDictionaryParser *copy = [[[self class] allocWithZone:zone] init]; + copy.collapseTextNodes = _collapseTextNodes; + copy.stripEmptyNodes = _stripEmptyNodes; + copy.trimWhiteSpace = _trimWhiteSpace; + copy.alwaysUseArrays = _alwaysUseArrays; + copy.preserveComments = _preserveComments; + copy.attributesMode = _attributesMode; + copy.nodeNameMode = _nodeNameMode; + copy.wrapRootNode = _wrapRootNode; + return copy; +} + +- (NSDictionary *)dictionaryWithParser:(NSXMLParser *)parser +{ + parser.delegate = self; + [parser parse]; + id result = _root; + _root = nil; + _stack = nil; + _text = nil; + return result; +} + +- (NSDictionary *)dictionaryWithData:(NSData *)data +{ + NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data]; + return [self dictionaryWithParser:parser]; +} + +- (NSDictionary *)dictionaryWithString:(NSString *)string +{ + NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding]; + return [self dictionaryWithData:data]; +} + +- (NSDictionary *)dictionaryWithFile:(NSString *)path +{ + NSData *data = [NSData dataWithContentsOfFile:path]; + return [self dictionaryWithData:data]; +} + ++ (NSString *)XMLStringForNode:(id)node withNodeName:(NSString *)nodeName +{ + if ([node isKindOfClass:[NSArray class]]) + { + NSMutableArray *nodes = [NSMutableArray arrayWithCapacity:[node count]]; + for (id individualNode in node) + { + [nodes addObject:[self XMLStringForNode:individualNode withNodeName:nodeName]]; + } + return [nodes componentsJoinedByString:@"\n"]; + } + else if ([node isKindOfClass:[NSDictionary class]]) + { + NSDictionary *attributes = [(NSDictionary *)node attributes]; + NSMutableString *attributeString = [NSMutableString string]; + [attributes enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *value, __unused BOOL *stop) { + [attributeString appendFormat:@" %@=\"%@\"", key.description.XMLEncodedString, value.description.XMLEncodedString]; + }]; + + NSString *innerXML = [node innerXML]; + if (innerXML.length) + { + return [NSString stringWithFormat:@"<%1$@%2$@>%3$@", nodeName, attributeString, innerXML]; + } + else + { + return [NSString stringWithFormat:@"<%@%@/>", nodeName, attributeString]; + } + } + else + { + return [NSString stringWithFormat:@"<%1$@>%2$@", nodeName, [node description].XMLEncodedString]; + } +} + +- (void)endText +{ + if (_trimWhiteSpace) + { + _text = [[_text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] mutableCopy]; + } + if (_text.length) + { + NSMutableDictionary *top = _stack.lastObject; + id existing = top[XMLDictionaryTextKey]; + if ([existing isKindOfClass:[NSArray class]]) + { + [existing addObject:_text]; + } + else if (existing) + { + top[XMLDictionaryTextKey] = [@[existing, _text] mutableCopy]; + } + else + { + top[XMLDictionaryTextKey] = _text; + } + } + _text = nil; +} + +- (void)addText:(NSString *)text +{ + if (!_text) + { + _text = [NSMutableString stringWithString:text]; + } + else + { + [_text appendString:text]; + } +} + +- (void)parser:(__unused NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(__unused NSString *)namespaceURI qualifiedName:(__unused NSString *)qName attributes:(NSDictionary *)attributeDict +{ + [self endText]; + + NSMutableDictionary *node = [NSMutableDictionary dictionary]; + switch (_nodeNameMode) + { + case XMLDictionaryNodeNameModeRootOnly: + { + if (!_root) + { + node[XMLDictionaryNodeNameKey] = elementName; + } + break; + } + case XMLDictionaryNodeNameModeAlways: + { + node[XMLDictionaryNodeNameKey] = elementName; + break; + } + case XMLDictionaryNodeNameModeNever: + { + break; + } + } + + if (attributeDict.count) + { + switch (_attributesMode) + { + case XMLDictionaryAttributesModePrefixed: + { + for (NSString *key in attributeDict) + { + node[[XMLDictionaryAttributePrefix stringByAppendingString:key]] = attributeDict[key]; + } + break; + } + case XMLDictionaryAttributesModeDictionary: + { + node[XMLDictionaryAttributesKey] = attributeDict; + break; + } + case XMLDictionaryAttributesModeUnprefixed: + { + [node addEntriesFromDictionary:attributeDict]; + break; + } + case XMLDictionaryAttributesModeDiscard: + { + break; + } + } + } + + if (!_root) + { + _root = node; + _stack = [NSMutableArray arrayWithObject:node]; + if (_wrapRootNode) + { + _root = [NSMutableDictionary dictionaryWithObject:_root forKey:elementName]; + [_stack insertObject:_root atIndex:0]; + } + } + else + { + NSMutableDictionary *top = _stack.lastObject; + id existing = top[elementName]; + if ([existing isKindOfClass:[NSArray class]]) + { + [(NSMutableArray *)existing addObject:node]; + } + else if (existing) + { + top[elementName] = [@[existing, node] mutableCopy]; + } + else if (_alwaysUseArrays) + { + top[elementName] = [NSMutableArray arrayWithObject:node]; + } + else + { + top[elementName] = node; + } + [_stack addObject:node]; + } +} + +- (NSString *)nameForNode:(NSDictionary *)node inDictionary:(NSDictionary *)dict +{ + if (node.nodeName) + { + return node.nodeName; + } + else + { + for (NSString *name in dict) + { + id object = dict[name]; + if (object == node) + { + return name; + } + else if ([object isKindOfClass:[NSArray class]] && [(NSArray *)object containsObject:node]) + { + return name; + } + } + } + return nil; +} + +- (void)parser:(__unused NSXMLParser *)parser didEndElement:(__unused NSString *)elementName namespaceURI:(__unused NSString *)namespaceURI qualifiedName:(__unused NSString *)qName +{ + [self endText]; + + NSMutableDictionary *top = _stack.lastObject; + [_stack removeLastObject]; + + if (!top.attributes && !top.childNodes && !top.comments) + { + NSMutableDictionary *newTop = _stack.lastObject; + NSString *nodeName = [self nameForNode:top inDictionary:newTop]; + if (nodeName) + { + id parentNode = newTop[nodeName]; + NSString *innerText = top.innerText; + if (innerText && _collapseTextNodes) + { + if ([parentNode isKindOfClass:[NSArray class]]) + { + parentNode[[parentNode count] - 1] = innerText; + } + else + { + newTop[nodeName] = innerText; + } + } + else if (!innerText) + { + if (_stripEmptyNodes) + { + if ([parentNode isKindOfClass:[NSArray class]]) + { + [(NSMutableArray *)parentNode removeLastObject]; + } + else + { + [newTop removeObjectForKey:nodeName]; + } + } + else if (!_collapseTextNodes) + { + top[XMLDictionaryTextKey] = @""; + } + } + } + } +} + +- (void)parser:(__unused NSXMLParser *)parser foundCharacters:(NSString *)string +{ + [self addText:string]; +} + +- (void)parser:(__unused NSXMLParser *)parser foundCDATA:(NSData *)CDATABlock +{ + [self addText:[[NSString alloc] initWithData:CDATABlock encoding:NSUTF8StringEncoding]]; +} + +- (void)parser:(__unused NSXMLParser *)parser foundComment:(NSString *)comment +{ + if (_preserveComments) + { + NSMutableDictionary *top = _stack.lastObject; + NSMutableArray *comments = top[XMLDictionaryCommentsKey]; + if (!comments) + { + comments = [@[comment] mutableCopy]; + top[XMLDictionaryCommentsKey] = comments; + } + else + { + [comments addObject:comment]; + } + } +} + +@end + + +@implementation NSDictionary(XMLDictionary) + ++ (NSDictionary *)dictionaryWithXMLParser:(NSXMLParser *)parser +{ + return [[[XMLDictionaryParser sharedInstance] copy] dictionaryWithParser:parser]; +} + ++ (NSDictionary *)dictionaryWithXMLData:(NSData *)data +{ + return [[[XMLDictionaryParser sharedInstance] copy] dictionaryWithData:data]; +} + ++ (NSDictionary *)dictionaryWithXMLString:(NSString *)string +{ + return [[[XMLDictionaryParser sharedInstance] copy] dictionaryWithString:string]; +} + ++ (NSDictionary *)dictionaryWithXMLFile:(NSString *)path +{ + return [[[XMLDictionaryParser sharedInstance] copy] dictionaryWithFile:path]; +} + +- (nullable NSDictionary *)attributes +{ + NSDictionary *attributes = self[XMLDictionaryAttributesKey]; + if (attributes) + { + return attributes.count? attributes: nil; + } + else + { + NSMutableDictionary *filteredDict = [NSMutableDictionary dictionaryWithDictionary:self]; + [filteredDict removeObjectsForKeys:@[XMLDictionaryCommentsKey, XMLDictionaryTextKey, XMLDictionaryNodeNameKey]]; + for (NSString *key in filteredDict.allKeys) + { + [filteredDict removeObjectForKey:key]; + if ([key hasPrefix:XMLDictionaryAttributePrefix]) + { + filteredDict[[key substringFromIndex:XMLDictionaryAttributePrefix.length]] = self[key]; + } + } + return filteredDict.count? filteredDict: nil; + } + return nil; +} + +- (nullable NSDictionary *)childNodes +{ + NSMutableDictionary *filteredDict = [self mutableCopy]; + [filteredDict removeObjectsForKeys:@[XMLDictionaryAttributesKey, XMLDictionaryCommentsKey, XMLDictionaryTextKey, XMLDictionaryNodeNameKey]]; + for (NSString *key in filteredDict.allKeys) + { + if ([key hasPrefix:XMLDictionaryAttributePrefix]) + { + [filteredDict removeObjectForKey:key]; + } + } + return filteredDict.count? filteredDict: nil; +} + +- (nullable NSArray *)comments +{ + return self[XMLDictionaryCommentsKey]; +} + +- (nullable NSString *)nodeName +{ + return self[XMLDictionaryNodeNameKey]; +} + +- (id)innerText +{ + id text = self[XMLDictionaryTextKey]; + if ([text isKindOfClass:[NSArray class]]) + { + return [text componentsJoinedByString:@"\n"]; + } + else + { + return text; + } +} + +- (NSString *)innerXML +{ + NSMutableArray *nodes = [NSMutableArray array]; + + for (NSString *comment in [self comments]) + { + [nodes addObject:[NSString stringWithFormat:@"", [comment XMLEncodedString]]]; + } + + NSDictionary *childNodes = [self childNodes]; + for (NSString *key in childNodes) + { + [nodes addObject:[XMLDictionaryParser XMLStringForNode:childNodes[key] withNodeName:key]]; + } + + NSString *text = [self innerText]; + if (text) + { + [nodes addObject:[text XMLEncodedString]]; + } + + return [nodes componentsJoinedByString:@"\n"]; +} + +- (NSString *)XMLString +{ + if (self.count == 1 && ![self nodeName]) + { + //ignore outermost dictionary + return [self innerXML]; + } + else + { + return [XMLDictionaryParser XMLStringForNode:self withNodeName:[self nodeName] ?: @"root"]; + } +} + +- (nullable NSArray *)arrayValueForKeyPath:(NSString *)keyPath +{ + id value = [self valueForKeyPath:keyPath]; + if (value && ![value isKindOfClass:[NSArray class]]) + { + return @[value]; + } + return value; +} + +- (nullable NSString *)stringValueForKeyPath:(NSString *)keyPath +{ + id value = [self valueForKeyPath:keyPath]; + if ([value isKindOfClass:[NSArray class]]) + { + value = ((NSArray *)value).firstObject; + } + if ([value isKindOfClass:[NSDictionary class]]) + { + return [(NSDictionary *)value innerText]; + } + return value; +} + +- (nullable NSDictionary *)dictionaryValueForKeyPath:(NSString *)keyPath +{ + id value = [self valueForKeyPath:keyPath]; + if ([value isKindOfClass:[NSArray class]]) + { + value = [value count]? value[0]: nil; + } + if ([value isKindOfClass:[NSString class]]) + { + return @{XMLDictionaryTextKey: value}; + } + return value; +} + +@end + + +@implementation NSString (XMLDictionary) + +- (NSString *)XMLEncodedString +{ + return [[[[[self stringByReplacingOccurrencesOfString:@"&" withString:@"&"] + stringByReplacingOccurrencesOfString:@"<" withString:@"<"] + stringByReplacingOccurrencesOfString:@">" withString:@">"] + stringByReplacingOccurrencesOfString:@"\"" withString:@"""] + stringByReplacingOccurrencesOfString:@"\'" withString:@"'"]; +} + +@end diff --git a/SiliconLabsApp-Bridging-Header.h b/SiliconLabsApp-Bridging-Header.h index bab9f89a..4408e88c 100644 --- a/SiliconLabsApp-Bridging-Header.h +++ b/SiliconLabsApp-Bridging-Header.h @@ -2,6 +2,7 @@ // Use this file to import your target's public headers that you would like to expose to Swift. // +#import "SILConstants.h" #import "SILBeacon.h" #import "SILCentralManager.h" #import "SILDiscoveredPeripheralDisplayDataViewModel.h" @@ -9,3 +10,4 @@ #import "SILDiscoveredPeripheralDisplayData.h" #import "SILRSSIMeasurementTable.h" #import "UIColor+SILColors.h" +#import "SILApp.h" diff --git a/SiliconLabsApp.pch b/SiliconLabsApp.pch deleted file mode 100644 index 6b1040d2..00000000 --- a/SiliconLabsApp.pch +++ /dev/null @@ -1,14 +0,0 @@ -// -// SiliconLabsApp.pch -// SiliconLabsApp -// -// Created by jamaal.sedayao on 10/24/17. -// Copyright © 2017 SiliconLabs. All rights reserved. -// - -#ifndef SiliconLabsApp_pch -#define SiliconLabsApp_pch - -#import "SiliconLabsApp-Swift.h" - -#endif /* SiliconLabsApp_pch */ diff --git a/SiliconLabsApp.xcodeproj/project.pbxproj b/SiliconLabsApp.xcodeproj/project.pbxproj index 707530e4..12519449 100644 --- a/SiliconLabsApp.xcodeproj/project.pbxproj +++ b/SiliconLabsApp.xcodeproj/project.pbxproj @@ -94,6 +94,7 @@ 07BBA7621BD688D300C2B07E /* SILBluetoothEnumerationModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 07BBA7611BD688D300C2B07E /* SILBluetoothEnumerationModel.m */; }; 07BBA7651BD68AB300C2B07E /* SILBluetoothFieldModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 07BBA7641BD68AB300C2B07E /* SILBluetoothFieldModel.m */; }; 07BBA7681BD6938800C2B07E /* SILBluetoothServiceCharacteristicModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 07BBA7671BD6938800C2B07E /* SILBluetoothServiceCharacteristicModel.m */; }; + 0C08FD5820CB1CA90016CABC /* SILConnectedLightingViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C39082E1FA8AC7A00934AD1 /* SILConnectedLightingViewController.m */; }; 0C2FCB031F9A542300F4F259 /* SILBluetoothFieldModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 07BBA7641BD68AB300C2B07E /* SILBluetoothFieldModel.m */; }; 0C2FCB041F9A542300F4F259 /* SILDebugCharacteristicEncodingFieldTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 498311D11BF239EF00D49FF2 /* SILDebugCharacteristicEncodingFieldTableViewCell.m */; }; 0C2FCB051F9A542300F4F259 /* SILOTAUICoordinator.m in Sources */ = {isa = PBXBuildFile; fileRef = 491ADCBA1E71EEA300AC2E69 /* SILOTAUICoordinator.m */; }; @@ -233,7 +234,6 @@ 0C2FCB971F9A542300F4F259 /* CoreBluetooth.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E621B33E1A65573500223C5A /* CoreBluetooth.framework */; }; 0C2FCB991F9A542300F4F259 /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E6D45D351A6EA74C002D9EC4 /* CoreLocation.framework */; }; 0C2FCB9A1F9A542300F4F259 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E666CBE61A77298900676C5C /* QuartzCore.framework */; }; - 0C2FCB9B1F9A542300F4F259 /* Pods_SiliconLabsApp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 426AC50AF4550762BDD32A6E /* Pods_SiliconLabsApp.framework */; }; 0C2FCB9D1F9A542300F4F259 /* SILOTAProgressViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 49FB4BF01E7A33C900223F3E /* SILOTAProgressViewController.xib */; }; 0C2FCB9E1F9A542300F4F259 /* SILDebugDeviceFilterViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = AAD9E9331F279B910054C387 /* SILDebugDeviceFilterViewController.xib */; }; 0C2FCB9F1F9A542300F4F259 /* SILBeaconRegistryEntryCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 07140FA01BFD80E8001CD217 /* SILBeaconRegistryEntryCell.xib */; }; @@ -287,12 +287,235 @@ 0C39082B1FA233F900934AD1 /* SILDeviceSelectionViewModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CC658141F96C3C200953CDC /* SILDeviceSelectionViewModel.m */; }; 0C3908301FA8AC7A00934AD1 /* SILConnectedLightingViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C39082E1FA8AC7A00934AD1 /* SILConnectedLightingViewController.m */; }; 0C3908311FA8AC7A00934AD1 /* SILConnectedLightingViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0C39082F1FA8AC7A00934AD1 /* SILConnectedLightingViewController.xib */; }; - 0C55454F1FC47FD100B0E98D /* SILConnectedLightingViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0C39082F1FA8AC7A00934AD1 /* SILConnectedLightingViewController.xib */; }; - 0C5545501FC47FD400B0E98D /* SILConnectedLightingViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C39082E1FA8AC7A00934AD1 /* SILConnectedLightingViewController.m */; }; 0C6745FF1FAC033F0032CBF5 /* SILCentralManager.m in Sources */ = {isa = PBXBuildFile; fileRef = E6A37E401A82809B00510E39 /* SILCentralManager.m */; }; 0CC658151F96C3C200953CDC /* SILDeviceSelectionViewModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CC658141F96C3C200953CDC /* SILDeviceSelectionViewModel.m */; }; + 0F34409520AF0E250067397C /* RangeTestStoryboard.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0F34409420AF0E250067397C /* RangeTestStoryboard.storyboard */; }; + 0F34409620AF0E250067397C /* RangeTestStoryboard.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0F34409420AF0E250067397C /* RangeTestStoryboard.storyboard */; }; + 0F34409820AF0E570067397C /* SILRangeTestModeSelectionViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0F34409720AF0E570067397C /* SILRangeTestModeSelectionViewController.xib */; }; + 0F34409920AF0E570067397C /* SILRangeTestModeSelectionViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0F34409720AF0E570067397C /* SILRangeTestModeSelectionViewController.xib */; }; + 0F34409B20AF18BA0067397C /* SILRangeTestAppViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F34409A20AF18BA0067397C /* SILRangeTestAppViewController.swift */; }; + 0F34409C20AF18BA0067397C /* SILRangeTestAppViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F34409A20AF18BA0067397C /* SILRangeTestAppViewController.swift */; }; + 0F392514214FA15F00D74963 /* SILRangeTestMovingAverageCalculator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0FFDD024210F09A000CFFB5E /* SILRangeTestMovingAverageCalculator.swift */; }; + 0F392515214FA16100D74963 /* SILRangeTestTXValueUpdater.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F75B9D021395E3200E8D9E9 /* SILRangeTestTXValueUpdater.swift */; }; + 0F3AC36720ADAABF0010091C /* SILRangeTestModeSelectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F3AC36520ADAABF0010091C /* SILRangeTestModeSelectionViewController.swift */; }; + 0F3AC36920ADAAC60010091C /* SILRangeTestModeSelectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F3AC36520ADAABF0010091C /* SILRangeTestModeSelectionViewController.swift */; }; + 0F3EB6B720C524C30062A7C1 /* SILRangeTestAppViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F3EB6B620C524C30062A7C1 /* SILRangeTestAppViewModel.swift */; }; + 0F3EB6B820C524C30062A7C1 /* SILRangeTestAppViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F3EB6B620C524C30062A7C1 /* SILRangeTestAppViewModel.swift */; }; + 0F44BCAE20EE5E0E00CD27B3 /* SILRangeTestCharacteristic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F44BCAD20EE5E0E00CD27B3 /* SILRangeTestCharacteristic.swift */; }; + 0F44BCAF20EE5E0E00CD27B3 /* SILRangeTestCharacteristic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F44BCAD20EE5E0E00CD27B3 /* SILRangeTestCharacteristic.swift */; }; + 0F4E50F621525FDC00F58ACE /* SILBluetoothFieldModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 07BBA7641BD68AB300C2B07E /* SILBluetoothFieldModel.m */; }; + 0F4E50F721525FDC00F58ACE /* SILDebugCharacteristicEncodingFieldTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 498311D11BF239EF00D49FF2 /* SILDebugCharacteristicEncodingFieldTableViewCell.m */; }; + 0F4E50F821525FDC00F58ACE /* SILOTAUICoordinator.m in Sources */ = {isa = PBXBuildFile; fileRef = 491ADCBA1E71EEA300AC2E69 /* SILOTAUICoordinator.m */; }; + 0F4E50F921525FDC00F58ACE /* SILActivityBarViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 492CA4AF1E4E0DD700502AC9 /* SILActivityBarViewController.m */; }; + 0F4E50FA21525FDC00F58ACE /* SILDebugAdvDetailsCollectionView.m in Sources */ = {isa = PBXBuildFile; fileRef = 0755DD031BD05C5C0003886D /* SILDebugAdvDetailsCollectionView.m */; }; + 0F4E50FB21525FDC00F58ACE /* SILAppearance.m in Sources */ = {isa = PBXBuildFile; fileRef = E666CBD71A767C5500676C5C /* SILAppearance.m */; }; + 0F4E50FC21525FDC00F58ACE /* SILDiscoveredPeripheralDisplayData.m in Sources */ = {isa = PBXBuildFile; fileRef = 070DDDD41BD96D28000BC644 /* SILDiscoveredPeripheralDisplayData.m */; }; + 0F4E50FD21525FDC00F58ACE /* SILBigRedButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 496A42F21E7C582F006E87F2 /* SILBigRedButton.m */; }; + 0F4E50FE21525FDC00F58ACE /* SILDebugCharacteristicTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 07B8A8CB1BCD6E3B001948C1 /* SILDebugCharacteristicTableViewCell.m */; }; + 0F4E50FF21525FDC00F58ACE /* SILBluetoothModelManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 07BBA74D1BD5858F00C2B07E /* SILBluetoothModelManager.m */; }; + 0F4E510021525FDC00F58ACE /* SILSettings.m in Sources */ = {isa = PBXBuildFile; fileRef = E607A3501A8D4FD100DAAFD3 /* SILSettings.m */; }; + 0F4E510121525FDC00F58ACE /* SILWeakTargetWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = E642661F1A855DA8006C6B2F /* SILWeakTargetWrapper.m */; }; + 0F4E510221525FDC00F58ACE /* SILAlertBarView.m in Sources */ = {isa = PBXBuildFile; fileRef = 07A9563E1BDD40CB0028D333 /* SILAlertBarView.m */; }; + 0F4E510321525FDC00F58ACE /* SILBeaconRegistry.m in Sources */ = {isa = PBXBuildFile; fileRef = E6CCCFEB1A73040C0004B2F4 /* SILBeaconRegistry.m */; }; + 0F4E510421525FDC00F58ACE /* SILDebugServiceTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 07B8A8CF1BCD6E3B001948C1 /* SILDebugServiceTableViewCell.m */; }; + 0F4E510521525FDC00F58ACE /* SILDebugAdvDetailsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 078138461BE99502001EFE7E /* SILDebugAdvDetailsViewController.m */; }; + 0F4E510621525FDC00F58ACE /* SILDeviceSelectionViewModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CC658141F96C3C200953CDC /* SILDeviceSelectionViewModel.m */; }; + 0F4E510721525FDC00F58ACE /* SILValueFieldEditorViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 498311DB1BF29AF600D49FF2 /* SILValueFieldEditorViewController.m */; }; + 0F4E510821525FDC00F58ACE /* SILBeaconViewModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 07B1AD771BFD043000D4D454 /* SILBeaconViewModel.m */; }; + 0F4E510921525FDC00F58ACE /* SILDeviceSelectionViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E621B3521A6568EE00223C5A /* SILDeviceSelectionViewController.m */; }; + 0F4E510A21525FDC00F58ACE /* SILCharacteristicFieldValueResolver.m in Sources */ = {isa = PBXBuildFile; fileRef = 0702AB2B1BDFEE35009527B0 /* SILCharacteristicFieldValueResolver.m */; }; + 0F4E510B21525FDC00F58ACE /* SILBluetoothBitFieldModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 07BBA75E1BD687CC00C2B07E /* SILBluetoothBitFieldModel.m */; }; + 0F4E510C21525FDC00F58ACE /* SILDiscoveredPeripheralDisplayDataViewModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 49BB94B41E68FB4B0068670E /* SILDiscoveredPeripheralDisplayDataViewModel.m */; }; + 0F4E510D21525FDC00F58ACE /* SILDebugDeviceTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 07B8A8D61BCD6E6F001948C1 /* SILDebugDeviceTableViewCell.m */; }; + 0F4E510E21525FDC00F58ACE /* DebugDeviceFilterViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAD9E9311F279A670054C387 /* DebugDeviceFilterViewController.swift */; }; + 0F4E510F21525FDC00F58ACE /* SILDebugAdvDetailCollectionViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 0755DCFA1BCFEE5D0003886D /* SILDebugAdvDetailCollectionViewCell.m */; }; + 0F4E511021525FDC00F58ACE /* SILHealthThermometerAppViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E6CFEB261A686DC000F216AB /* SILHealthThermometerAppViewController.m */; }; + 0F4E511121525FDC00F58ACE /* SILProximityCalculator.m in Sources */ = {isa = PBXBuildFile; fileRef = E64266221A8565BA006C6B2F /* SILProximityCalculator.m */; }; + 0F4E511221525FDC00F58ACE /* SILDoubleKeyDictionaryPair.m in Sources */ = {isa = PBXBuildFile; fileRef = 0752B7811BDEEC2C0064CBF0 /* SILDoubleKeyDictionaryPair.m */; }; + 0F4E511321525FDC00F58ACE /* SILBluetoothEnumerationModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 07BBA7611BD688D300C2B07E /* SILBluetoothEnumerationModel.m */; }; + 0F4E511421525FDC00F58ACE /* RSSISliderTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA4D43591F291C17001EE0D2 /* RSSISliderTableViewCell.swift */; }; + 0F4E511521525FDC00F58ACE /* SILBGBeaconViewModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 07B1AD7A1BFD05CA00D4D454 /* SILBGBeaconViewModel.m */; }; + 0F4E511621525FDC00F58ACE /* SILDebugEnumerationValueTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 0781384E1BE99521001EFE7E /* SILDebugEnumerationValueTableViewCell.m */; }; + 0F4E511721525FDC00F58ACE /* SILDeviceSelectionCollectionViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = E643F41A1A728A8500FB34F5 /* SILDeviceSelectionCollectionViewCell.m */; }; + 0F4E511821525FDC00F58ACE /* SILDebugCharacteristicValueFieldTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 0702AB311BE10E07009527B0 /* SILDebugCharacteristicValueFieldTableViewCell.m */; }; + 0F4E511921525FDC00F58ACE /* UIImage+SILImages.m in Sources */ = {isa = PBXBuildFile; fileRef = E6CCCFF71A7304210004B2F4 /* UIImage+SILImages.m */; }; + 0F4E511A21525FDC00F58ACE /* DebugDeviceFilterViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA7817401F33B26C00B37B09 /* DebugDeviceFilterViewModel.swift */; }; + 0F4E511B21525FDC00F58ACE /* TLMData.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA162DCD1F0541B600E3DB22 /* TLMData.swift */; }; + 0F4E511C21525FDC00F58ACE /* UITableViewCell+SILHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = 074691431BFE21A7000D6839 /* UITableViewCell+SILHelpers.m */; }; + 0F4E511D21525FDC00F58ACE /* SILTextFieldEntryCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 078138571BE9B014001EFE7E /* SILTextFieldEntryCell.m */; }; + 0F4E511E21525FDC00F58ACE /* SILAdvertisementDataModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 0755DD061BD086180003886D /* SILAdvertisementDataModel.m */; }; + 0F4E511F21525FDC00F58ACE /* SILCharacteristicTableModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 07B8A8861BC47790001948C1 /* SILCharacteristicTableModel.m */; }; + 0F4E512021525FDC00F58ACE /* SILBeaconDataModel.m in Sources */ = {isa = PBXBuildFile; fileRef = AA0FF40D1EFC62C7007C14D3 /* SILBeaconDataModel.m */; }; + 0F4E512121525FDC00F58ACE /* SILRangeTestAppViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F3EB6B620C524C30062A7C1 /* SILRangeTestAppViewModel.swift */; }; + 0F4E512221525FDC00F58ACE /* SILDebugCharacteristicPropertyView.m in Sources */ = {isa = PBXBuildFile; fileRef = 07B8A8C91BCD6E3B001948C1 /* SILDebugCharacteristicPropertyView.m */; }; + 0F4E512321525FDC00F58ACE /* CBPeripheral+Services.m in Sources */ = {isa = PBXBuildFile; fileRef = 4924BA6A1E7057F800AE9E56 /* CBPeripheral+Services.m */; }; + 0F4E512421525FDC00F58ACE /* SILDebugProperty.m in Sources */ = {isa = PBXBuildFile; fileRef = 07B8A89B1BC5F872001948C1 /* SILDebugProperty.m */; }; + 0F4E512521525FDC00F58ACE /* SILPopoverViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 49FB4BEA1E7A2EC200223F3E /* SILPopoverViewController.m */; }; + 0F4E512621525FDC00F58ACE /* SILSegmentedControl.m in Sources */ = {isa = PBXBuildFile; fileRef = E666CBEA1A77C75400676C5C /* SILSegmentedControl.m */; }; + 0F4E512721525FDC00F58ACE /* SILRetailBeaconDetailsHeaderView.m in Sources */ = {isa = PBXBuildFile; fileRef = AA5F62EA1F0A84ED007EDAAC /* SILRetailBeaconDetailsHeaderView.m */; }; + 0F4E512821525FDC00F58ACE /* SILOTAHUDPeripheralViewModel.m in Sources */ = {isa = PBXBuildFile; fileRef = DC4E508D1E92E507004FD829 /* SILOTAHUDPeripheralViewModel.m */; }; + 0F4E512921525FDC00F58ACE /* SILDebugAdvDetailTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 078138481BE99502001EFE7E /* SILDebugAdvDetailTableViewCell.m */; }; + 0F4E512A21525FDC00F58ACE /* EddystoneScanner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4977B0311E607D99006DE78C /* EddystoneScanner.swift */; }; + 0F4E512B21525FDC00F58ACE /* SILDebugCharacteristicEncodingViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 078138521BE9A849001EFE7E /* SILDebugCharacteristicEncodingViewController.m */; }; + 0F4E512C21525FDC00F58ACE /* SILAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = E6CAA2281A64011900A49DAF /* SILAppDelegate.m */; }; + 0F4E512D21525FDC00F58ACE /* SILHeartRateMeasurement.m in Sources */ = {isa = PBXBuildFile; fileRef = E6B773EC1A68474800B93058 /* SILHeartRateMeasurement.m */; }; + 0F4E512E21525FDC00F58ACE /* SILApp+AttributedProfiles.m in Sources */ = {isa = PBXBuildFile; fileRef = E666CBE01A76B67900676C5C /* SILApp+AttributedProfiles.m */; }; + 0F4E512F21525FDC00F58ACE /* SILOTAFirmwareFile.m in Sources */ = {isa = PBXBuildFile; fileRef = 494F93C91E7719D40057C1E0 /* SILOTAFirmwareFile.m */; }; + 0F4E513021525FDC00F58ACE /* SILBitRowModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 0752B77B1BDED93F0064CBF0 /* SILBitRowModel.m */; }; + 0F4E513121525FDC00F58ACE /* SILRetailBeaconDetailsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = AA0FF40A1EFC368A007C14D3 /* SILRetailBeaconDetailsViewController.m */; }; + 0F4E513221525FDC00F58ACE /* SILCollectionViewRightAlignedFlowLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = E6C8FF0E1A71A9A900DF062F /* SILCollectionViewRightAlignedFlowLayout.m */; }; + 0F4E513321525FDC00F58ACE /* UIColor+SILColors.m in Sources */ = {isa = PBXBuildFile; fileRef = E666CBDA1A767DCB00676C5C /* UIColor+SILColors.m */; }; + 0F4E513421525FDC00F58ACE /* SILBeaconRegistryEntryCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 07B1AD891BFD4C8F00D4D454 /* SILBeaconRegistryEntryCell.m */; }; + 0F4E513521525FDC00F58ACE /* SILAppSelectionHelpViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E666CBE41A76C0E800676C5C /* SILAppSelectionHelpViewController.m */; }; + 0F4E513621525FDC00F58ACE /* SILTemperatureType.m in Sources */ = {isa = PBXBuildFile; fileRef = E6CDEB3B1A698F4900AC7B33 /* SILTemperatureType.m */; }; + 0F4E513721525FDC00F58ACE /* SILKeyFobViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E67C5BBF1A7FA64D003628A4 /* SILKeyFobViewController.m */; }; + 0F4E513821525FDC00F58ACE /* SILCentralManager.m in Sources */ = {isa = PBXBuildFile; fileRef = E6A37E401A82809B00510E39 /* SILCentralManager.m */; }; + 0F4E513921525FDC00F58ACE /* CBService+Categories.m in Sources */ = {isa = PBXBuildFile; fileRef = 4924BA6D1E70585100AE9E56 /* CBService+Categories.m */; }; + 0F4E513A21525FDC00F58ACE /* SILEddystoneBeaconViewModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 495BF34F1E5F6A81002B3F8D /* SILEddystoneBeaconViewModel.m */; }; + 0F4E513B21525FDC00F58ACE /* SILBluetoothDescriptorModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 07BBA7581BD5CDB400C2B07E /* SILBluetoothDescriptorModel.m */; }; + 0F4E513C21525FDC00F58ACE /* SILRoundedViewBehaviour.m in Sources */ = {isa = PBXBuildFile; fileRef = E6B3EC9B1AADD9BD005A687F /* SILRoundedViewBehaviour.m */; }; + 0F4E513D21525FDC00F58ACE /* SILRangeTestSettingValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F8163C020C52386008B98C6 /* SILRangeTestSettingValue.swift */; }; + 0F4E513E21525FDC00F58ACE /* EddystoneBeacon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49E96F3E1E64618E00516DDC /* EddystoneBeacon.swift */; }; + 0F4E513F21525FDC00F58ACE /* SILRangeTestModeSelectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F3AC36520ADAABF0010091C /* SILRangeTestModeSelectionViewController.swift */; }; + 0F4E514021525FDC00F58ACE /* SILRangeTestPeripheral.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0FD15EB920BD3D0D00ED43BB /* SILRangeTestPeripheral.swift */; }; + 0F4E514121525FDC00F58ACE /* SILAltBeaconViewModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 07B1AD831BFD0B4F00D4D454 /* SILAltBeaconViewModel.m */; }; + 0F4E514221525FDC00F58ACE /* SILKeyValueViewModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 494F93C01E77170B0057C1E0 /* SILKeyValueViewModel.m */; }; + 0F4E514321525FDC00F58ACE /* SILDebugCharacteristicEnumerationFieldTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 0702AB3B1BE1844E009527B0 /* SILDebugCharacteristicEnumerationFieldTableViewCell.m */; }; + 0F4E514421525FDC00F58ACE /* SILRangeTestCharacteristic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F44BCAD20EE5E0E00CD27B3 /* SILRangeTestCharacteristic.swift */; }; + 0F4E514521525FDC00F58ACE /* SILTemperatureMeasurement.m in Sources */ = {isa = PBXBuildFile; fileRef = E6CDEB3E1A69911D00AC7B33 /* SILTemperatureMeasurement.m */; }; + 0F4E514621525FDC00F58ACE /* SILRetailBeaconAppViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E6CCCFEF1A73040C0004B2F4 /* SILRetailBeaconAppViewController.m */; }; + 0F4E514721525FDC00F58ACE /* SILBeaconDataViewModel.m in Sources */ = {isa = PBXBuildFile; fileRef = AA0FF4101EFC65F5007C14D3 /* SILBeaconDataViewModel.m */; }; + 0F4E514821525FDC00F58ACE /* SILOTAFirmwareUpdate.m in Sources */ = {isa = PBXBuildFile; fileRef = 494F93C61E7717A90057C1E0 /* SILOTAFirmwareUpdate.m */; }; + 0F4E514921525FDC00F58ACE /* SILBodySensorLocation.m in Sources */ = {isa = PBXBuildFile; fileRef = E6B773EF1A684B9700B93058 /* SILBodySensorLocation.m */; }; + 0F4E514A21525FDC00F58ACE /* TextFieldTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA4D43571F27EA65001EE0D2 /* TextFieldTableViewCell.swift */; }; + 0F4E514B21525FDC00F58ACE /* SILConnectedLightingViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C39082E1FA8AC7A00934AD1 /* SILConnectedLightingViewController.m */; }; + 0F4E514C21525FDC00F58ACE /* SILCharacteristicFieldBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = 0752B7741BDEC2C00064CBF0 /* SILCharacteristicFieldBuilder.m */; }; + 0F4E514D21525FDC00F58ACE /* SILApp.m in Sources */ = {isa = PBXBuildFile; fileRef = E621B34B1A655B3F00223C5A /* SILApp.m */; }; + 0F4E514E21525FDC00F58ACE /* UIFont+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA78173E1F33A86100B37B09 /* UIFont+Extensions.swift */; }; + 0F4E514F21525FDC00F58ACE /* SILDebugServicesViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 07B8A8CD1BCD6E3B001948C1 /* SILDebugServicesViewController.m */; }; + 0F4E515021525FDC00F58ACE /* SILBeacon.m in Sources */ = {isa = PBXBuildFile; fileRef = E6CCCFE91A73040C0004B2F4 /* SILBeacon.m */; }; + 0F4E515121525FDC00F58ACE /* SILFindKeyFobViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E6A37E431A82AAFC00510E39 /* SILFindKeyFobViewController.m */; }; + 0F4E515221525FDC00F58ACE /* SILOTAProgressViewModel.m in Sources */ = {isa = PBXBuildFile; fileRef = DC380D4C1E89584700898C12 /* SILOTAProgressViewModel.m */; }; + 0F4E515321525FDC00F58ACE /* SILOTASetupViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 491ADCBD1E72E58300AC2E69 /* SILOTASetupViewController.m */; }; + 0F4E515421525FDC00F58ACE /* WYPopoverController+SILHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = E6CCCFF91A7304210004B2F4 /* WYPopoverController+SILHelpers.m */; }; + 0F4E515521525FDC00F58ACE /* SILUUIDProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = 4924BA731E719C9900AE9E56 /* SILUUIDProvider.m */; }; + 0F4E515621525FDC00F58ACE /* SILRangeTestMovingAverageCalculator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0FFDD024210F09A000CFFB5E /* SILRangeTestMovingAverageCalculator.swift */; }; + 0F4E515721525FDC00F58ACE /* SILDebugSpacerTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 078137DB1BE3C45D001EFE7E /* SILDebugSpacerTableViewCell.m */; }; + 0F4E515821525FDC00F58ACE /* SILOTAFirmwareUpdateManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 49C10EEE1E71E0EC00C67256 /* SILOTAFirmwareUpdateManager.m */; }; + 0F4E515921525FDC00F58ACE /* SILOTAProgressViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 49FB4BEF1E7A33C900223F3E /* SILOTAProgressViewController.m */; }; + 0F4E515A21525FDC00F58ACE /* SILDebugCharacteristicToggleFieldTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 0702AB361BE179EE009527B0 /* SILDebugCharacteristicToggleFieldTableViewCell.m */; }; + 0F4E515B21525FDC00F58ACE /* SILRSSIMeasurementTable.m in Sources */ = {isa = PBXBuildFile; fileRef = E642661C1A8527C0006C6B2F /* SILRSSIMeasurementTable.m */; }; + 0F4E515C21525FDC00F58ACE /* SILConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = E6A37E461A82C1C400510E39 /* SILConstants.m */; }; + 0F4E515D21525FDC00F58ACE /* SILCalibrationViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E607A34D1A8D1F3000DAAFD3 /* SILCalibrationViewController.m */; }; + 0F4E515E21525FDC00F58ACE /* SILBeaconRegistryEntryViewModel.m in Sources */ = {isa = PBXBuildFile; fileRef = DCE784DE1E7AF0930038C87A /* SILBeaconRegistryEntryViewModel.m */; }; + 0F4E515F21525FDC00F58ACE /* SILBitFieldFieldModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 070167491BE2B5B70075F005 /* SILBitFieldFieldModel.m */; }; + 0F4E516021525FDC00F58ACE /* SILBluetoothXMLParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 07BBA7461BD5820C00C2B07E /* SILBluetoothXMLParser.m */; }; + 0F4E516121525FDC00F58ACE /* SILDebugDeviceViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 07B8A8D81BCD6E6F001948C1 /* SILDebugDeviceViewController.m */; }; + 0F4E516221525FDC00F58ACE /* SILBluetoothServiceCharacteristicModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 07BBA7671BD6938800C2B07E /* SILBluetoothServiceCharacteristicModel.m */; }; + 0F4E516321525FDC00F58ACE /* SILAppSelectionViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E621B3471A6558DB00223C5A /* SILAppSelectionViewController.m */; }; + 0F4E516421525FDC00F58ACE /* SILDebugHeaderView.m in Sources */ = {isa = PBXBuildFile; fileRef = 07B8A8C61BCD6E2D001948C1 /* SILDebugHeaderView.m */; }; + 0F4E516521525FDC00F58ACE /* SILKeyFobTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = E6B3EAFE1A7FEDB5002E3567 /* SILKeyFobTableViewCell.m */; }; + 0F4E516621525FDC00F58ACE /* SILCentralManagerBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = E6B773DF1A671E8A00B93058 /* SILCentralManagerBuilder.m */; }; + 0F4E516721525FDC00F58ACE /* SILRangeTestAppViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F34409A20AF18BA0067397C /* SILRangeTestAppViewController.swift */; }; + 0F4E516821525FDC00F58ACE /* SILOTAFirmwareUpdateViewModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 494F93C31E7717540057C1E0 /* SILOTAFirmwareUpdateViewModel.m */; }; + 0F4E516921525FDC00F58ACE /* UIView+SILAnimations.m in Sources */ = {isa = PBXBuildFile; fileRef = 07B8A87F1BC41462001948C1 /* UIView+SILAnimations.m */; }; + 0F4E516A21525FDC00F58ACE /* SILValueFieldRowModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 0752B77E1BDED9710064CBF0 /* SILValueFieldRowModel.m */; }; + 0F4E516B21525FDC00F58ACE /* SILEnumerationFieldRowModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 0752B7781BDED8D00064CBF0 /* SILEnumerationFieldRowModel.m */; }; + 0F4E516C21525FDC00F58ACE /* Int+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA7817421F34C5C500B37B09 /* Int+Extensions.swift */; }; + 0F4E516D21525FDC00F58ACE /* UIImage+SILHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = E666CBDD1A76809A00676C5C /* UIImage+SILHelpers.m */; }; + 0F4E516E21525FDC00F58ACE /* SILOTAHUDView.m in Sources */ = {isa = PBXBuildFile; fileRef = DCB431101E8315CE00EE94F0 /* SILOTAHUDView.m */; }; + 0F4E516F21525FDC00F58ACE /* SILServiceTableModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 07B8A8831BC47615001948C1 /* SILServiceTableModel.m */; }; + 0F4E517021525FDC00F58ACE /* SILBluetoothSearch.m in Sources */ = {isa = PBXBuildFile; fileRef = 79E62B4E1ECCA29400344CAA /* SILBluetoothSearch.m */; }; + 0F4E517121525FDC00F58ACE /* SILBluetoothCharacteristicModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 07BBA7551BD5C89700C2B07E /* SILBluetoothCharacteristicModel.m */; }; + 0F4E517221525FDC00F58ACE /* SILDiscoveredPeripheral.m in Sources */ = {isa = PBXBuildFile; fileRef = E6B773DC1A670F8100B93058 /* SILDiscoveredPeripheral.m */; }; + 0F4E517321525FDC00F58ACE /* SILBluetoothServiceModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 07BBA7521BD5BD3500C2B07E /* SILBluetoothServiceModel.m */; }; + 0F4E517421525FDC00F58ACE /* SILWeakNotificationPair.m in Sources */ = {isa = PBXBuildFile; fileRef = E6C667231B0A5BD90083C248 /* SILWeakNotificationPair.m */; }; + 0F4E517521525FDC00F58ACE /* GradientSlider.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA4D435D1F2A3F15001EE0D2 /* GradientSlider.swift */; }; + 0F4E517621525FDC00F58ACE /* SILAppSelectionTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = E621B34E1A65645A00223C5A /* SILAppSelectionTableViewCell.m */; }; + 0F4E517721525FDC00F58ACE /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = E6CAA2251A64011900A49DAF /* main.m */; }; + 0F4E517821525FDC00F58ACE /* DebugDeviceViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA154A71F20F3D8002078B5 /* DebugDeviceViewModel.swift */; }; + 0F4E517921525FDC00F58ACE /* SILDebugPopoverViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 078138361BE97370001EFE7E /* SILDebugPopoverViewController.m */; }; + 0F4E517A21525FDC00F58ACE /* SILRSSIMeasurement.m in Sources */ = {isa = PBXBuildFile; fileRef = E64266191A84F1D6006C6B2F /* SILRSSIMeasurement.m */; }; + 0F4E517B21525FDC00F58ACE /* SILIBeaconViewModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 07B1AD7D1BFD0A2100D4D454 /* SILIBeaconViewModel.m */; }; + 0F4E517C21525FDC00F58ACE /* SILBluetoothBitModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 07BBA75B1BD6862A00C2B07E /* SILBluetoothBitModel.m */; }; + 0F4E517D21525FDC00F58ACE /* SILKeyFobTableSectionHeaderView.m in Sources */ = {isa = PBXBuildFile; fileRef = E6B3EB011A7FEE1C002E3567 /* SILKeyFobTableSectionHeaderView.m */; }; + 0F4E517E21525FDC00F58ACE /* SILRangeTestTXValueUpdater.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F75B9D021395E3200E8D9E9 /* SILRangeTestTXValueUpdater.swift */; }; + 0F4E517F21525FDC00F58ACE /* NSDictionary+SILErrorCode.m in Sources */ = {isa = PBXBuildFile; fileRef = 494F93AA1E757FB10057C1E0 /* NSDictionary+SILErrorCode.m */; }; + 0F4E518021525FDC00F58ACE /* GradientView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA4D435B1F2A35A3001EE0D2 /* GradientView.swift */; }; + 0F4E518121525FDC00F58ACE /* KZBehaviour.m in Sources */ = {isa = PBXBuildFile; fileRef = E64C95BB1AB20DB60029E23A /* KZBehaviour.m */; }; + 0F4E518221525FDC00F58ACE /* SILDescriptorTableModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 07B8A8891BC47834001948C1 /* SILDescriptorTableModel.m */; }; + 0F4E518321525FDC00F58ACE /* SILBeaconRegistryEntry.m in Sources */ = {isa = PBXBuildFile; fileRef = E6CCCFED1A73040C0004B2F4 /* SILBeaconRegistryEntry.m */; }; + 0F4E518421525FDC00F58ACE /* SILBarGraphCollectionViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = E6C8FF0B1A71869A00DF062F /* SILBarGraphCollectionViewCell.m */; }; + 0F4E518521525FDC00F58ACE /* SILDebugCharacteristicEnumerationListViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0781384C1BE99521001EFE7E /* SILDebugCharacteristicEnumerationListViewController.m */; }; + 0F4E518621525FDC00F58ACE /* SILRangeTestManufacturerData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F69656820ECD32A0083C32A /* SILRangeTestManufacturerData.swift */; }; + 0F4E518721525FDC00F58ACE /* NSError+SILHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = E6CCCFF51A7304210004B2F4 /* NSError+SILHelpers.m */; }; + 0F4E518821525FDC00F58ACE /* SILAdvertisementDataViewModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 49BB94B11E68F2DC0068670E /* SILAdvertisementDataViewModel.m */; }; + 0F4E518921525FDC00F58ACE /* SILEncodingPseudoFieldRowModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 19AC2956BD095FCA31424BC0 /* SILEncodingPseudoFieldRowModel.m */; }; + 0F4E518B21525FDC00F58ACE /* CoreBluetooth.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E621B33E1A65573500223C5A /* CoreBluetooth.framework */; }; + 0F4E518C21525FDC00F58ACE /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E6D45D351A6EA74C002D9EC4 /* CoreLocation.framework */; }; + 0F4E518D21525FDC00F58ACE /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E666CBE61A77298900676C5C /* QuartzCore.framework */; }; + 0F4E519121525FDC00F58ACE /* SILOTAProgressViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 49FB4BF01E7A33C900223F3E /* SILOTAProgressViewController.xib */; }; + 0F4E519221525FDC00F58ACE /* SILDebugDeviceFilterViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = AAD9E9331F279B910054C387 /* SILDebugDeviceFilterViewController.xib */; }; + 0F4E519321525FDC00F58ACE /* SILBeaconRegistryEntryCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 07140FA01BFD80E8001CD217 /* SILBeaconRegistryEntryCell.xib */; }; + 0F4E519421525FDC00F58ACE /* SILConnectedLightingViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0C39082F1FA8AC7A00934AD1 /* SILConnectedLightingViewController.xib */; }; + 0F4E519521525FDC00F58ACE /* SILDebugDeviceTableViewCell~iphone.xib in Resources */ = {isa = PBXBuildFile; fileRef = 078137EC1BE40A8C001EFE7E /* SILDebugDeviceTableViewCell~iphone.xib */; }; + 0F4E519621525FDC00F58ACE /* SILDebugDeviceTableViewCell~ipad.xib in Resources */ = {isa = PBXBuildFile; fileRef = 078137EB1BE40A8C001EFE7E /* SILDebugDeviceTableViewCell~ipad.xib */; }; + 0F4E519721525FDC00F58ACE /* SILRetailBeaconDetailsHeaderView.xib in Resources */ = {isa = PBXBuildFile; fileRef = AA5F62EC1F0A859F007EDAAC /* SILRetailBeaconDetailsHeaderView.xib */; }; + 0F4E519821525FDC00F58ACE /* SILDebugAdvDetailTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0763AC4A1BFE8F5400EBE94B /* SILDebugAdvDetailTableViewCell.xib */; }; + 0F4E519921525FDC00F58ACE /* SILRangeTestModeSelectionViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0F34409720AF0E570067397C /* SILRangeTestModeSelectionViewController.xib */; }; + 0F4E519A21525FDC00F58ACE /* SILDebugDeviceViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 078137ED1BE40A8C001EFE7E /* SILDebugDeviceViewController.xib */; }; + 0F4E519B21525FDC00F58ACE /* SILDebugCharacteristicToggleFieldTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 078137FD1BE40AA5001EFE7E /* SILDebugCharacteristicToggleFieldTableViewCell.xib */; }; + 0F4E519C21525FDC00F58ACE /* SILOTAHUDView.xib in Resources */ = {isa = PBXBuildFile; fileRef = DCB431121E8315EF00EE94F0 /* SILOTAHUDView.xib */; }; + 0F4E519D21525FDC00F58ACE /* SILDebugCharacteristicValueFieldTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 078137FE1BE40AA5001EFE7E /* SILDebugCharacteristicValueFieldTableViewCell.xib */; }; + 0F4E519E21525FDC00F58ACE /* RangeTestStoryboard.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0F34409420AF0E250067397C /* RangeTestStoryboard.storyboard */; }; + 0F4E519F21525FDC00F58ACE /* SILActivityBarViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 492CA4B01E4E0DD700502AC9 /* SILActivityBarViewController.xib */; }; + 0F4E51A021525FDC00F58ACE /* SILKeyFobTableViewCell~ipad.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0781380F1BE40D2D001EFE7E /* SILKeyFobTableViewCell~ipad.xib */; }; + 0F4E51A121525FDC00F58ACE /* SILDebugAdvDetailCollectionViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 078137E81BE40A8C001EFE7E /* SILDebugAdvDetailCollectionViewCell.xib */; }; + 0F4E51A221525FDC00F58ACE /* SILDebugServiceTableViewCell~iphone.xib in Resources */ = {isa = PBXBuildFile; fileRef = 078138021BE40AA5001EFE7E /* SILDebugServiceTableViewCell~iphone.xib */; }; + 0F4E51A321525FDC00F58ACE /* SILDeviceSelectionViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = E6B3ECA31AAE3DFC005A687F /* SILDeviceSelectionViewController.xib */; }; + 0F4E51A421525FDC00F58ACE /* SILDebugSpacerTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 078137FF1BE40AA5001EFE7E /* SILDebugSpacerTableViewCell.xib */; }; + 0F4E51A521525FDC00F58ACE /* SILFindKeyFobViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0781380D1BE40D2D001EFE7E /* SILFindKeyFobViewController.xib */; }; + 0F4E51A621525FDC00F58ACE /* SILDebugCharacteristicEncodingFieldTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 498311CE1BF2398B00D49FF2 /* SILDebugCharacteristicEncodingFieldTableViewCell.xib */; }; + 0F4E51A721525FDC00F58ACE /* SILDebugCharacteristicTableViewCell~ipad.xib in Resources */ = {isa = PBXBuildFile; fileRef = 078137FB1BE40AA5001EFE7E /* SILDebugCharacteristicTableViewCell~ipad.xib */; }; + 0F4E51A821525FDC00F58ACE /* SILDebugServicesViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 078138001BE40AA5001EFE7E /* SILDebugServicesViewController.xib */; }; + 0F4E51A921525FDC00F58ACE /* XML in Resources */ = {isa = PBXBuildFile; fileRef = 07BBA74F1BD599F800C2B07E /* XML */; }; + 0F4E51AA21525FDC00F58ACE /* SILDebugCharacteristicEnumerationFieldTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 078137F91BE40AA5001EFE7E /* SILDebugCharacteristicEnumerationFieldTableViewCell.xib */; }; + 0F4E51AB21525FDC00F58ACE /* SILPopoverViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 49FB4BEB1E7A2EC200223F3E /* SILPopoverViewController.xib */; }; + 0F4E51AC21525FDC00F58ACE /* SILKeyFobTableSectionHeaderView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0781380E1BE40D2D001EFE7E /* SILKeyFobTableSectionHeaderView.xib */; }; + 0F4E51AD21525FDC00F58ACE /* SILDebugAdvDetailsViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0763AC491BFE8F5400EBE94B /* SILDebugAdvDetailsViewController.xib */; }; + 0F4E51AE21525FDC00F58ACE /* SILRetailBeaconDetailsViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = AA0FF4061EFC11AD007C14D3 /* SILRetailBeaconDetailsViewController.xib */; }; + 0F4E51AF21525FDC00F58ACE /* SILKeyFobViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 078138111BE40D2D001EFE7E /* SILKeyFobViewController.xib */; }; + 0F4E51B021525FDC00F58ACE /* SILDebugCharacteristicPropertyView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 078137FA1BE40AA5001EFE7E /* SILDebugCharacteristicPropertyView.xib */; }; + 0F4E51B121525FDC00F58ACE /* SILAppSelectionViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 078138221BE40D75001EFE7E /* SILAppSelectionViewController.xib */; }; + 0F4E51B221525FDC00F58ACE /* SILHealthThermometerAppViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0781381D1BE40D69001EFE7E /* SILHealthThermometerAppViewController.xib */; }; + 0F4E51B321525FDC00F58ACE /* SILDeviceSelectionCollectionViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = E6B3ECA61AAE3E5B005A687F /* SILDeviceSelectionCollectionViewCell.xib */; }; + 0F4E51B421525FDC00F58ACE /* SILRetailBeaconAppViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0781381A1BE40D4C001EFE7E /* SILRetailBeaconAppViewController.xib */; }; + 0F4E51B521525FDC00F58ACE /* SILDebugServiceTableViewCell~ipad.xib in Resources */ = {isa = PBXBuildFile; fileRef = 078138011BE40AA5001EFE7E /* SILDebugServiceTableViewCell~ipad.xib */; }; + 0F4E51B621525FDC00F58ACE /* SILKeyFobTableViewCell~iphone.xib in Resources */ = {isa = PBXBuildFile; fileRef = 078138101BE40D2D001EFE7E /* SILKeyFobTableViewCell~iphone.xib */; }; + 0F4E51B721525FDC00F58ACE /* SILAppSelectionTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 078138211BE40D75001EFE7E /* SILAppSelectionTableViewCell.xib */; }; + 0F4E51B821525FDC00F58ACE /* SILAppSelectionHelpViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 078138201BE40D75001EFE7E /* SILAppSelectionHelpViewController.xib */; }; + 0F4E51B921525FDC00F58ACE /* SILDebugCharacteristicEncodingViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0797E34C1BF0071D0046EF0E /* SILDebugCharacteristicEncodingViewController.xib */; }; + 0F4E51BA21525FDC00F58ACE /* SILOTASetupViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 491ADCBE1E72E58300AC2E69 /* SILOTASetupViewController.xib */; }; + 0F4E51BB21525FDC00F58ACE /* SILValueFieldEditorViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0763AC4B1BFE8F5400EBE94B /* SILValueFieldEditorViewController.xib */; }; + 0F4E51BC21525FDC00F58ACE /* SILCalibrationViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = E6B3ECA01AAE2C8B005A687F /* SILCalibrationViewController.xib */; }; + 0F4E51BD21525FDC00F58ACE /* SILBarGraphCollectionViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0781381C1BE40D69001EFE7E /* SILBarGraphCollectionViewCell.xib */; }; + 0F4E51BE21525FDC00F58ACE /* SILDebugHeaderView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 078137EF1BE40A8C001EFE7E /* SILDebugHeaderView.xib */; }; + 0F4E51BF21525FDC00F58ACE /* SILTextFieldEntryCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0797E34B1BF0071D0046EF0E /* SILTextFieldEntryCell.xib */; }; + 0F4E51C021525FDC00F58ACE /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = E6CAA2321A64011900A49DAF /* LaunchScreen.xib */; }; + 0F4E51C121525FDC00F58ACE /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E6CAA2301A64011900A49DAF /* Images.xcassets */; }; + 0F4E51C221525FDC00F58ACE /* SILDebugEnumerationValueTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0781383F1BE993A8001EFE7E /* SILDebugEnumerationValueTableViewCell.xib */; }; + 0F4E51C321525FDC00F58ACE /* SILDebugCharacteristicEnumerationListViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0781383E1BE993A8001EFE7E /* SILDebugCharacteristicEnumerationListViewController.xib */; }; + 0F4E51C421525FDC00F58ACE /* SILDebugCharacteristicTableViewCell~iphone.xib in Resources */ = {isa = PBXBuildFile; fileRef = 078137FC1BE40AA5001EFE7E /* SILDebugCharacteristicTableViewCell~iphone.xib */; }; + 0F69656920ECD32A0083C32A /* SILRangeTestManufacturerData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F69656820ECD32A0083C32A /* SILRangeTestManufacturerData.swift */; }; + 0F69656A20ECD32A0083C32A /* SILRangeTestManufacturerData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F69656820ECD32A0083C32A /* SILRangeTestManufacturerData.swift */; }; + 0F75B9D121395E3200E8D9E9 /* SILRangeTestTXValueUpdater.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F75B9D021395E3200E8D9E9 /* SILRangeTestTXValueUpdater.swift */; }; + 0F8163C120C52386008B98C6 /* SILRangeTestSettingValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F8163C020C52386008B98C6 /* SILRangeTestSettingValue.swift */; }; + 0F8163C220C52386008B98C6 /* SILRangeTestSettingValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F8163C020C52386008B98C6 /* SILRangeTestSettingValue.swift */; }; + 0FD15EBA20BD3D0D00ED43BB /* SILRangeTestPeripheral.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0FD15EB920BD3D0D00ED43BB /* SILRangeTestPeripheral.swift */; }; + 0FD15EBB20BD3D0D00ED43BB /* SILRangeTestPeripheral.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0FD15EB920BD3D0D00ED43BB /* SILRangeTestPeripheral.swift */; }; + 0FFDD025210F09A000CFFB5E /* SILRangeTestMovingAverageCalculator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0FFDD024210F09A000CFFB5E /* SILRangeTestMovingAverageCalculator.swift */; }; 19AC27E79B49CB3AD403E6EA /* SILEncodingPseudoFieldRowModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 19AC2956BD095FCA31424BC0 /* SILEncodingPseudoFieldRowModel.m */; }; - 301355A997CA76D6D580223F /* Pods_SiliconLabsAppWithoutHomeKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7AAD8E27028334FE640216CD /* Pods_SiliconLabsAppWithoutHomeKit.framework */; }; + 2B257CB817ADC2635883B007 /* Pods_WirelessGecko.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6E7E1967C516A49F37A0A7B8 /* Pods_WirelessGecko.framework */; }; 491ADCBB1E71EEA300AC2E69 /* SILOTAUICoordinator.m in Sources */ = {isa = PBXBuildFile; fileRef = 491ADCBA1E71EEA300AC2E69 /* SILOTAUICoordinator.m */; }; 491ADCBF1E72E58300AC2E69 /* SILOTASetupViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 491ADCBD1E72E58300AC2E69 /* SILOTASetupViewController.m */; }; 491ADCC01E72E58300AC2E69 /* SILOTASetupViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 491ADCBE1E72E58300AC2E69 /* SILOTASetupViewController.xib */; }; @@ -320,7 +543,12 @@ 49FB4BED1E7A2EC200223F3E /* SILPopoverViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 49FB4BEB1E7A2EC200223F3E /* SILPopoverViewController.xib */; }; 49FB4BF11E7A33C900223F3E /* SILOTAProgressViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 49FB4BEF1E7A33C900223F3E /* SILOTAProgressViewController.m */; }; 49FB4BF21E7A33C900223F3E /* SILOTAProgressViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 49FB4BF01E7A33C900223F3E /* SILOTAProgressViewController.xib */; }; - 4EEACB99918C6244B448E420 /* Pods_SiliconLabsApp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 426AC50AF4550762BDD32A6E /* Pods_SiliconLabsApp.framework */; }; + 4D9E26202212BFB200617DBA /* SILRangeTestBoardFeatures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D9E261F2212BFB100617DBA /* SILRangeTestBoardFeatures.swift */; }; + 4D9E26212212BFB200617DBA /* SILRangeTestBoardFeatures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D9E261F2212BFB100617DBA /* SILRangeTestBoardFeatures.swift */; }; + 4D9E26222212BFB200617DBA /* SILRangeTestBoardFeatures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D9E261F2212BFB100617DBA /* SILRangeTestBoardFeatures.swift */; }; + 4D9E26252212CA7000617DBA /* SILRangeTestBoardInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D9E26242212CA7000617DBA /* SILRangeTestBoardInfo.swift */; }; + 4D9E26262212CA7000617DBA /* SILRangeTestBoardInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D9E26242212CA7000617DBA /* SILRangeTestBoardInfo.swift */; }; + 4D9E26272212CA7000617DBA /* SILRangeTestBoardInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D9E26242212CA7000617DBA /* SILRangeTestBoardInfo.swift */; }; 7928D85E1ECA10FD0075FFCB /* SILHomeKitDebugServicesViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7928D85D1ECA10FD0075FFCB /* SILHomeKitDebugServicesViewController.m */; }; 7928D8601ECA12070075FFCB /* SILHomeKitDebugServicesViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7928D85F1ECA12070075FFCB /* SILHomeKitDebugServicesViewController.xib */; }; 7928D8671ECA38AE0075FFCB /* SILHomeKitServiceTableModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 7928D8661ECA38AE0075FFCB /* SILHomeKitServiceTableModel.m */; }; @@ -336,6 +564,7 @@ 79C40C6D1EC9F59B00B729BF /* SILHomeKitDebugDeviceTableViewCell~iphone.xib in Resources */ = {isa = PBXBuildFile; fileRef = 79C40C6B1EC9F59B00B729BF /* SILHomeKitDebugDeviceTableViewCell~iphone.xib */; }; 79C40C701EC9F6A800B729BF /* SILHomeKitDebugDeviceTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 79C40C6F1EC9F6A800B729BF /* SILHomeKitDebugDeviceTableViewCell.m */; }; 79E62B4F1ECCA29400344CAA /* SILBluetoothSearch.m in Sources */ = {isa = PBXBuildFile; fileRef = 79E62B4E1ECCA29400344CAA /* SILBluetoothSearch.m */; }; + 9450946334099D8FAA384ABE /* Pods_BlueGeckoWithHomeKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84342BE824D4F9248E13114A /* Pods_BlueGeckoWithHomeKit.framework */; }; AA0724F71F388D2D001446CA /* DebugDeviceFilterViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA0724F61F388D2D001446CA /* DebugDeviceFilterViewModelTests.swift */; }; AA0FF4081EFC11AD007C14D3 /* SILRetailBeaconDetailsViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = AA0FF4061EFC11AD007C14D3 /* SILRetailBeaconDetailsViewController.xib */; }; AA0FF40B1EFC368A007C14D3 /* SILRetailBeaconDetailsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = AA0FF40A1EFC368A007C14D3 /* SILRetailBeaconDetailsViewController.m */; }; @@ -359,6 +588,7 @@ DCB431111E8315CE00EE94F0 /* SILOTAHUDView.m in Sources */ = {isa = PBXBuildFile; fileRef = DCB431101E8315CE00EE94F0 /* SILOTAHUDView.m */; }; DCB431131E8315EF00EE94F0 /* SILOTAHUDView.xib in Resources */ = {isa = PBXBuildFile; fileRef = DCB431121E8315EF00EE94F0 /* SILOTAHUDView.xib */; }; DCE784DF1E7AF0930038C87A /* SILBeaconRegistryEntryViewModel.m in Sources */ = {isa = PBXBuildFile; fileRef = DCE784DE1E7AF0930038C87A /* SILBeaconRegistryEntryViewModel.m */; }; + E48275BE20D812BE006D1478 /* SILConnectedLightingViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0C39082F1FA8AC7A00934AD1 /* SILConnectedLightingViewController.xib */; }; E607A34E1A8D1F3000DAAFD3 /* SILCalibrationViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E607A34D1A8D1F3000DAAFD3 /* SILCalibrationViewController.m */; }; E607A3511A8D4FD100DAAFD3 /* SILSettings.m in Sources */ = {isa = PBXBuildFile; fileRef = E607A3501A8D4FD100DAAFD3 /* SILSettings.m */; }; E607A36C1A9627E600DAAFD3 /* SILTemperatureMeasurementTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E607A36B1A9627E600DAAFD3 /* SILTemperatureMeasurementTests.m */; }; @@ -412,6 +642,7 @@ E6CDEB3F1A69911D00AC7B33 /* SILTemperatureMeasurement.m in Sources */ = {isa = PBXBuildFile; fileRef = E6CDEB3E1A69911D00AC7B33 /* SILTemperatureMeasurement.m */; }; E6CFEB271A686DC000F216AB /* SILHealthThermometerAppViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E6CFEB261A686DC000F216AB /* SILHealthThermometerAppViewController.m */; }; E6D45D361A6EA74C002D9EC4 /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E6D45D351A6EA74C002D9EC4 /* CoreLocation.framework */; }; + FCFE74AF68F9F5BE332F46B6 /* Pods_BlueGecko.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 71F25116C7DF08741307B3E0 /* Pods_BlueGecko.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -425,6 +656,7 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 06CC32BDFF67F87AF59FFD4D /* Pods-BlueGeckoWithHomeKit.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BlueGeckoWithHomeKit.debug.xcconfig"; path = "Pods/Target Support Files/Pods-BlueGeckoWithHomeKit/Pods-BlueGeckoWithHomeKit.debug.xcconfig"; sourceTree = ""; }; 070167481BE2B5B70075F005 /* SILBitFieldFieldModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SILBitFieldFieldModel.h; sourceTree = ""; }; 070167491BE2B5B70075F005 /* SILBitFieldFieldModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SILBitFieldFieldModel.m; sourceTree = ""; }; 0702AB2A1BDFEE35009527B0 /* SILCharacteristicFieldValueResolver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SILCharacteristicFieldValueResolver.h; sourceTree = ""; }; @@ -437,6 +669,7 @@ 0702AB3B1BE1844E009527B0 /* SILDebugCharacteristicEnumerationFieldTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SILDebugCharacteristicEnumerationFieldTableViewCell.m; path = DebugApp/ServicesTable/SILDebugCharacteristicEnumerationFieldTableViewCell.m; sourceTree = ""; }; 070DDDD31BD96D28000BC644 /* SILDiscoveredPeripheralDisplayData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SILDiscoveredPeripheralDisplayData.h; sourceTree = ""; }; 070DDDD41BD96D28000BC644 /* SILDiscoveredPeripheralDisplayData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SILDiscoveredPeripheralDisplayData.m; sourceTree = ""; }; + 070E794C717D970F0A0892C4 /* Pods-SiliconLabsAppWithoutHomeKit Dev.debug-wireless-gecko.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SiliconLabsAppWithoutHomeKit Dev.debug-wireless-gecko.xcconfig"; path = "Pods/Target Support Files/Pods-SiliconLabsAppWithoutHomeKit Dev/Pods-SiliconLabsAppWithoutHomeKit Dev.debug-wireless-gecko.xcconfig"; sourceTree = ""; }; 07140FA01BFD80E8001CD217 /* SILBeaconRegistryEntryCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = SILBeaconRegistryEntryCell.xib; path = RetailBeacon/SILBeaconRegistryEntryCell.xib; sourceTree = ""; }; 074691421BFE21A7000D6839 /* UITableViewCell+SILHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UITableViewCell+SILHelpers.h"; sourceTree = ""; }; 074691431BFE21A7000D6839 /* UITableViewCell+SILHelpers.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UITableViewCell+SILHelpers.m"; sourceTree = ""; }; @@ -544,8 +777,8 @@ 07B8A8D61BCD6E6F001948C1 /* SILDebugDeviceTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SILDebugDeviceTableViewCell.m; path = DebugApp/DevicesTable/SILDebugDeviceTableViewCell.m; sourceTree = ""; }; 07B8A8D71BCD6E6F001948C1 /* SILDebugDeviceViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SILDebugDeviceViewController.h; path = DebugApp/DevicesTable/SILDebugDeviceViewController.h; sourceTree = ""; }; 07B8A8D81BCD6E6F001948C1 /* SILDebugDeviceViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; name = SILDebugDeviceViewController.m; path = DebugApp/DevicesTable/SILDebugDeviceViewController.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; - 07BBA7451BD5820C00C2B07E /* SILBluetoothXMLParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SILBluetoothXMLParser.h; path = Services/XML/SILBluetoothXMLParser.h; sourceTree = ""; }; - 07BBA7461BD5820C00C2B07E /* SILBluetoothXMLParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SILBluetoothXMLParser.m; path = Services/XML/SILBluetoothXMLParser.m; sourceTree = ""; }; + 07BBA7451BD5820C00C2B07E /* SILBluetoothXMLParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SILBluetoothXMLParser.h; sourceTree = ""; }; + 07BBA7461BD5820C00C2B07E /* SILBluetoothXMLParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SILBluetoothXMLParser.m; sourceTree = ""; }; 07BBA74C1BD5858F00C2B07E /* SILBluetoothModelManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SILBluetoothModelManager.h; path = BluetoothModels/SILBluetoothModelManager.h; sourceTree = ""; }; 07BBA74D1BD5858F00C2B07E /* SILBluetoothModelManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SILBluetoothModelManager.m; path = BluetoothModels/SILBluetoothModelManager.m; sourceTree = ""; }; 07BBA74F1BD599F800C2B07E /* XML */ = {isa = PBXFileReference; lastKnownFileType = folder; name = XML; path = SiliconLabsApp/XML; sourceTree = SOURCE_ROOT; }; @@ -565,23 +798,43 @@ 07BBA7641BD68AB300C2B07E /* SILBluetoothFieldModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SILBluetoothFieldModel.m; path = BluetoothModels/SILBluetoothFieldModel.m; sourceTree = ""; }; 07BBA7661BD6938800C2B07E /* SILBluetoothServiceCharacteristicModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SILBluetoothServiceCharacteristicModel.h; path = BluetoothModels/SILBluetoothServiceCharacteristicModel.h; sourceTree = ""; }; 07BBA7671BD6938800C2B07E /* SILBluetoothServiceCharacteristicModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SILBluetoothServiceCharacteristicModel.m; path = BluetoothModels/SILBluetoothServiceCharacteristicModel.m; sourceTree = ""; }; - 07F48D5B1BEC0AC500C76F6F /* SILCharacteristicFieldRow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SILCharacteristicFieldRow.h; path = Protocols/SILCharacteristicFieldRow.h; sourceTree = ""; }; - 07F48D5E1BEC0B1300C76F6F /* SILFieldRequirementEnforcer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SILFieldRequirementEnforcer.h; path = Protocols/SILFieldRequirementEnforcer.h; sourceTree = ""; }; - 0C2FCBDA1F9A542300F4F259 /* SiliconLabsAppWithoutHomeKit.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SiliconLabsAppWithoutHomeKit.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 0C2FCBDB1F9A542400F4F259 /* Info-WithoutHomeKit.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "Info-WithoutHomeKit.plist"; path = "/Users/jamaal.sedayao/Desktop/Developer/Bluegecko-ios-private/SiliconLabsApp/SupportingFiles/Info-WithoutHomeKit.plist"; sourceTree = ""; }; - 0C2FCBE11F9A7F7700F4F259 /* SiliconLabsAppWithoutHomeKit.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = SiliconLabsAppWithoutHomeKit.entitlements; sourceTree = ""; }; + 07F48D5B1BEC0AC500C76F6F /* SILCharacteristicFieldRow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SILCharacteristicFieldRow.h; sourceTree = ""; }; + 07F48D5E1BEC0B1300C76F6F /* SILFieldRequirementEnforcer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SILFieldRequirementEnforcer.h; sourceTree = ""; }; + 0B98AA271D57BF6AA89CE5DC /* Pods-Wireless Gecko.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Wireless Gecko.release.xcconfig"; path = "Pods/Target Support Files/Pods-Wireless Gecko/Pods-Wireless Gecko.release.xcconfig"; sourceTree = ""; }; + 0C2FCBDA1F9A542300F4F259 /* BlueGecko.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = BlueGecko.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 0C2FCBDB1F9A542400F4F259 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 0C2FCBE11F9A7F7700F4F259 /* Entitlements.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Entitlements.entitlements; sourceTree = ""; }; 0C39082D1FA8AC7A00934AD1 /* SILConnectedLightingViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SILConnectedLightingViewController.h; path = ConnectedLightingApp/SILConnectedLightingViewController.h; sourceTree = ""; }; 0C39082E1FA8AC7A00934AD1 /* SILConnectedLightingViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SILConnectedLightingViewController.m; path = ConnectedLightingApp/SILConnectedLightingViewController.m; sourceTree = ""; }; 0C39082F1FA8AC7A00934AD1 /* SILConnectedLightingViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = SILConnectedLightingViewController.xib; path = ConnectedLightingApp/SILConnectedLightingViewController.xib; sourceTree = ""; }; 0C744A481FB369FD0016B3C5 /* ExportOptions.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = ExportOptions.plist; sourceTree = ""; }; - 0CB9F1571F9F7DC60089DC65 /* SiliconLabsApp.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SiliconLabsApp.pch; sourceTree = ""; }; - 0CB9F1581F9F7DE80089DC65 /* SiliconLabsAppWithoutHomeKit.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SiliconLabsAppWithoutHomeKit.pch; sourceTree = ""; }; + 0CA91D794559B3C4861B03B4 /* Pods-WirelessGecko.release-wireless-gecko.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WirelessGecko.release-wireless-gecko.xcconfig"; path = "Pods/Target Support Files/Pods-WirelessGecko/Pods-WirelessGecko.release-wireless-gecko.xcconfig"; sourceTree = ""; }; + 0CB9F1571F9F7DC60089DC65 /* BlueGeckoWithHomeKit.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BlueGeckoWithHomeKit.pch; sourceTree = ""; }; + 0CB9F1581F9F7DE80089DC65 /* BlueGecko.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BlueGecko.pch; sourceTree = ""; }; 0CC658131F96C3C200953CDC /* SILDeviceSelectionViewModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SILDeviceSelectionViewModel.h; path = ../ViewModels/SILDeviceSelectionViewModel.h; sourceTree = ""; }; 0CC658141F96C3C200953CDC /* SILDeviceSelectionViewModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SILDeviceSelectionViewModel.m; path = ../ViewModels/SILDeviceSelectionViewModel.m; sourceTree = ""; }; + 0F34409420AF0E250067397C /* RangeTestStoryboard.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = RangeTestStoryboard.storyboard; sourceTree = ""; }; + 0F34409720AF0E570067397C /* SILRangeTestModeSelectionViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = SILRangeTestModeSelectionViewController.xib; sourceTree = ""; }; + 0F34409A20AF18BA0067397C /* SILRangeTestAppViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SILRangeTestAppViewController.swift; sourceTree = ""; }; + 0F3AC36520ADAABF0010091C /* SILRangeTestModeSelectionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SILRangeTestModeSelectionViewController.swift; sourceTree = ""; }; + 0F3EB6B620C524C30062A7C1 /* SILRangeTestAppViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SILRangeTestAppViewModel.swift; sourceTree = ""; }; + 0F44BCAD20EE5E0E00CD27B3 /* SILRangeTestCharacteristic.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SILRangeTestCharacteristic.swift; sourceTree = ""; }; + 0F4E51CC21525FDC00F58ACE /* WirelessGecko.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = WirelessGecko.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 0F4E51CE2152684500F58ACE /* WirelessGecko.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WirelessGecko.pch; sourceTree = ""; }; + 0F69656820ECD32A0083C32A /* SILRangeTestManufacturerData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SILRangeTestManufacturerData.swift; sourceTree = ""; }; + 0F75B9D021395E3200E8D9E9 /* SILRangeTestTXValueUpdater.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SILRangeTestTXValueUpdater.swift; sourceTree = ""; }; + 0F8163C020C52386008B98C6 /* SILRangeTestSettingValue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SILRangeTestSettingValue.swift; sourceTree = ""; }; + 0FD15EB920BD3D0D00ED43BB /* SILRangeTestPeripheral.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SILRangeTestPeripheral.swift; sourceTree = ""; }; + 0FFDD024210F09A000CFFB5E /* SILRangeTestMovingAverageCalculator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SILRangeTestMovingAverageCalculator.swift; sourceTree = ""; }; + 12C24CC1B29409750D9A1CB2 /* Pods_SiliconLabsAppWithoutHomeKit_Dev.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SiliconLabsAppWithoutHomeKit_Dev.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 14222593B3D5CABF925418CF /* Pods_SiliconLabsApp_Dev.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SiliconLabsApp_Dev.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 19AC23CE45AA832127AAE6DD /* SILEncodingPseudoFieldRowModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SILEncodingPseudoFieldRowModel.h; sourceTree = ""; }; 19AC2956BD095FCA31424BC0 /* SILEncodingPseudoFieldRowModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SILEncodingPseudoFieldRowModel.m; sourceTree = ""; }; 257E756EE6E82EC7E361629D /* Pods-SiliconLabsApp.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SiliconLabsApp.debug.xcconfig"; path = "Pods/Target Support Files/Pods-SiliconLabsApp/Pods-SiliconLabsApp.debug.xcconfig"; sourceTree = ""; }; + 40F66980CDB9137B6A8DE02E /* Pods-Wireless Gecko.debug-wireless-gecko.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Wireless Gecko.debug-wireless-gecko.xcconfig"; path = "Pods/Target Support Files/Pods-Wireless Gecko/Pods-Wireless Gecko.debug-wireless-gecko.xcconfig"; sourceTree = ""; }; 426AC50AF4550762BDD32A6E /* Pods_SiliconLabsApp.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SiliconLabsApp.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 4491900FB788A5F0E74824C6 /* Pods-BlueGecko.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BlueGecko.debug.xcconfig"; path = "Pods/Target Support Files/Pods-BlueGecko/Pods-BlueGecko.debug.xcconfig"; sourceTree = ""; }; + 48633F2056480FFEA1BD8A72 /* Pods-SiliconLabsApp Dev.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SiliconLabsApp Dev.debug.xcconfig"; path = "Pods/Target Support Files/Pods-SiliconLabsApp Dev/Pods-SiliconLabsApp Dev.debug.xcconfig"; sourceTree = ""; }; 491ADCB91E71EEA300AC2E69 /* SILOTAUICoordinator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SILOTAUICoordinator.h; path = DebugApp/SILOTAUICoordinator.h; sourceTree = ""; }; 491ADCBA1E71EEA300AC2E69 /* SILOTAUICoordinator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SILOTAUICoordinator.m; path = DebugApp/SILOTAUICoordinator.m; sourceTree = ""; }; 491ADCBC1E72E58300AC2E69 /* SILOTASetupViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SILOTASetupViewController.h; path = DebugApp/SILOTASetupViewController.h; sourceTree = ""; }; @@ -606,7 +859,7 @@ 494F93C61E7717A90057C1E0 /* SILOTAFirmwareUpdate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SILOTAFirmwareUpdate.m; sourceTree = ""; }; 494F93C81E7719D40057C1E0 /* SILOTAFirmwareFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SILOTAFirmwareFile.h; sourceTree = ""; }; 494F93C91E7719D40057C1E0 /* SILOTAFirmwareFile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SILOTAFirmwareFile.m; sourceTree = ""; }; - 494F93CB1E7884150057C1E0 /* SiliconLabsApp.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = SiliconLabsApp.entitlements; sourceTree = ""; }; + 494F93CB1E7884150057C1E0 /* Entitlements.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Entitlements.entitlements; sourceTree = ""; }; 495BF34E1E5F6A81002B3F8D /* SILEddystoneBeaconViewModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SILEddystoneBeaconViewModel.h; path = SiliconLabsApp/ViewModels/SILEddystoneBeaconViewModel.h; sourceTree = SOURCE_ROOT; }; 495BF34F1E5F6A81002B3F8D /* SILEddystoneBeaconViewModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SILEddystoneBeaconViewModel.m; path = SiliconLabsApp/ViewModels/SILEddystoneBeaconViewModel.m; sourceTree = SOURCE_ROOT; }; 495BF3571E5F9D9A002B3F8D /* SiliconLabsApp-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SiliconLabsApp-Bridging-Header.h"; sourceTree = ""; }; @@ -633,8 +886,17 @@ 49FB4BEF1E7A33C900223F3E /* SILOTAProgressViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SILOTAProgressViewController.m; path = DebugApp/SILOTAProgressViewController.m; sourceTree = ""; }; 49FB4BF01E7A33C900223F3E /* SILOTAProgressViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = SILOTAProgressViewController.xib; path = DebugApp/SILOTAProgressViewController.xib; sourceTree = ""; }; 4CA68516D3541CFE58D83A14 /* Pods-SiliconLabsAppWithoutHomeKit.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SiliconLabsAppWithoutHomeKit.debug.xcconfig"; path = "Pods/Target Support Files/Pods-SiliconLabsAppWithoutHomeKit/Pods-SiliconLabsAppWithoutHomeKit.debug.xcconfig"; sourceTree = ""; }; + 4D6925E6228453B800E7F015 /* Entitlements.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Entitlements.entitlements; sourceTree = ""; }; + 4D6925EB2284549A00E7F015 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 4D9E261F2212BFB100617DBA /* SILRangeTestBoardFeatures.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SILRangeTestBoardFeatures.swift; sourceTree = ""; }; + 4D9E26242212CA7000617DBA /* SILRangeTestBoardInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SILRangeTestBoardInfo.swift; sourceTree = ""; }; + 5D477CF57EA327218A303591 /* Pods-SiliconLabsAppWithoutHomeKit Dev.release-wireless-gecko.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SiliconLabsAppWithoutHomeKit Dev.release-wireless-gecko.xcconfig"; path = "Pods/Target Support Files/Pods-SiliconLabsAppWithoutHomeKit Dev/Pods-SiliconLabsAppWithoutHomeKit Dev.release-wireless-gecko.xcconfig"; sourceTree = ""; }; 61C2546AB44D8C072A96C83A /* Pods-SiliconLabsAppWithoutHomeKit.debug-wireless-gecko.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SiliconLabsAppWithoutHomeKit.debug-wireless-gecko.xcconfig"; path = "Pods/Target Support Files/Pods-SiliconLabsAppWithoutHomeKit/Pods-SiliconLabsAppWithoutHomeKit.debug-wireless-gecko.xcconfig"; sourceTree = ""; }; 62E0D0F50D4DF9406BE2453B /* Pods-SiliconLabsApp.release-wireless-gecko.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SiliconLabsApp.release-wireless-gecko.xcconfig"; path = "Pods/Target Support Files/Pods-SiliconLabsApp/Pods-SiliconLabsApp.release-wireless-gecko.xcconfig"; sourceTree = ""; }; + 63D66014C77760FCDAC6A134 /* Pods-SiliconLabsApp Dev.release-wireless-gecko.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SiliconLabsApp Dev.release-wireless-gecko.xcconfig"; path = "Pods/Target Support Files/Pods-SiliconLabsApp Dev/Pods-SiliconLabsApp Dev.release-wireless-gecko.xcconfig"; sourceTree = ""; }; + 6E7E1967C516A49F37A0A7B8 /* Pods_WirelessGecko.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_WirelessGecko.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 71F25116C7DF08741307B3E0 /* Pods_BlueGecko.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_BlueGecko.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 722F5EF560719504746B876B /* Pods-BlueGecko.release-wireless-gecko.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BlueGecko.release-wireless-gecko.xcconfig"; path = "Pods/Target Support Files/Pods-BlueGecko/Pods-BlueGecko.release-wireless-gecko.xcconfig"; sourceTree = ""; }; 7928D85C1ECA10FD0075FFCB /* SILHomeKitDebugServicesViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SILHomeKitDebugServicesViewController.h; path = HomeKitDebugApp/ServicesTable/SILHomeKitDebugServicesViewController.h; sourceTree = ""; }; 7928D85D1ECA10FD0075FFCB /* SILHomeKitDebugServicesViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SILHomeKitDebugServicesViewController.m; path = HomeKitDebugApp/ServicesTable/SILHomeKitDebugServicesViewController.m; sourceTree = ""; }; 7928D85F1ECA12070075FFCB /* SILHomeKitDebugServicesViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = SILHomeKitDebugServicesViewController.xib; path = Debug/HomeKit/SILHomeKitDebugServicesViewController.xib; sourceTree = ""; }; @@ -662,8 +924,14 @@ 79E62B4D1ECCA29400344CAA /* SILBluetoothSearch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SILBluetoothSearch.h; sourceTree = ""; }; 79E62B4E1ECCA29400344CAA /* SILBluetoothSearch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SILBluetoothSearch.m; sourceTree = ""; }; 7AAD8E27028334FE640216CD /* Pods_SiliconLabsAppWithoutHomeKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SiliconLabsAppWithoutHomeKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 7D7E90CFE18ED0DFB6F387D5 /* Pods-SiliconLabsAppWithoutHomeKit Dev.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SiliconLabsAppWithoutHomeKit Dev.debug.xcconfig"; path = "Pods/Target Support Files/Pods-SiliconLabsAppWithoutHomeKit Dev/Pods-SiliconLabsAppWithoutHomeKit Dev.debug.xcconfig"; sourceTree = ""; }; + 84342BE824D4F9248E13114A /* Pods_BlueGeckoWithHomeKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_BlueGeckoWithHomeKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 8A73A6BB1453DAE49320F05E /* Pods-SiliconLabsAppWithoutHomeKit.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SiliconLabsAppWithoutHomeKit.release.xcconfig"; path = "Pods/Target Support Files/Pods-SiliconLabsAppWithoutHomeKit/Pods-SiliconLabsAppWithoutHomeKit.release.xcconfig"; sourceTree = ""; }; + 8E2432EAF11ADE0582587F26 /* Pods-SiliconLabsApp Dev.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SiliconLabsApp Dev.release.xcconfig"; path = "Pods/Target Support Files/Pods-SiliconLabsApp Dev/Pods-SiliconLabsApp Dev.release.xcconfig"; sourceTree = ""; }; + 94A7D6CCB3C047F5ECDF876C /* Pods-BlueGeckoWithHomeKit.debug-wireless-gecko.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BlueGeckoWithHomeKit.debug-wireless-gecko.xcconfig"; path = "Pods/Target Support Files/Pods-BlueGeckoWithHomeKit/Pods-BlueGeckoWithHomeKit.debug-wireless-gecko.xcconfig"; sourceTree = ""; }; + 9D503111803F12397900799A /* Pods-BlueGecko.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BlueGecko.release.xcconfig"; path = "Pods/Target Support Files/Pods-BlueGecko/Pods-BlueGecko.release.xcconfig"; sourceTree = ""; }; A058D14EA4646B6D95A1DC6C /* Pods-SiliconLabsApp.debug-wireless-gecko.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SiliconLabsApp.debug-wireless-gecko.xcconfig"; path = "Pods/Target Support Files/Pods-SiliconLabsApp/Pods-SiliconLabsApp.debug-wireless-gecko.xcconfig"; sourceTree = ""; }; + A96DF018704C41E44822DFDB /* Pods-BlueGeckoWithHomeKit.release-wireless-gecko.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BlueGeckoWithHomeKit.release-wireless-gecko.xcconfig"; path = "Pods/Target Support Files/Pods-BlueGeckoWithHomeKit/Pods-BlueGeckoWithHomeKit.release-wireless-gecko.xcconfig"; sourceTree = ""; }; AA0724F51F388D2D001446CA /* SiliconLabsAppTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SiliconLabsAppTests-Bridging-Header.h"; sourceTree = ""; }; AA0724F61F388D2D001446CA /* DebugDeviceFilterViewModelTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DebugDeviceFilterViewModelTests.swift; sourceTree = ""; }; AA0FF4071EFC11AD007C14D3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = SILRetailBeaconDetailsViewController.xib; sourceTree = ""; }; @@ -688,6 +956,12 @@ AAD9E9311F279A670054C387 /* DebugDeviceFilterViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DebugDeviceFilterViewController.swift; path = DebugApp/DevicesTable/DebugDeviceFilterViewController.swift; sourceTree = ""; }; AAD9E9331F279B910054C387 /* SILDebugDeviceFilterViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = SILDebugDeviceFilterViewController.xib; path = Debug/Devices/SILDebugDeviceFilterViewController.xib; sourceTree = ""; }; B581D509B0AA85FC9096885F /* Pods-SiliconLabsApp.debug-wireless gecko.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SiliconLabsApp.debug-wireless gecko.xcconfig"; path = "Pods/Target Support Files/Pods-SiliconLabsApp/Pods-SiliconLabsApp.debug-wireless gecko.xcconfig"; sourceTree = ""; }; + BA98220D8E87584BC34D74E1 /* Pods_Wireless_Gecko.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Wireless_Gecko.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + BBA88A0DF7A10843B48785CA /* Pods-WirelessGecko.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WirelessGecko.release.xcconfig"; path = "Pods/Target Support Files/Pods-WirelessGecko/Pods-WirelessGecko.release.xcconfig"; sourceTree = ""; }; + C2B97654F5DCDC40565223A0 /* Pods-Wireless Gecko.release-wireless-gecko.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Wireless Gecko.release-wireless-gecko.xcconfig"; path = "Pods/Target Support Files/Pods-Wireless Gecko/Pods-Wireless Gecko.release-wireless-gecko.xcconfig"; sourceTree = ""; }; + C96C72B6450C03B91081A26A /* Pods-WirelessGecko.debug-wireless-gecko.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WirelessGecko.debug-wireless-gecko.xcconfig"; path = "Pods/Target Support Files/Pods-WirelessGecko/Pods-WirelessGecko.debug-wireless-gecko.xcconfig"; sourceTree = ""; }; + CC4321107ADA97596BC58909 /* Pods-Wireless Gecko.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Wireless Gecko.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Wireless Gecko/Pods-Wireless Gecko.debug.xcconfig"; sourceTree = ""; }; + D578365DE8C84B43DE844D60 /* Pods-WirelessGecko.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WirelessGecko.debug.xcconfig"; path = "Pods/Target Support Files/Pods-WirelessGecko/Pods-WirelessGecko.debug.xcconfig"; sourceTree = ""; }; D88A34903477559039113A50 /* Pods-SiliconLabsAppWithoutHomeKit.release-wireless-gecko.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SiliconLabsAppWithoutHomeKit.release-wireless-gecko.xcconfig"; path = "Pods/Target Support Files/Pods-SiliconLabsAppWithoutHomeKit/Pods-SiliconLabsAppWithoutHomeKit.release-wireless-gecko.xcconfig"; sourceTree = ""; }; DC380D4C1E89584700898C12 /* SILOTAProgressViewModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SILOTAProgressViewModel.m; sourceTree = ""; }; DC380D4E1E89586300898C12 /* SILOTAProgressViewModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SILOTAProgressViewModel.h; sourceTree = ""; }; @@ -701,6 +975,7 @@ DCB431121E8315EF00EE94F0 /* SILOTAHUDView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = SILOTAHUDView.xib; sourceTree = ""; }; DCE784DD1E7AF0700038C87A /* SILBeaconRegistryEntryViewModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SILBeaconRegistryEntryViewModel.h; path = SiliconLabsApp/ViewModels/SILBeaconRegistryEntryViewModel.h; sourceTree = SOURCE_ROOT; }; DCE784DE1E7AF0930038C87A /* SILBeaconRegistryEntryViewModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SILBeaconRegistryEntryViewModel.m; sourceTree = ""; }; + DD05F35A97FE411FF4B9277B /* Pods-BlueGecko.debug-wireless-gecko.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BlueGecko.debug-wireless-gecko.xcconfig"; path = "Pods/Target Support Files/Pods-BlueGecko/Pods-BlueGecko.debug-wireless-gecko.xcconfig"; sourceTree = ""; }; E406AEFE9A8583311524FBD8 /* Pods-SiliconLabsApp.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SiliconLabsApp.release.xcconfig"; path = "Pods/Target Support Files/Pods-SiliconLabsApp/Pods-SiliconLabsApp.release.xcconfig"; sourceTree = ""; }; E607A34C1A8D1F3000DAAFD3 /* SILCalibrationViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SILCalibrationViewController.h; sourceTree = ""; }; E607A34D1A8D1F3000DAAFD3 /* SILCalibrationViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SILCalibrationViewController.m; sourceTree = ""; }; @@ -772,7 +1047,7 @@ E6C8FF0B1A71869A00DF062F /* SILBarGraphCollectionViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SILBarGraphCollectionViewCell.m; sourceTree = ""; }; E6C8FF0D1A71A9A900DF062F /* SILCollectionViewRightAlignedFlowLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SILCollectionViewRightAlignedFlowLayout.h; sourceTree = ""; }; E6C8FF0E1A71A9A900DF062F /* SILCollectionViewRightAlignedFlowLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SILCollectionViewRightAlignedFlowLayout.m; sourceTree = ""; }; - E6CAA2201A64011900A49DAF /* SiliconLabsApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SiliconLabsApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; + E6CAA2201A64011900A49DAF /* BlueGeckoWithHomeKit.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = BlueGeckoWithHomeKit.app; sourceTree = BUILT_PRODUCTS_DIR; }; E6CAA2241A64011900A49DAF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; E6CAA2251A64011900A49DAF /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; E6CAA2271A64011900A49DAF /* SILAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SILAppDelegate.h; sourceTree = ""; }; @@ -803,6 +1078,9 @@ E6CFEB261A686DC000F216AB /* SILHealthThermometerAppViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SILHealthThermometerAppViewController.m; sourceTree = ""; }; E6D45D351A6EA74C002D9EC4 /* CoreLocation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreLocation.framework; path = System/Library/Frameworks/CoreLocation.framework; sourceTree = SDKROOT; }; E75945505948D0B91B6E3402 /* Pods-SiliconLabsApp.release-wireless gecko.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SiliconLabsApp.release-wireless gecko.xcconfig"; path = "Pods/Target Support Files/Pods-SiliconLabsApp/Pods-SiliconLabsApp.release-wireless gecko.xcconfig"; sourceTree = ""; }; + EE79C090DAF2823DC5A7610A /* Pods-SiliconLabsAppWithoutHomeKit Dev.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SiliconLabsAppWithoutHomeKit Dev.release.xcconfig"; path = "Pods/Target Support Files/Pods-SiliconLabsAppWithoutHomeKit Dev/Pods-SiliconLabsAppWithoutHomeKit Dev.release.xcconfig"; sourceTree = ""; }; + F3FCDDB05872DDFD08FD595A /* Pods-BlueGeckoWithHomeKit.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BlueGeckoWithHomeKit.release.xcconfig"; path = "Pods/Target Support Files/Pods-BlueGeckoWithHomeKit/Pods-BlueGeckoWithHomeKit.release.xcconfig"; sourceTree = ""; }; + F5199A85C35947636C5A3164 /* Pods-SiliconLabsApp Dev.debug-wireless-gecko.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SiliconLabsApp Dev.debug-wireless-gecko.xcconfig"; path = "Pods/Target Support Files/Pods-SiliconLabsApp Dev/Pods-SiliconLabsApp Dev.debug-wireless-gecko.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -813,8 +1091,18 @@ 0C2FCB971F9A542300F4F259 /* CoreBluetooth.framework in Frameworks */, 0C2FCB991F9A542300F4F259 /* CoreLocation.framework in Frameworks */, 0C2FCB9A1F9A542300F4F259 /* QuartzCore.framework in Frameworks */, - 0C2FCB9B1F9A542300F4F259 /* Pods_SiliconLabsApp.framework in Frameworks */, - 301355A997CA76D6D580223F /* Pods_SiliconLabsAppWithoutHomeKit.framework in Frameworks */, + FCFE74AF68F9F5BE332F46B6 /* Pods_BlueGecko.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0F4E518A21525FDC00F58ACE /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 0F4E518B21525FDC00F58ACE /* CoreBluetooth.framework in Frameworks */, + 0F4E518C21525FDC00F58ACE /* CoreLocation.framework in Frameworks */, + 0F4E518D21525FDC00F58ACE /* QuartzCore.framework in Frameworks */, + 2B257CB817ADC2635883B007 /* Pods_WirelessGecko.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -826,7 +1114,7 @@ 0C2FCBDD1F9A675A00F4F259 /* HomeKit.framework in Frameworks */, E6D45D361A6EA74C002D9EC4 /* CoreLocation.framework in Frameworks */, E666CBE71A77298900676C5C /* QuartzCore.framework in Frameworks */, - 4EEACB99918C6244B448E420 /* Pods_SiliconLabsApp.framework in Frameworks */, + 9450946334099D8FAA384ABE /* Pods_BlueGeckoWithHomeKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1103,7 +1391,7 @@ children = ( 07BBA7441BD57FCF00C2B07E /* XML */, ); - name = Services; + path = Services; sourceTree = ""; }; 07BBA7441BD57FCF00C2B07E /* XML */ = { @@ -1112,7 +1400,7 @@ 07BBA7451BD5820C00C2B07E /* SILBluetoothXMLParser.h */, 07BBA7461BD5820C00C2B07E /* SILBluetoothXMLParser.m */, ); - name = XML; + path = XML; sourceTree = ""; }; 07BBA74B1BD5837400C2B07E /* BluetoothModels */ = { @@ -1172,7 +1460,7 @@ 07F48D5B1BEC0AC500C76F6F /* SILCharacteristicFieldRow.h */, 07F48D5E1BEC0B1300C76F6F /* SILFieldRequirementEnforcer.h */, ); - name = Protocols; + path = Protocols; sourceTree = ""; }; 0C3908321FA9C02100934AD1 /* ConnectedLighting */ = { @@ -1185,6 +1473,40 @@ name = ConnectedLighting; sourceTree = ""; }; + 0F34406020ADAB580067397C /* RangeTest */ = { + isa = PBXGroup; + children = ( + 0F34409720AF0E570067397C /* SILRangeTestModeSelectionViewController.xib */, + 0F34409420AF0E250067397C /* RangeTestStoryboard.storyboard */, + ); + path = RangeTest; + sourceTree = ""; + }; + 0F3AC36420ADAA200010091C /* RangeTestApp */ = { + isa = PBXGroup; + children = ( + 4D9E26232212CA5300617DBA /* Board */, + 0F44BCAC20EE5B0100CD27B3 /* Peripheral */, + 0F3AC36520ADAABF0010091C /* SILRangeTestModeSelectionViewController.swift */, + 0F34409A20AF18BA0067397C /* SILRangeTestAppViewController.swift */, + 0F8163C020C52386008B98C6 /* SILRangeTestSettingValue.swift */, + 0F3EB6B620C524C30062A7C1 /* SILRangeTestAppViewModel.swift */, + 0FFDD024210F09A000CFFB5E /* SILRangeTestMovingAverageCalculator.swift */, + 0F75B9D021395E3200E8D9E9 /* SILRangeTestTXValueUpdater.swift */, + ); + path = RangeTestApp; + sourceTree = ""; + }; + 0F44BCAC20EE5B0100CD27B3 /* Peripheral */ = { + isa = PBXGroup; + children = ( + 0FD15EB920BD3D0D00ED43BB /* SILRangeTestPeripheral.swift */, + 0F69656820ECD32A0083C32A /* SILRangeTestManufacturerData.swift */, + 0F44BCAD20EE5E0E00CD27B3 /* SILRangeTestCharacteristic.swift */, + ); + path = Peripheral; + sourceTree = ""; + }; 11CC9F6FE96DECE887FB6DF6 /* Pods */ = { isa = PBXGroup; children = ( @@ -1198,6 +1520,30 @@ 61C2546AB44D8C072A96C83A /* Pods-SiliconLabsAppWithoutHomeKit.debug-wireless-gecko.xcconfig */, 8A73A6BB1453DAE49320F05E /* Pods-SiliconLabsAppWithoutHomeKit.release.xcconfig */, D88A34903477559039113A50 /* Pods-SiliconLabsAppWithoutHomeKit.release-wireless-gecko.xcconfig */, + 48633F2056480FFEA1BD8A72 /* Pods-SiliconLabsApp Dev.debug.xcconfig */, + F5199A85C35947636C5A3164 /* Pods-SiliconLabsApp Dev.debug-wireless-gecko.xcconfig */, + 8E2432EAF11ADE0582587F26 /* Pods-SiliconLabsApp Dev.release.xcconfig */, + 63D66014C77760FCDAC6A134 /* Pods-SiliconLabsApp Dev.release-wireless-gecko.xcconfig */, + 7D7E90CFE18ED0DFB6F387D5 /* Pods-SiliconLabsAppWithoutHomeKit Dev.debug.xcconfig */, + 070E794C717D970F0A0892C4 /* Pods-SiliconLabsAppWithoutHomeKit Dev.debug-wireless-gecko.xcconfig */, + EE79C090DAF2823DC5A7610A /* Pods-SiliconLabsAppWithoutHomeKit Dev.release.xcconfig */, + 5D477CF57EA327218A303591 /* Pods-SiliconLabsAppWithoutHomeKit Dev.release-wireless-gecko.xcconfig */, + CC4321107ADA97596BC58909 /* Pods-Wireless Gecko.debug.xcconfig */, + 40F66980CDB9137B6A8DE02E /* Pods-Wireless Gecko.debug-wireless-gecko.xcconfig */, + 0B98AA271D57BF6AA89CE5DC /* Pods-Wireless Gecko.release.xcconfig */, + C2B97654F5DCDC40565223A0 /* Pods-Wireless Gecko.release-wireless-gecko.xcconfig */, + 4491900FB788A5F0E74824C6 /* Pods-BlueGecko.debug.xcconfig */, + DD05F35A97FE411FF4B9277B /* Pods-BlueGecko.debug-wireless-gecko.xcconfig */, + 9D503111803F12397900799A /* Pods-BlueGecko.release.xcconfig */, + 722F5EF560719504746B876B /* Pods-BlueGecko.release-wireless-gecko.xcconfig */, + 06CC32BDFF67F87AF59FFD4D /* Pods-BlueGeckoWithHomeKit.debug.xcconfig */, + 94A7D6CCB3C047F5ECDF876C /* Pods-BlueGeckoWithHomeKit.debug-wireless-gecko.xcconfig */, + F3FCDDB05872DDFD08FD595A /* Pods-BlueGeckoWithHomeKit.release.xcconfig */, + A96DF018704C41E44822DFDB /* Pods-BlueGeckoWithHomeKit.release-wireless-gecko.xcconfig */, + D578365DE8C84B43DE844D60 /* Pods-WirelessGecko.debug.xcconfig */, + C96C72B6450C03B91081A26A /* Pods-WirelessGecko.debug-wireless-gecko.xcconfig */, + BBA88A0DF7A10843B48785CA /* Pods-WirelessGecko.release.xcconfig */, + 0CA91D794559B3C4861B03B4 /* Pods-WirelessGecko.release-wireless-gecko.xcconfig */, ); name = Pods; sourceTree = ""; @@ -1212,6 +1558,45 @@ path = DebugApp/PopoverViewControllers/ValueEditor; sourceTree = ""; }; + 4D6925E72284540200E7F015 /* BlueGecko */ = { + isa = PBXGroup; + children = ( + 0CB9F1581F9F7DE80089DC65 /* BlueGecko.pch */, + 0C2FCBE11F9A7F7700F4F259 /* Entitlements.entitlements */, + 0C2FCBDB1F9A542400F4F259 /* Info.plist */, + ); + path = BlueGecko; + sourceTree = ""; + }; + 4D6925E82284541200E7F015 /* BlueGeckoWithHomeKit */ = { + isa = PBXGroup; + children = ( + 0CB9F1571F9F7DC60089DC65 /* BlueGeckoWithHomeKit.pch */, + 494F93CB1E7884150057C1E0 /* Entitlements.entitlements */, + E6CAA2241A64011900A49DAF /* Info.plist */, + ); + path = BlueGeckoWithHomeKit; + sourceTree = ""; + }; + 4D6925E92284541A00E7F015 /* WirelessGecko */ = { + isa = PBXGroup; + children = ( + 0F4E51CE2152684500F58ACE /* WirelessGecko.pch */, + 4D6925E6228453B800E7F015 /* Entitlements.entitlements */, + 4D6925EB2284549A00E7F015 /* Info.plist */, + ); + path = WirelessGecko; + sourceTree = ""; + }; + 4D9E26232212CA5300617DBA /* Board */ = { + isa = PBXGroup; + children = ( + 4D9E26242212CA7000617DBA /* SILRangeTestBoardInfo.swift */, + 4D9E261F2212BFB100617DBA /* SILRangeTestBoardFeatures.swift */, + ); + path = Board; + sourceTree = ""; + }; 7928D85B1ECA10A40075FFCB /* ServicesTable */ = { isa = PBXGroup; children = ( @@ -1292,6 +1677,7 @@ 078137E31BE40910001EFE7E /* HealthThermometer */, 078137E21BE408FC001EFE7E /* RetailBeacon */, 078137E11BE408EC001EFE7E /* KeyFob */, + 0F34406020ADAB580067397C /* RangeTest */, E6B3ECA01AAE2C8B005A687F /* SILCalibrationViewController.xib */, E6CAA2321A64011900A49DAF /* LaunchScreen.xib */, E6B3ECA61AAE3E5B005A687F /* SILDeviceSelectionCollectionViewCell.xib */, @@ -1313,6 +1699,7 @@ E67C5BBD1A7FA5BC003628A4 /* KeyFob */, E6D45D311A6E8A80002D9EC4 /* RetailBeaconApp */, 0C3908321FA9C02100934AD1 /* ConnectedLighting */, + 0F3AC36420ADAA200010091C /* RangeTestApp */, ); path = ViewControllers; sourceTree = ""; @@ -1337,6 +1724,12 @@ E621B33E1A65573500223C5A /* CoreBluetooth.framework */, 426AC50AF4550762BDD32A6E /* Pods_SiliconLabsApp.framework */, 7AAD8E27028334FE640216CD /* Pods_SiliconLabsAppWithoutHomeKit.framework */, + 14222593B3D5CABF925418CF /* Pods_SiliconLabsApp_Dev.framework */, + 12C24CC1B29409750D9A1CB2 /* Pods_SiliconLabsAppWithoutHomeKit_Dev.framework */, + BA98220D8E87584BC34D74E1 /* Pods_Wireless_Gecko.framework */, + 71F25116C7DF08741307B3E0 /* Pods_BlueGecko.framework */, + 84342BE824D4F9248E13114A /* Pods_BlueGeckoWithHomeKit.framework */, + 6E7E1967C516A49F37A0A7B8 /* Pods_WirelessGecko.framework */, ); name = Frameworks; sourceTree = ""; @@ -1530,17 +1923,16 @@ E6CAA2211A64011900A49DAF /* Products */, 11CC9F6FE96DECE887FB6DF6 /* Pods */, 495BF3571E5F9D9A002B3F8D /* SiliconLabsApp-Bridging-Header.h */, - 0CB9F1571F9F7DC60089DC65 /* SiliconLabsApp.pch */, - 0CB9F1581F9F7DE80089DC65 /* SiliconLabsAppWithoutHomeKit.pch */, ); sourceTree = ""; }; E6CAA2211A64011900A49DAF /* Products */ = { isa = PBXGroup; children = ( - E6CAA2201A64011900A49DAF /* SiliconLabsApp.app */, + E6CAA2201A64011900A49DAF /* BlueGeckoWithHomeKit.app */, E6CAA2391A64011900A49DAF /* SiliconLabsAppTests.xctest */, - 0C2FCBDA1F9A542300F4F259 /* SiliconLabsAppWithoutHomeKit.app */, + 0C2FCBDA1F9A542300F4F259 /* BlueGecko.app */, + 0F4E51CC21525FDC00F58ACE /* WirelessGecko.app */, ); name = Products; sourceTree = ""; @@ -1548,23 +1940,20 @@ E6CAA2221A64011900A49DAF /* SiliconLabsApp */ = { isa = PBXGroup; children = ( - 494F93CB1E7884150057C1E0 /* SiliconLabsApp.entitlements */, - 0C2FCBE11F9A7F7700F4F259 /* SiliconLabsAppWithoutHomeKit.entitlements */, - 07BBA7401BD5691E00C2B07E /* Services */, E621B33C1A6555F800223C5A /* Base.lproj */, E6B773D71A67082300B93058 /* BluetoothControllers */, E63DD42E1A71449500E0040F /* Categories */, 07F48D5A1BEC0A7C00C76F6F /* Protocols */, E666CBD51A767C0600676C5C /* Helpers */, - E6CAA2301A64011900A49DAF /* Images.xcassets */, 07B1AD741BFCFF6900D4D454 /* ViewModels */, E621B3491A655AFE00223C5A /* DataModels */, + E621B33D1A65562400223C5A /* ViewControllers */, + E666CBE81A77C70700676C5C /* Views */, + 07BBA7401BD5691E00C2B07E /* Services */, + E6CAA2231A64011900A49DAF /* Supporting Files */, E6CAA2271A64011900A49DAF /* SILAppDelegate.h */, E6CAA2281A64011900A49DAF /* SILAppDelegate.m */, 498311D31BF29A5400D49FF2 /* SILCharacteristicEditEnabler.h */, - E6CAA2231A64011900A49DAF /* Supporting Files */, - E621B33D1A65562400223C5A /* ViewControllers */, - E666CBE81A77C70700676C5C /* Views */, ); path = SiliconLabsApp; sourceTree = ""; @@ -1572,9 +1961,11 @@ E6CAA2231A64011900A49DAF /* Supporting Files */ = { isa = PBXGroup; children = ( + 4D6925E72284540200E7F015 /* BlueGecko */, + 4D6925E82284541200E7F015 /* BlueGeckoWithHomeKit */, + 4D6925E92284541A00E7F015 /* WirelessGecko */, 07BBA74F1BD599F800C2B07E /* XML */, - E6CAA2241A64011900A49DAF /* Info.plist */, - 0C2FCBDB1F9A542400F4F259 /* Info-WithoutHomeKit.plist */, + E6CAA2301A64011900A49DAF /* Images.xcassets */, 0C744A481FB369FD0016B3C5 /* ExportOptions.plist */, E6CAA2251A64011900A49DAF /* main.m */, ); @@ -1639,46 +2030,61 @@ /* End PBXGroup section */ /* Begin PBXNativeTarget section */ - 0C2FCB001F9A542300F4F259 /* SiliconLabsAppWithoutHomeKit */ = { + 0C2FCB001F9A542300F4F259 /* BlueGecko */ = { isa = PBXNativeTarget; - buildConfigurationList = 0C2FCBD51F9A542300F4F259 /* Build configuration list for PBXNativeTarget "SiliconLabsAppWithoutHomeKit" */; + buildConfigurationList = 0C2FCBD51F9A542300F4F259 /* Build configuration list for PBXNativeTarget "BlueGecko" */; buildPhases = ( 0C2FCB011F9A542300F4F259 /* [CP] Check Pods Manifest.lock */, 0C2FCB021F9A542300F4F259 /* Sources */, 0C2FCB961F9A542300F4F259 /* Frameworks */, 0C2FCB9C1F9A542300F4F259 /* Resources */, - 0C2FCBD21F9A542300F4F259 /* ShellScript */, 0C2FCBD31F9A542300F4F259 /* [CP] Embed Pods Frameworks */, - 0C2FCBD41F9A542300F4F259 /* [CP] Copy Pods Resources */, ); buildRules = ( ); dependencies = ( ); - name = SiliconLabsAppWithoutHomeKit; + name = BlueGecko; + productName = SiliconLabsApp; + productReference = 0C2FCBDA1F9A542300F4F259 /* BlueGecko.app */; + productType = "com.apple.product-type.application"; + }; + 0F4E50F321525FDC00F58ACE /* WirelessGecko */ = { + isa = PBXNativeTarget; + buildConfigurationList = 0F4E51C721525FDC00F58ACE /* Build configuration list for PBXNativeTarget "WirelessGecko" */; + buildPhases = ( + 0F4E50F421525FDC00F58ACE /* [CP] Check Pods Manifest.lock */, + 0F4E50F521525FDC00F58ACE /* Sources */, + 0F4E518A21525FDC00F58ACE /* Frameworks */, + 0F4E519021525FDC00F58ACE /* Resources */, + 0F4E51C621525FDC00F58ACE /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = WirelessGecko; productName = SiliconLabsApp; - productReference = 0C2FCBDA1F9A542300F4F259 /* SiliconLabsAppWithoutHomeKit.app */; + productReference = 0F4E51CC21525FDC00F58ACE /* WirelessGecko.app */; productType = "com.apple.product-type.application"; }; - E6CAA21F1A64011900A49DAF /* SiliconLabsApp */ = { + E6CAA21F1A64011900A49DAF /* BlueGeckoWithHomeKit */ = { isa = PBXNativeTarget; - buildConfigurationList = E6CAA2431A64011900A49DAF /* Build configuration list for PBXNativeTarget "SiliconLabsApp" */; + buildConfigurationList = E6CAA2431A64011900A49DAF /* Build configuration list for PBXNativeTarget "BlueGeckoWithHomeKit" */; buildPhases = ( BB5B54324EC59BC38D43DF4A /* [CP] Check Pods Manifest.lock */, E6CAA21C1A64011900A49DAF /* Sources */, E6CAA21D1A64011900A49DAF /* Frameworks */, E6CAA21E1A64011900A49DAF /* Resources */, - 071C49B01C33273E003F80B8 /* ShellScript */, 2647BDE6F2DEEDB67778BAD3 /* [CP] Embed Pods Frameworks */, - CEB0F3BF6A3483B3B06517C2 /* [CP] Copy Pods Resources */, ); buildRules = ( ); dependencies = ( ); - name = SiliconLabsApp; + name = BlueGeckoWithHomeKit; productName = SiliconLabsApp; - productReference = E6CAA2201A64011900A49DAF /* SiliconLabsApp.app */; + productReference = E6CAA2201A64011900A49DAF /* BlueGeckoWithHomeKit.app */; productType = "com.apple.product-type.application"; }; E6CAA2381A64011900A49DAF /* SiliconLabsAppTests */ = { @@ -1706,7 +2112,7 @@ isa = PBXProject; attributes = { CLASSPREFIX = SIL; - LastUpgradeCheck = 0830; + LastUpgradeCheck = 1020; ORGANIZATIONNAME = SiliconLabs; TargetAttributes = { 0C2FCB001F9A542300F4F259 = { @@ -1718,11 +2124,15 @@ }; }; }; + 0F4E50F321525FDC00F58ACE = { + DevelopmentTeam = 52444FG85C; + ProvisioningStyle = Automatic; + }; E6CAA21F1A64011900A49DAF = { CreatedOnToolsVersion = 6.1.1; - DevelopmentTeam = THP5EV5EJ9; + DevelopmentTeam = 52444FG85C; LastSwiftMigration = 0820; - ProvisioningStyle = Manual; + ProvisioningStyle = Automatic; SystemCapabilities = { com.apple.BackgroundModes = { enabled = 0; @@ -1754,6 +2164,7 @@ developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( + English, en, Base, ); @@ -1762,8 +2173,9 @@ projectDirPath = ""; projectRoot = ""; targets = ( - E6CAA21F1A64011900A49DAF /* SiliconLabsApp */, - 0C2FCB001F9A542300F4F259 /* SiliconLabsAppWithoutHomeKit */, + 0C2FCB001F9A542300F4F259 /* BlueGecko */, + E6CAA21F1A64011900A49DAF /* BlueGeckoWithHomeKit */, + 0F4E50F321525FDC00F58ACE /* WirelessGecko */, E6CAA2381A64011900A49DAF /* SiliconLabsAppTests */, ); }; @@ -1777,15 +2189,17 @@ 0C2FCB9D1F9A542300F4F259 /* SILOTAProgressViewController.xib in Resources */, 0C2FCB9E1F9A542300F4F259 /* SILDebugDeviceFilterViewController.xib in Resources */, 0C2FCB9F1F9A542300F4F259 /* SILBeaconRegistryEntryCell.xib in Resources */, - 0C55454F1FC47FD100B0E98D /* SILConnectedLightingViewController.xib in Resources */, + E48275BE20D812BE006D1478 /* SILConnectedLightingViewController.xib in Resources */, 0C2FCBA01F9A542300F4F259 /* SILDebugDeviceTableViewCell~iphone.xib in Resources */, 0C2FCBA11F9A542300F4F259 /* SILDebugDeviceTableViewCell~ipad.xib in Resources */, 0C2FCBA21F9A542300F4F259 /* SILRetailBeaconDetailsHeaderView.xib in Resources */, 0C2FCBA31F9A542300F4F259 /* SILDebugAdvDetailTableViewCell.xib in Resources */, + 0F34409920AF0E570067397C /* SILRangeTestModeSelectionViewController.xib in Resources */, 0C2FCBA41F9A542300F4F259 /* SILDebugDeviceViewController.xib in Resources */, 0C2FCBA51F9A542300F4F259 /* SILDebugCharacteristicToggleFieldTableViewCell.xib in Resources */, 0C2FCBA61F9A542300F4F259 /* SILOTAHUDView.xib in Resources */, 0C2FCBA71F9A542300F4F259 /* SILDebugCharacteristicValueFieldTableViewCell.xib in Resources */, + 0F34409620AF0E250067397C /* RangeTestStoryboard.storyboard in Resources */, 0C2FCBA81F9A542300F4F259 /* SILActivityBarViewController.xib in Resources */, 0C2FCBA91F9A542300F4F259 /* SILKeyFobTableViewCell~ipad.xib in Resources */, 0C2FCBAA1F9A542300F4F259 /* SILDebugAdvDetailCollectionViewCell.xib in Resources */, @@ -1827,6 +2241,65 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 0F4E519021525FDC00F58ACE /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 0F4E519121525FDC00F58ACE /* SILOTAProgressViewController.xib in Resources */, + 0F4E519221525FDC00F58ACE /* SILDebugDeviceFilterViewController.xib in Resources */, + 0F4E519321525FDC00F58ACE /* SILBeaconRegistryEntryCell.xib in Resources */, + 0F4E519421525FDC00F58ACE /* SILConnectedLightingViewController.xib in Resources */, + 0F4E519521525FDC00F58ACE /* SILDebugDeviceTableViewCell~iphone.xib in Resources */, + 0F4E519621525FDC00F58ACE /* SILDebugDeviceTableViewCell~ipad.xib in Resources */, + 0F4E519721525FDC00F58ACE /* SILRetailBeaconDetailsHeaderView.xib in Resources */, + 0F4E519821525FDC00F58ACE /* SILDebugAdvDetailTableViewCell.xib in Resources */, + 0F4E519921525FDC00F58ACE /* SILRangeTestModeSelectionViewController.xib in Resources */, + 0F4E519A21525FDC00F58ACE /* SILDebugDeviceViewController.xib in Resources */, + 0F4E519B21525FDC00F58ACE /* SILDebugCharacteristicToggleFieldTableViewCell.xib in Resources */, + 0F4E519C21525FDC00F58ACE /* SILOTAHUDView.xib in Resources */, + 0F4E519D21525FDC00F58ACE /* SILDebugCharacteristicValueFieldTableViewCell.xib in Resources */, + 0F4E519E21525FDC00F58ACE /* RangeTestStoryboard.storyboard in Resources */, + 0F4E519F21525FDC00F58ACE /* SILActivityBarViewController.xib in Resources */, + 0F4E51A021525FDC00F58ACE /* SILKeyFobTableViewCell~ipad.xib in Resources */, + 0F4E51A121525FDC00F58ACE /* SILDebugAdvDetailCollectionViewCell.xib in Resources */, + 0F4E51A221525FDC00F58ACE /* SILDebugServiceTableViewCell~iphone.xib in Resources */, + 0F4E51A321525FDC00F58ACE /* SILDeviceSelectionViewController.xib in Resources */, + 0F4E51A421525FDC00F58ACE /* SILDebugSpacerTableViewCell.xib in Resources */, + 0F4E51A521525FDC00F58ACE /* SILFindKeyFobViewController.xib in Resources */, + 0F4E51A621525FDC00F58ACE /* SILDebugCharacteristicEncodingFieldTableViewCell.xib in Resources */, + 0F4E51A721525FDC00F58ACE /* SILDebugCharacteristicTableViewCell~ipad.xib in Resources */, + 0F4E51A821525FDC00F58ACE /* SILDebugServicesViewController.xib in Resources */, + 0F4E51A921525FDC00F58ACE /* XML in Resources */, + 0F4E51AA21525FDC00F58ACE /* SILDebugCharacteristicEnumerationFieldTableViewCell.xib in Resources */, + 0F4E51AB21525FDC00F58ACE /* SILPopoverViewController.xib in Resources */, + 0F4E51AC21525FDC00F58ACE /* SILKeyFobTableSectionHeaderView.xib in Resources */, + 0F4E51AD21525FDC00F58ACE /* SILDebugAdvDetailsViewController.xib in Resources */, + 0F4E51AE21525FDC00F58ACE /* SILRetailBeaconDetailsViewController.xib in Resources */, + 0F4E51AF21525FDC00F58ACE /* SILKeyFobViewController.xib in Resources */, + 0F4E51B021525FDC00F58ACE /* SILDebugCharacteristicPropertyView.xib in Resources */, + 0F4E51B121525FDC00F58ACE /* SILAppSelectionViewController.xib in Resources */, + 0F4E51B221525FDC00F58ACE /* SILHealthThermometerAppViewController.xib in Resources */, + 0F4E51B321525FDC00F58ACE /* SILDeviceSelectionCollectionViewCell.xib in Resources */, + 0F4E51B421525FDC00F58ACE /* SILRetailBeaconAppViewController.xib in Resources */, + 0F4E51B521525FDC00F58ACE /* SILDebugServiceTableViewCell~ipad.xib in Resources */, + 0F4E51B621525FDC00F58ACE /* SILKeyFobTableViewCell~iphone.xib in Resources */, + 0F4E51B721525FDC00F58ACE /* SILAppSelectionTableViewCell.xib in Resources */, + 0F4E51B821525FDC00F58ACE /* SILAppSelectionHelpViewController.xib in Resources */, + 0F4E51B921525FDC00F58ACE /* SILDebugCharacteristicEncodingViewController.xib in Resources */, + 0F4E51BA21525FDC00F58ACE /* SILOTASetupViewController.xib in Resources */, + 0F4E51BB21525FDC00F58ACE /* SILValueFieldEditorViewController.xib in Resources */, + 0F4E51BC21525FDC00F58ACE /* SILCalibrationViewController.xib in Resources */, + 0F4E51BD21525FDC00F58ACE /* SILBarGraphCollectionViewCell.xib in Resources */, + 0F4E51BE21525FDC00F58ACE /* SILDebugHeaderView.xib in Resources */, + 0F4E51BF21525FDC00F58ACE /* SILTextFieldEntryCell.xib in Resources */, + 0F4E51C021525FDC00F58ACE /* LaunchScreen.xib in Resources */, + 0F4E51C121525FDC00F58ACE /* Images.xcassets in Resources */, + 0F4E51C221525FDC00F58ACE /* SILDebugEnumerationValueTableViewCell.xib in Resources */, + 0F4E51C321525FDC00F58ACE /* SILDebugCharacteristicEnumerationListViewController.xib in Resources */, + 0F4E51C421525FDC00F58ACE /* SILDebugCharacteristicTableViewCell~iphone.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; E6CAA21E1A64011900A49DAF /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -1842,6 +2315,7 @@ 078138071BE40AA5001EFE7E /* SILDebugCharacteristicToggleFieldTableViewCell.xib in Resources */, DCB431131E8315EF00EE94F0 /* SILOTAHUDView.xib in Resources */, 078138081BE40AA5001EFE7E /* SILDebugCharacteristicValueFieldTableViewCell.xib in Resources */, + 0F34409820AF0E570067397C /* SILRangeTestModeSelectionViewController.xib in Resources */, 492CA4B21E4E0DD700502AC9 /* SILActivityBarViewController.xib in Resources */, 078138141BE40D2D001EFE7E /* SILKeyFobTableViewCell~ipad.xib in Resources */, 078137F01BE40A8C001EFE7E /* SILDebugAdvDetailCollectionViewCell.xib in Resources */, @@ -1857,6 +2331,7 @@ 07BBA7501BD599F800C2B07E /* XML in Resources */, 078138031BE40AA5001EFE7E /* SILDebugCharacteristicEnumerationFieldTableViewCell.xib in Resources */, 49FB4BED1E7A2EC200223F3E /* SILPopoverViewController.xib in Resources */, + 0F34409520AF0E250067397C /* RangeTestStoryboard.storyboard in Resources */, 078138131BE40D2D001EFE7E /* SILKeyFobTableSectionHeaderView.xib in Resources */, 0763AC4C1BFE8F5400EBE94B /* SILDebugAdvDetailsViewController.xib in Resources */, AA0FF4081EFC11AD007C14D3 /* SILRetailBeaconDetailsViewController.xib in Resources */, @@ -1898,19 +2373,6 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 071C49B01C33273E003F80B8 /* ShellScript */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Fabric/run\" d4644999f9acaab70a6af52eebed37881b8dc107 3ac40070001448c72125e7becb3d822cc0a1f74a30c6327231b6eb046bdd7e4e"; - }; 0C2FCB011F9A542300F4F259 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -1922,33 +2384,23 @@ ); name = "[CP] Check Pods Manifest.lock"; outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-SiliconLabsAppWithoutHomeKit-checkManifestLockResult.txt", + "$(DERIVED_FILE_DIR)/Pods-BlueGecko-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - 0C2FCBD21F9A542300F4F259 /* ShellScript */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Fabric/run\" d4644999f9acaab70a6af52eebed37881b8dc107 3ac40070001448c72125e7becb3d822cc0a1f74a30c6327231b6eb046bdd7e4e"; - }; 0C2FCBD31F9A542300F4F259 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( - "${SRCROOT}/Pods/Target Support Files/Pods-SiliconLabsAppWithoutHomeKit/Pods-SiliconLabsAppWithoutHomeKit-frameworks.sh", + "${SRCROOT}/Pods/Target Support Files/Pods-BlueGecko/Pods-BlueGecko-frameworks.sh", + "${BUILT_PRODUCTS_DIR}/ActionSheetPicker-3.0/ActionSheetPicker_3_0.framework", + "${BUILT_PRODUCTS_DIR}/ChameleonFramework/ChameleonFramework.framework", + "${BUILT_PRODUCTS_DIR}/Charts/Charts.framework", "${BUILT_PRODUCTS_DIR}/Eddystone/Eddystone.framework", "${BUILT_PRODUCTS_DIR}/IP-UIKit-Wisdom/IP_UIKit_Wisdom.framework", "${BUILT_PRODUCTS_DIR}/KVOController/KVOController.framework", @@ -1961,6 +2413,9 @@ ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ActionSheetPicker_3_0.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ChameleonFramework.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Charts.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Eddystone.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/IP_UIKit_Wisdom.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/KVOController.framework", @@ -1973,31 +2428,37 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-SiliconLabsAppWithoutHomeKit/Pods-SiliconLabsAppWithoutHomeKit-frameworks.sh\"\n"; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-BlueGecko/Pods-BlueGecko-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - 0C2FCBD41F9A542300F4F259 /* [CP] Copy Pods Resources */ = { + 0F4E50F421525FDC00F58ACE /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", ); - name = "[CP] Copy Pods Resources"; + name = "[CP] Check Pods Manifest.lock"; outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-WirelessGecko-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-SiliconLabsAppWithoutHomeKit/Pods-SiliconLabsAppWithoutHomeKit-resources.sh\"\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - 2647BDE6F2DEEDB67778BAD3 /* [CP] Embed Pods Frameworks */ = { + 0F4E51C621525FDC00F58ACE /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( - "${SRCROOT}/Pods/Target Support Files/Pods-SiliconLabsApp/Pods-SiliconLabsApp-frameworks.sh", + "${SRCROOT}/Pods/Target Support Files/Pods-WirelessGecko/Pods-WirelessGecko-frameworks.sh", + "${BUILT_PRODUCTS_DIR}/ActionSheetPicker-3.0/ActionSheetPicker_3_0.framework", + "${BUILT_PRODUCTS_DIR}/ChameleonFramework/ChameleonFramework.framework", + "${BUILT_PRODUCTS_DIR}/Charts/Charts.framework", "${BUILT_PRODUCTS_DIR}/Eddystone/Eddystone.framework", "${BUILT_PRODUCTS_DIR}/IP-UIKit-Wisdom/IP_UIKit_Wisdom.framework", "${BUILT_PRODUCTS_DIR}/KVOController/KVOController.framework", @@ -2010,6 +2471,9 @@ ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ActionSheetPicker_3_0.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ChameleonFramework.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Charts.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Eddystone.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/IP_UIKit_Wisdom.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/KVOController.framework", @@ -2022,40 +2486,65 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-SiliconLabsApp/Pods-SiliconLabsApp-frameworks.sh\"\n"; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-WirelessGecko/Pods-WirelessGecko-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - BB5B54324EC59BC38D43DF4A /* [CP] Check Pods Manifest.lock */ = { + 2647BDE6F2DEEDB67778BAD3 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", + "${SRCROOT}/Pods/Target Support Files/Pods-BlueGeckoWithHomeKit/Pods-BlueGeckoWithHomeKit-frameworks.sh", + "${BUILT_PRODUCTS_DIR}/ActionSheetPicker-3.0/ActionSheetPicker_3_0.framework", + "${BUILT_PRODUCTS_DIR}/ChameleonFramework/ChameleonFramework.framework", + "${BUILT_PRODUCTS_DIR}/Charts/Charts.framework", + "${BUILT_PRODUCTS_DIR}/Eddystone/Eddystone.framework", + "${BUILT_PRODUCTS_DIR}/IP-UIKit-Wisdom/IP_UIKit_Wisdom.framework", + "${BUILT_PRODUCTS_DIR}/KVOController/KVOController.framework", + "${BUILT_PRODUCTS_DIR}/MZTimerLabel/MZTimerLabel.framework", + "${BUILT_PRODUCTS_DIR}/PureLayout/PureLayout.framework", + "${BUILT_PRODUCTS_DIR}/SVProgressHUD/SVProgressHUD.framework", + "${BUILT_PRODUCTS_DIR}/UICircularProgressRing/UICircularProgressRing.framework", + "${BUILT_PRODUCTS_DIR}/WYPopoverController/WYPopoverController.framework", + "${BUILT_PRODUCTS_DIR}/XMLDictionary/XMLDictionary.framework", ); - name = "[CP] Check Pods Manifest.lock"; + name = "[CP] Embed Pods Frameworks"; outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-SiliconLabsApp-checkManifestLockResult.txt", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ActionSheetPicker_3_0.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ChameleonFramework.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Charts.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Eddystone.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/IP_UIKit_Wisdom.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/KVOController.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MZTimerLabel.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/PureLayout.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SVProgressHUD.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/UICircularProgressRing.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/WYPopoverController.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/XMLDictionary.framework", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-BlueGeckoWithHomeKit/Pods-BlueGeckoWithHomeKit-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - CEB0F3BF6A3483B3B06517C2 /* [CP] Copy Pods Resources */ = { + BB5B54324EC59BC38D43DF4A /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", ); - name = "[CP] Copy Pods Resources"; + name = "[CP] Check Pods Manifest.lock"; outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-BlueGeckoWithHomeKit-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-SiliconLabsApp/Pods-SiliconLabsApp-resources.sh\"\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ @@ -2069,6 +2558,7 @@ 0C2FCB041F9A542300F4F259 /* SILDebugCharacteristicEncodingFieldTableViewCell.m in Sources */, 0C2FCB051F9A542300F4F259 /* SILOTAUICoordinator.m in Sources */, 0C2FCB061F9A542300F4F259 /* SILActivityBarViewController.m in Sources */, + 4D9E26212212BFB200617DBA /* SILRangeTestBoardFeatures.swift in Sources */, 0C2FCB071F9A542300F4F259 /* SILDebugAdvDetailsCollectionView.m in Sources */, 0C2FCB081F9A542300F4F259 /* SILAppearance.m in Sources */, 0C2FCB091F9A542300F4F259 /* SILDiscoveredPeripheralDisplayData.m in Sources */, @@ -2108,6 +2598,7 @@ 0C2FCB2E1F9A542300F4F259 /* SILAdvertisementDataModel.m in Sources */, 0C2FCB2F1F9A542300F4F259 /* SILCharacteristicTableModel.m in Sources */, 0C2FCB301F9A542300F4F259 /* SILBeaconDataModel.m in Sources */, + 0F3EB6B820C524C30062A7C1 /* SILRangeTestAppViewModel.swift in Sources */, 0C2FCB311F9A542300F4F259 /* SILDebugCharacteristicPropertyView.m in Sources */, 0C2FCB321F9A542300F4F259 /* CBPeripheral+Services.m in Sources */, 0C2FCB331F9A542300F4F259 /* SILDebugProperty.m in Sources */, @@ -2135,19 +2626,23 @@ 0C2FCB481F9A542300F4F259 /* SILEddystoneBeaconViewModel.m in Sources */, 0C2FCB491F9A542300F4F259 /* SILBluetoothDescriptorModel.m in Sources */, 0C2FCB4A1F9A542300F4F259 /* SILRoundedViewBehaviour.m in Sources */, + 0F8163C220C52386008B98C6 /* SILRangeTestSettingValue.swift in Sources */, 0C2FCB4B1F9A542300F4F259 /* EddystoneBeacon.swift in Sources */, + 0F3AC36920ADAAC60010091C /* SILRangeTestModeSelectionViewController.swift in Sources */, + 0FD15EBB20BD3D0D00ED43BB /* SILRangeTestPeripheral.swift in Sources */, 0C2FCB4C1F9A542300F4F259 /* SILAltBeaconViewModel.m in Sources */, 0C2FCB4D1F9A542300F4F259 /* SILKeyValueViewModel.m in Sources */, 0C2FCB4E1F9A542300F4F259 /* SILDebugCharacteristicEnumerationFieldTableViewCell.m in Sources */, + 0F44BCAF20EE5E0E00CD27B3 /* SILRangeTestCharacteristic.swift in Sources */, 0C2FCB4F1F9A542300F4F259 /* SILTemperatureMeasurement.m in Sources */, 0C2FCB501F9A542300F4F259 /* SILRetailBeaconAppViewController.m in Sources */, 0C2FCB511F9A542300F4F259 /* SILBeaconDataViewModel.m in Sources */, 0C2FCB521F9A542300F4F259 /* SILOTAFirmwareUpdate.m in Sources */, 0C2FCB531F9A542300F4F259 /* SILBodySensorLocation.m in Sources */, 0C2FCB541F9A542300F4F259 /* TextFieldTableViewCell.swift in Sources */, + 0C08FD5820CB1CA90016CABC /* SILConnectedLightingViewController.m in Sources */, 0C2FCB551F9A542300F4F259 /* SILCharacteristicFieldBuilder.m in Sources */, 0C2FCB561F9A542300F4F259 /* SILApp.m in Sources */, - 0C5545501FC47FD400B0E98D /* SILConnectedLightingViewController.m in Sources */, 0C2FCB571F9A542300F4F259 /* UIFont+Extensions.swift in Sources */, 0C2FCB581F9A542300F4F259 /* SILDebugServicesViewController.m in Sources */, 0C2FCB591F9A542300F4F259 /* SILBeacon.m in Sources */, @@ -2156,6 +2651,7 @@ 0C2FCB5C1F9A542300F4F259 /* SILOTASetupViewController.m in Sources */, 0C2FCB5F1F9A542300F4F259 /* WYPopoverController+SILHelpers.m in Sources */, 0C2FCB601F9A542300F4F259 /* SILUUIDProvider.m in Sources */, + 0F392514214FA15F00D74963 /* SILRangeTestMovingAverageCalculator.swift in Sources */, 0C2FCB621F9A542300F4F259 /* SILDebugSpacerTableViewCell.m in Sources */, 0C2FCB631F9A542300F4F259 /* SILOTAFirmwareUpdateManager.m in Sources */, 0C2FCB641F9A542300F4F259 /* SILOTAProgressViewController.m in Sources */, @@ -2171,7 +2667,9 @@ 0C2FCB6F1F9A542300F4F259 /* SILAppSelectionViewController.m in Sources */, 0C2FCB701F9A542300F4F259 /* SILDebugHeaderView.m in Sources */, 0C2FCB711F9A542300F4F259 /* SILKeyFobTableViewCell.m in Sources */, + 4D9E26262212CA7000617DBA /* SILRangeTestBoardInfo.swift in Sources */, 0C2FCB721F9A542300F4F259 /* SILCentralManagerBuilder.m in Sources */, + 0F34409C20AF18BA0067397C /* SILRangeTestAppViewController.swift in Sources */, 0C2FCB731F9A542300F4F259 /* SILOTAFirmwareUpdateViewModel.m in Sources */, 0C2FCB741F9A542300F4F259 /* UIView+SILAnimations.m in Sources */, 0C2FCB751F9A542300F4F259 /* SILValueFieldRowModel.m in Sources */, @@ -2194,6 +2692,7 @@ 0C2FCB871F9A542300F4F259 /* SILIBeaconViewModel.m in Sources */, 0C2FCB891F9A542300F4F259 /* SILBluetoothBitModel.m in Sources */, 0C2FCB8A1F9A542300F4F259 /* SILKeyFobTableSectionHeaderView.m in Sources */, + 0F392515214FA16100D74963 /* SILRangeTestTXValueUpdater.swift in Sources */, 0C2FCB8B1F9A542300F4F259 /* NSDictionary+SILErrorCode.m in Sources */, 0C2FCB8C1F9A542300F4F259 /* GradientView.swift in Sources */, 0C2FCB8E1F9A542300F4F259 /* KZBehaviour.m in Sources */, @@ -2201,12 +2700,170 @@ 0C2FCB901F9A542300F4F259 /* SILBeaconRegistryEntry.m in Sources */, 0C2FCB911F9A542300F4F259 /* SILBarGraphCollectionViewCell.m in Sources */, 0C2FCB921F9A542300F4F259 /* SILDebugCharacteristicEnumerationListViewController.m in Sources */, + 0F69656A20ECD32A0083C32A /* SILRangeTestManufacturerData.swift in Sources */, 0C2FCB931F9A542300F4F259 /* NSError+SILHelpers.m in Sources */, 0C2FCB941F9A542300F4F259 /* SILAdvertisementDataViewModel.m in Sources */, 0C2FCB951F9A542300F4F259 /* SILEncodingPseudoFieldRowModel.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; + 0F4E50F521525FDC00F58ACE /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 0F4E50F621525FDC00F58ACE /* SILBluetoothFieldModel.m in Sources */, + 0F4E50F721525FDC00F58ACE /* SILDebugCharacteristicEncodingFieldTableViewCell.m in Sources */, + 0F4E50F821525FDC00F58ACE /* SILOTAUICoordinator.m in Sources */, + 0F4E50F921525FDC00F58ACE /* SILActivityBarViewController.m in Sources */, + 4D9E26222212BFB200617DBA /* SILRangeTestBoardFeatures.swift in Sources */, + 0F4E50FA21525FDC00F58ACE /* SILDebugAdvDetailsCollectionView.m in Sources */, + 0F4E50FB21525FDC00F58ACE /* SILAppearance.m in Sources */, + 0F4E50FC21525FDC00F58ACE /* SILDiscoveredPeripheralDisplayData.m in Sources */, + 0F4E50FD21525FDC00F58ACE /* SILBigRedButton.m in Sources */, + 0F4E50FE21525FDC00F58ACE /* SILDebugCharacteristicTableViewCell.m in Sources */, + 0F4E50FF21525FDC00F58ACE /* SILBluetoothModelManager.m in Sources */, + 0F4E510021525FDC00F58ACE /* SILSettings.m in Sources */, + 0F4E510121525FDC00F58ACE /* SILWeakTargetWrapper.m in Sources */, + 0F4E510221525FDC00F58ACE /* SILAlertBarView.m in Sources */, + 0F4E510321525FDC00F58ACE /* SILBeaconRegistry.m in Sources */, + 0F4E510421525FDC00F58ACE /* SILDebugServiceTableViewCell.m in Sources */, + 0F4E510521525FDC00F58ACE /* SILDebugAdvDetailsViewController.m in Sources */, + 0F4E510621525FDC00F58ACE /* SILDeviceSelectionViewModel.m in Sources */, + 0F4E510721525FDC00F58ACE /* SILValueFieldEditorViewController.m in Sources */, + 0F4E510821525FDC00F58ACE /* SILBeaconViewModel.m in Sources */, + 0F4E510921525FDC00F58ACE /* SILDeviceSelectionViewController.m in Sources */, + 0F4E510A21525FDC00F58ACE /* SILCharacteristicFieldValueResolver.m in Sources */, + 0F4E510B21525FDC00F58ACE /* SILBluetoothBitFieldModel.m in Sources */, + 0F4E510C21525FDC00F58ACE /* SILDiscoveredPeripheralDisplayDataViewModel.m in Sources */, + 0F4E510D21525FDC00F58ACE /* SILDebugDeviceTableViewCell.m in Sources */, + 0F4E510E21525FDC00F58ACE /* DebugDeviceFilterViewController.swift in Sources */, + 0F4E510F21525FDC00F58ACE /* SILDebugAdvDetailCollectionViewCell.m in Sources */, + 0F4E511021525FDC00F58ACE /* SILHealthThermometerAppViewController.m in Sources */, + 0F4E511121525FDC00F58ACE /* SILProximityCalculator.m in Sources */, + 0F4E511221525FDC00F58ACE /* SILDoubleKeyDictionaryPair.m in Sources */, + 0F4E511321525FDC00F58ACE /* SILBluetoothEnumerationModel.m in Sources */, + 0F4E511421525FDC00F58ACE /* RSSISliderTableViewCell.swift in Sources */, + 0F4E511521525FDC00F58ACE /* SILBGBeaconViewModel.m in Sources */, + 0F4E511621525FDC00F58ACE /* SILDebugEnumerationValueTableViewCell.m in Sources */, + 0F4E511721525FDC00F58ACE /* SILDeviceSelectionCollectionViewCell.m in Sources */, + 0F4E511821525FDC00F58ACE /* SILDebugCharacteristicValueFieldTableViewCell.m in Sources */, + 0F4E511921525FDC00F58ACE /* UIImage+SILImages.m in Sources */, + 0F4E511A21525FDC00F58ACE /* DebugDeviceFilterViewModel.swift in Sources */, + 0F4E511B21525FDC00F58ACE /* TLMData.swift in Sources */, + 0F4E511C21525FDC00F58ACE /* UITableViewCell+SILHelpers.m in Sources */, + 0F4E511D21525FDC00F58ACE /* SILTextFieldEntryCell.m in Sources */, + 0F4E511E21525FDC00F58ACE /* SILAdvertisementDataModel.m in Sources */, + 0F4E511F21525FDC00F58ACE /* SILCharacteristicTableModel.m in Sources */, + 0F4E512021525FDC00F58ACE /* SILBeaconDataModel.m in Sources */, + 0F4E512121525FDC00F58ACE /* SILRangeTestAppViewModel.swift in Sources */, + 0F4E512221525FDC00F58ACE /* SILDebugCharacteristicPropertyView.m in Sources */, + 0F4E512321525FDC00F58ACE /* CBPeripheral+Services.m in Sources */, + 0F4E512421525FDC00F58ACE /* SILDebugProperty.m in Sources */, + 0F4E512521525FDC00F58ACE /* SILPopoverViewController.m in Sources */, + 0F4E512621525FDC00F58ACE /* SILSegmentedControl.m in Sources */, + 0F4E512721525FDC00F58ACE /* SILRetailBeaconDetailsHeaderView.m in Sources */, + 0F4E512821525FDC00F58ACE /* SILOTAHUDPeripheralViewModel.m in Sources */, + 0F4E512921525FDC00F58ACE /* SILDebugAdvDetailTableViewCell.m in Sources */, + 0F4E512A21525FDC00F58ACE /* EddystoneScanner.swift in Sources */, + 0F4E512B21525FDC00F58ACE /* SILDebugCharacteristicEncodingViewController.m in Sources */, + 0F4E512C21525FDC00F58ACE /* SILAppDelegate.m in Sources */, + 0F4E512D21525FDC00F58ACE /* SILHeartRateMeasurement.m in Sources */, + 0F4E512E21525FDC00F58ACE /* SILApp+AttributedProfiles.m in Sources */, + 0F4E512F21525FDC00F58ACE /* SILOTAFirmwareFile.m in Sources */, + 0F4E513021525FDC00F58ACE /* SILBitRowModel.m in Sources */, + 0F4E513121525FDC00F58ACE /* SILRetailBeaconDetailsViewController.m in Sources */, + 0F4E513221525FDC00F58ACE /* SILCollectionViewRightAlignedFlowLayout.m in Sources */, + 0F4E513321525FDC00F58ACE /* UIColor+SILColors.m in Sources */, + 0F4E513421525FDC00F58ACE /* SILBeaconRegistryEntryCell.m in Sources */, + 0F4E513521525FDC00F58ACE /* SILAppSelectionHelpViewController.m in Sources */, + 0F4E513621525FDC00F58ACE /* SILTemperatureType.m in Sources */, + 0F4E513721525FDC00F58ACE /* SILKeyFobViewController.m in Sources */, + 0F4E513821525FDC00F58ACE /* SILCentralManager.m in Sources */, + 0F4E513921525FDC00F58ACE /* CBService+Categories.m in Sources */, + 0F4E513A21525FDC00F58ACE /* SILEddystoneBeaconViewModel.m in Sources */, + 0F4E513B21525FDC00F58ACE /* SILBluetoothDescriptorModel.m in Sources */, + 0F4E513C21525FDC00F58ACE /* SILRoundedViewBehaviour.m in Sources */, + 0F4E513D21525FDC00F58ACE /* SILRangeTestSettingValue.swift in Sources */, + 0F4E513E21525FDC00F58ACE /* EddystoneBeacon.swift in Sources */, + 0F4E513F21525FDC00F58ACE /* SILRangeTestModeSelectionViewController.swift in Sources */, + 0F4E514021525FDC00F58ACE /* SILRangeTestPeripheral.swift in Sources */, + 0F4E514121525FDC00F58ACE /* SILAltBeaconViewModel.m in Sources */, + 0F4E514221525FDC00F58ACE /* SILKeyValueViewModel.m in Sources */, + 0F4E514321525FDC00F58ACE /* SILDebugCharacteristicEnumerationFieldTableViewCell.m in Sources */, + 0F4E514421525FDC00F58ACE /* SILRangeTestCharacteristic.swift in Sources */, + 0F4E514521525FDC00F58ACE /* SILTemperatureMeasurement.m in Sources */, + 0F4E514621525FDC00F58ACE /* SILRetailBeaconAppViewController.m in Sources */, + 0F4E514721525FDC00F58ACE /* SILBeaconDataViewModel.m in Sources */, + 0F4E514821525FDC00F58ACE /* SILOTAFirmwareUpdate.m in Sources */, + 0F4E514921525FDC00F58ACE /* SILBodySensorLocation.m in Sources */, + 0F4E514A21525FDC00F58ACE /* TextFieldTableViewCell.swift in Sources */, + 0F4E514B21525FDC00F58ACE /* SILConnectedLightingViewController.m in Sources */, + 0F4E514C21525FDC00F58ACE /* SILCharacteristicFieldBuilder.m in Sources */, + 0F4E514D21525FDC00F58ACE /* SILApp.m in Sources */, + 0F4E514E21525FDC00F58ACE /* UIFont+Extensions.swift in Sources */, + 0F4E514F21525FDC00F58ACE /* SILDebugServicesViewController.m in Sources */, + 0F4E515021525FDC00F58ACE /* SILBeacon.m in Sources */, + 0F4E515121525FDC00F58ACE /* SILFindKeyFobViewController.m in Sources */, + 0F4E515221525FDC00F58ACE /* SILOTAProgressViewModel.m in Sources */, + 0F4E515321525FDC00F58ACE /* SILOTASetupViewController.m in Sources */, + 0F4E515421525FDC00F58ACE /* WYPopoverController+SILHelpers.m in Sources */, + 0F4E515521525FDC00F58ACE /* SILUUIDProvider.m in Sources */, + 0F4E515621525FDC00F58ACE /* SILRangeTestMovingAverageCalculator.swift in Sources */, + 0F4E515721525FDC00F58ACE /* SILDebugSpacerTableViewCell.m in Sources */, + 0F4E515821525FDC00F58ACE /* SILOTAFirmwareUpdateManager.m in Sources */, + 0F4E515921525FDC00F58ACE /* SILOTAProgressViewController.m in Sources */, + 0F4E515A21525FDC00F58ACE /* SILDebugCharacteristicToggleFieldTableViewCell.m in Sources */, + 0F4E515B21525FDC00F58ACE /* SILRSSIMeasurementTable.m in Sources */, + 0F4E515C21525FDC00F58ACE /* SILConstants.m in Sources */, + 0F4E515D21525FDC00F58ACE /* SILCalibrationViewController.m in Sources */, + 0F4E515E21525FDC00F58ACE /* SILBeaconRegistryEntryViewModel.m in Sources */, + 0F4E515F21525FDC00F58ACE /* SILBitFieldFieldModel.m in Sources */, + 0F4E516021525FDC00F58ACE /* SILBluetoothXMLParser.m in Sources */, + 0F4E516121525FDC00F58ACE /* SILDebugDeviceViewController.m in Sources */, + 0F4E516221525FDC00F58ACE /* SILBluetoothServiceCharacteristicModel.m in Sources */, + 0F4E516321525FDC00F58ACE /* SILAppSelectionViewController.m in Sources */, + 0F4E516421525FDC00F58ACE /* SILDebugHeaderView.m in Sources */, + 0F4E516521525FDC00F58ACE /* SILKeyFobTableViewCell.m in Sources */, + 4D9E26272212CA7000617DBA /* SILRangeTestBoardInfo.swift in Sources */, + 0F4E516621525FDC00F58ACE /* SILCentralManagerBuilder.m in Sources */, + 0F4E516721525FDC00F58ACE /* SILRangeTestAppViewController.swift in Sources */, + 0F4E516821525FDC00F58ACE /* SILOTAFirmwareUpdateViewModel.m in Sources */, + 0F4E516921525FDC00F58ACE /* UIView+SILAnimations.m in Sources */, + 0F4E516A21525FDC00F58ACE /* SILValueFieldRowModel.m in Sources */, + 0F4E516B21525FDC00F58ACE /* SILEnumerationFieldRowModel.m in Sources */, + 0F4E516C21525FDC00F58ACE /* Int+Extensions.swift in Sources */, + 0F4E516D21525FDC00F58ACE /* UIImage+SILHelpers.m in Sources */, + 0F4E516E21525FDC00F58ACE /* SILOTAHUDView.m in Sources */, + 0F4E516F21525FDC00F58ACE /* SILServiceTableModel.m in Sources */, + 0F4E517021525FDC00F58ACE /* SILBluetoothSearch.m in Sources */, + 0F4E517121525FDC00F58ACE /* SILBluetoothCharacteristicModel.m in Sources */, + 0F4E517221525FDC00F58ACE /* SILDiscoveredPeripheral.m in Sources */, + 0F4E517321525FDC00F58ACE /* SILBluetoothServiceModel.m in Sources */, + 0F4E517421525FDC00F58ACE /* SILWeakNotificationPair.m in Sources */, + 0F4E517521525FDC00F58ACE /* GradientSlider.swift in Sources */, + 0F4E517621525FDC00F58ACE /* SILAppSelectionTableViewCell.m in Sources */, + 0F4E517721525FDC00F58ACE /* main.m in Sources */, + 0F4E517821525FDC00F58ACE /* DebugDeviceViewModel.swift in Sources */, + 0F4E517921525FDC00F58ACE /* SILDebugPopoverViewController.m in Sources */, + 0F4E517A21525FDC00F58ACE /* SILRSSIMeasurement.m in Sources */, + 0F4E517B21525FDC00F58ACE /* SILIBeaconViewModel.m in Sources */, + 0F4E517C21525FDC00F58ACE /* SILBluetoothBitModel.m in Sources */, + 0F4E517D21525FDC00F58ACE /* SILKeyFobTableSectionHeaderView.m in Sources */, + 0F4E517E21525FDC00F58ACE /* SILRangeTestTXValueUpdater.swift in Sources */, + 0F4E517F21525FDC00F58ACE /* NSDictionary+SILErrorCode.m in Sources */, + 0F4E518021525FDC00F58ACE /* GradientView.swift in Sources */, + 0F4E518121525FDC00F58ACE /* KZBehaviour.m in Sources */, + 0F4E518221525FDC00F58ACE /* SILDescriptorTableModel.m in Sources */, + 0F4E518321525FDC00F58ACE /* SILBeaconRegistryEntry.m in Sources */, + 0F4E518421525FDC00F58ACE /* SILBarGraphCollectionViewCell.m in Sources */, + 0F4E518521525FDC00F58ACE /* SILDebugCharacteristicEnumerationListViewController.m in Sources */, + 0F4E518621525FDC00F58ACE /* SILRangeTestManufacturerData.swift in Sources */, + 0F4E518721525FDC00F58ACE /* NSError+SILHelpers.m in Sources */, + 0F4E518821525FDC00F58ACE /* SILAdvertisementDataViewModel.m in Sources */, + 0F4E518921525FDC00F58ACE /* SILEncodingPseudoFieldRowModel.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; E6CAA21C1A64011900A49DAF /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -2220,6 +2877,7 @@ 070DDDD51BD96D28000BC644 /* SILDiscoveredPeripheralDisplayData.m in Sources */, 496A42F31E7C582F006E87F2 /* SILBigRedButton.m in Sources */, 07B8A8D21BCD6E3B001948C1 /* SILDebugCharacteristicTableViewCell.m in Sources */, + 0F3EB6B720C524C30062A7C1 /* SILRangeTestAppViewModel.swift in Sources */, 07BBA74E1BD5858F00C2B07E /* SILBluetoothModelManager.m in Sources */, E607A3511A8D4FD100DAAFD3 /* SILSettings.m in Sources */, E64266201A855DA8006C6B2F /* SILWeakTargetWrapper.m in Sources */, @@ -2234,6 +2892,7 @@ 0702AB2C1BDFEE35009527B0 /* SILCharacteristicFieldValueResolver.m in Sources */, 07BBA75F1BD687CC00C2B07E /* SILBluetoothBitFieldModel.m in Sources */, 49BB94B51E68FB4B0068670E /* SILDiscoveredPeripheralDisplayDataViewModel.m in Sources */, + 0F75B9D121395E3200E8D9E9 /* SILRangeTestTXValueUpdater.swift in Sources */, 07B8A8D91BCD6E6F001948C1 /* SILDebugDeviceTableViewCell.m in Sources */, AAD9E9321F279A670054C387 /* DebugDeviceFilterViewController.swift in Sources */, 0755DCFB1BCFEE5D0003886D /* SILDebugAdvDetailCollectionViewCell.m in Sources */, @@ -2243,14 +2902,17 @@ 79C036211EC5F29500EF179B /* HMService+SILHelpers.m in Sources */, 07BBA7621BD688D300C2B07E /* SILBluetoothEnumerationModel.m in Sources */, AA4D435A1F291C17001EE0D2 /* RSSISliderTableViewCell.swift in Sources */, + 4D9E26202212BFB200617DBA /* SILRangeTestBoardFeatures.swift in Sources */, 79C40C701EC9F6A800B729BF /* SILHomeKitDebugDeviceTableViewCell.m in Sources */, 07B1AD7B1BFD05CA00D4D454 /* SILBGBeaconViewModel.m in Sources */, + 0F69656920ECD32A0083C32A /* SILRangeTestManufacturerData.swift in Sources */, 078138501BE99521001EFE7E /* SILDebugEnumerationValueTableViewCell.m in Sources */, 7985D6621EC60C33000FA0FB /* HMCharacteristic+SILHelpers.m in Sources */, E643F41B1A728A8500FB34F5 /* SILDeviceSelectionCollectionViewCell.m in Sources */, 0702AB331BE10E07009527B0 /* SILDebugCharacteristicValueFieldTableViewCell.m in Sources */, E6CCCFFB1A7304210004B2F4 /* UIImage+SILImages.m in Sources */, AA7817411F33B26C00B37B09 /* DebugDeviceFilterViewModel.swift in Sources */, + 0FD15EBA20BD3D0D00ED43BB /* SILRangeTestPeripheral.swift in Sources */, AA162DCE1F0541B600E3DB22 /* TLMData.swift in Sources */, 074691441BFE21A7000D6839 /* UITableViewCell+SILHelpers.m in Sources */, 078138591BE9B014001EFE7E /* SILTextFieldEntryCell.m in Sources */, @@ -2261,6 +2923,7 @@ 4924BA6B1E7057F800AE9E56 /* CBPeripheral+Services.m in Sources */, 07B8A89C1BC5F872001948C1 /* SILDebugProperty.m in Sources */, 49FB4BEC1E7A2EC200223F3E /* SILPopoverViewController.m in Sources */, + 0F34409B20AF18BA0067397C /* SILRangeTestAppViewController.swift in Sources */, E666CBEB1A77C75400676C5C /* SILSegmentedControl.m in Sources */, AA5F62EB1F0A84ED007EDAAC /* SILRetailBeaconDetailsHeaderView.m in Sources */, DC4E508E1E92E507004FD829 /* SILOTAHUDPeripheralViewModel.m in Sources */, @@ -2268,6 +2931,10 @@ 0781384A1BE99502001EFE7E /* SILDebugAdvDetailTableViewCell.m in Sources */, 4977B0321E607D99006DE78C /* EddystoneScanner.swift in Sources */, 078138541BE9A849001EFE7E /* SILDebugCharacteristicEncodingViewController.m in Sources */, + 4D9E26252212CA7000617DBA /* SILRangeTestBoardInfo.swift in Sources */, + 0FFDD025210F09A000CFFB5E /* SILRangeTestMovingAverageCalculator.swift in Sources */, + 0F44BCAE20EE5E0E00CD27B3 /* SILRangeTestCharacteristic.swift in Sources */, + 0F3AC36720ADAABF0010091C /* SILRangeTestModeSelectionViewController.swift in Sources */, E6CAA2291A64011900A49DAF /* SILAppDelegate.m in Sources */, E6B773ED1A68474800B93058 /* SILHeartRateMeasurement.m in Sources */, E666CBE11A76B67900676C5C /* SILApp+AttributedProfiles.m in Sources */, @@ -2333,6 +3000,7 @@ DCB431111E8315CE00EE94F0 /* SILOTAHUDView.m in Sources */, 07B8A8841BC47615001948C1 /* SILServiceTableModel.m in Sources */, 79E62B4F1ECCA29400344CAA /* SILBluetoothSearch.m in Sources */, + 0F8163C120C52386008B98C6 /* SILRangeTestSettingValue.swift in Sources */, 79C0361B1EC5576100EF179B /* SILHomeKitManager.m in Sources */, 0CC658151F96C3C200953CDC /* SILDeviceSelectionViewModel.m in Sources */, 07BBA7561BD5C89700C2B07E /* SILBluetoothCharacteristicModel.m in Sources */, @@ -2378,7 +3046,7 @@ /* Begin PBXTargetDependency section */ E6CAA23B1A64011900A49DAF /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = E6CAA21F1A64011900A49DAF /* SiliconLabsApp */; + target = E6CAA21F1A64011900A49DAF /* BlueGeckoWithHomeKit */; targetProxy = E6CAA23A1A64011900A49DAF /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ @@ -2430,15 +3098,14 @@ /* Begin XCBuildConfiguration section */ 0C2FCBD61F9A542300F4F259 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 4CA68516D3541CFE58D83A14 /* Pods-SiliconLabsAppWithoutHomeKit.debug.xcconfig */; + baseConfigurationReference = 4491900FB788A5F0E74824C6 /* Pods-BlueGecko.debug.xcconfig */; buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIconBlueGecko; ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; - BUNDLE_ID_SUFFIX = ""; - BUNDLE_VERSION_STRING = 1.4.1; CLANG_ENABLE_MODULES = YES; CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS = NO; - CODE_SIGN_ENTITLEMENTS = SiliconLabsApp/SiliconLabsAppWithoutHomeKit.entitlements; + CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/SiliconLabsApp/SupportingFiles/BlueGecko/Entitlements.entitlements"; + CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_RESOURCE_RULES_PATH = ""; CODE_SIGN_STYLE = Automatic; @@ -2446,70 +3113,31 @@ DEVELOPMENT_TEAM = 52444FG85C; DISPLAY_NAME = "Blue Gecko"; ENABLE_BITCODE = YES; - GCC_PREFIX_HEADER = SiliconLabsAppWithoutHomeKit.pch; + GCC_PREFIX_HEADER = "$(SRCROOT)/SiliconLabsApp/SupportingFiles/BlueGecko/BlueGecko.pch"; "GCC_PREPROCESSOR_DEFINITIONS[arch=*]" = "$(inherited)"; - INFOPLIST_FILE = "$(SRCROOT)/SiliconLabsApp/SupportingFiles/Info-WithoutHomeKit.plist"; + INFOPLIST_FILE = "$(SRCROOT)/SiliconLabsApp/SupportingFiles/BlueGecko/Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.3; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.silabs.WirelessGeckoDemoApp; + PRODUCT_BUNDLE_IDENTIFIER = com.silabs.BlueGeckoDemoApp; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = ""; PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_OBJC_BRIDGING_HEADER = "SiliconLabsApp-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; - 0C2FCBD71F9A542300F4F259 /* Debug-Wireless-Gecko */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 61C2546AB44D8C072A96C83A /* Pods-SiliconLabsAppWithoutHomeKit.debug-wireless-gecko.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon${BUNDLE_ID_SUFFIX}"; - ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; - BUNDLE_ID_SUFFIX = .wireless; - BUNDLE_VERSION_STRING = 1.1; - CLANG_ENABLE_MODULES = YES; - CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS = NO; - CODE_SIGN_ENTITLEMENTS = SiliconLabsApp/SiliconLabsAppWithoutHomeKit.entitlements; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - CODE_SIGN_RESOURCE_RULES_PATH = ""; - CODE_SIGN_STYLE = Automatic; - DEFINES_MODULE = YES; - DEVELOPMENT_TEAM = 52444FG85C; - DISPLAY_NAME = "Wireless Gecko"; - ENABLE_BITCODE = YES; - GCC_PREFIX_HEADER = SiliconLabsAppWithoutHomeKit.pch; - GCC_PREPROCESSOR_DEFINITIONS = ( - "$(inherited)", - "WIRELESS=1", - ); - INFOPLIST_FILE = "$(SRCROOT)/SiliconLabsApp/SupportingFiles/Info-WithoutHomeKit.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 9.3; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.silabs.WirelessGeckoDemoApp; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = ""; - PROVISIONING_PROFILE_SPECIFIER = ""; - SWIFT_OBJC_BRIDGING_HEADER = "SiliconLabsApp-Bridging-Header.h"; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 3.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = "Debug-Wireless-Gecko"; - }; 0C2FCBD81F9A542300F4F259 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 8A73A6BB1453DAE49320F05E /* Pods-SiliconLabsAppWithoutHomeKit.release.xcconfig */; + baseConfigurationReference = 9D503111803F12397900799A /* Pods-BlueGecko.release.xcconfig */; buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIconBlueGecko; ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; - BUNDLE_ID_SUFFIX = ""; - BUNDLE_VERSION_STRING = 1.4.1; CLANG_ENABLE_MODULES = YES; CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS = NO; - CODE_SIGN_ENTITLEMENTS = SiliconLabsApp/SiliconLabsAppWithoutHomeKit.entitlements; + CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/SiliconLabsApp/SupportingFiles/BlueGecko/Entitlements.entitlements"; + CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_RESOURCE_RULES_PATH = ""; CODE_SIGN_STYLE = Automatic; @@ -2517,31 +3145,29 @@ DEVELOPMENT_TEAM = 52444FG85C; DISPLAY_NAME = "Blue Gecko"; ENABLE_BITCODE = YES; - GCC_PREFIX_HEADER = SiliconLabsAppWithoutHomeKit.pch; - INFOPLIST_FILE = "$(SRCROOT)/SiliconLabsApp/SupportingFiles/Info-WithoutHomeKit.plist"; + GCC_PREFIX_HEADER = "$(SRCROOT)/SiliconLabsApp/SupportingFiles/BlueGecko/BlueGecko.pch"; + INFOPLIST_FILE = "$(SRCROOT)/SiliconLabsApp/SupportingFiles/BlueGecko/Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.3; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.silabs.WirelessGeckoDemoApp; + PRODUCT_BUNDLE_IDENTIFIER = com.silabs.BlueGeckoDemoApp; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = ""; PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_OBJC_BRIDGING_HEADER = "SiliconLabsApp-Bridging-Header.h"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Release; }; - 0C2FCBD91F9A542300F4F259 /* Release-Wireless-Gecko */ = { + 0F4E51C821525FDC00F58ACE /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = D88A34903477559039113A50 /* Pods-SiliconLabsAppWithoutHomeKit.release-wireless-gecko.xcconfig */; + baseConfigurationReference = D578365DE8C84B43DE844D60 /* Pods-WirelessGecko.debug.xcconfig */; buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon${BUNDLE_ID_SUFFIX}"; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIconWirelessGecko; ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; - BUNDLE_ID_SUFFIX = .wireless; - BUNDLE_VERSION_STRING = 1.1; CLANG_ENABLE_MODULES = YES; CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS = NO; - CODE_SIGN_ENTITLEMENTS = SiliconLabsApp/SiliconLabsAppWithoutHomeKit.entitlements; + CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/SiliconLabsApp/SupportingFiles/WirelessGecko/Entitlements.entitlements"; + CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_RESOURCE_RULES_PATH = ""; CODE_SIGN_STYLE = Automatic; @@ -2549,250 +3175,84 @@ DEVELOPMENT_TEAM = 52444FG85C; DISPLAY_NAME = "Wireless Gecko"; ENABLE_BITCODE = YES; - GCC_PREFIX_HEADER = SiliconLabsAppWithoutHomeKit.pch; + GCC_PREFIX_HEADER = "$(SRCROOT)/SiliconLabsApp/SupportingFiles/WirelessGecko/WirelessGecko.pch"; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", "WIRELESS=1", ); - INFOPLIST_FILE = "$(SRCROOT)/SiliconLabsApp/SupportingFiles/Info-WithoutHomeKit.plist"; + "GCC_PREPROCESSOR_DEFINITIONS[arch=*]" = "$(inherited)"; + INFOPLIST_FILE = "$(SRCROOT)/SiliconLabsApp/SupportingFiles/WirelessGecko/Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.3; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.silabs.WirelessGeckoDemoApp; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = ""; PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_OBJC_BRIDGING_HEADER = "SiliconLabsApp-Bridging-Header.h"; - SWIFT_VERSION = 3.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = "Release-Wireless-Gecko"; - }; - B0C18E911F87DAFD00B7401F /* Debug-Wireless-Gecko */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.3; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - PROVISIONING_PROFILE = ""; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = 2; - }; - name = "Debug-Wireless-Gecko"; - }; - B0C18E921F87DAFD00B7401F /* Debug-Wireless-Gecko */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = A058D14EA4646B6D95A1DC6C /* Pods-SiliconLabsApp.debug-wireless-gecko.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon${BUNDLE_ID_SUFFIX}"; - ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; - BUNDLE_ID_SUFFIX = .wireless; - BUNDLE_VERSION_STRING = 1.1; - CLANG_ENABLE_MODULES = YES; - CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS = NO; - CODE_SIGN_ENTITLEMENTS = SiliconLabsApp/SiliconLabsApp.entitlements; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - CODE_SIGN_RESOURCE_RULES_PATH = ""; - DEFINES_MODULE = YES; - DEVELOPMENT_TEAM = THP5EV5EJ9; - DISPLAY_NAME = "Wireless Gecko"; - ENABLE_BITCODE = YES; - GCC_PREFIX_HEADER = SiliconLabsApp.pch; - GCC_PREPROCESSOR_DEFINITIONS = ( - "$(inherited)", - "WIRELESS=1", - "ENABLE_HOMEKIT=1", - ); - INFOPLIST_FILE = SiliconLabsApp/SupportingFiles/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 9.3; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = io.intrepid.silabs.WirelessGecko; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = "1ffbfc05-e8f7-477b-8efb-6afd1e79f203"; - PROVISIONING_PROFILE_SPECIFIER = "SiLabs Wireless Gecko Development"; - SWIFT_OBJC_BRIDGING_HEADER = "SiliconLabsApp-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = "1,2"; }; - name = "Debug-Wireless-Gecko"; - }; - B0C18E931F87DAFD00B7401F /* Debug-Wireless-Gecko */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - BUNDLE_LOADER = "$(TEST_HOST)"; - CLANG_ENABLE_MODULES = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - FRAMEWORK_SEARCH_PATHS = ( - "$(SDKROOT)/Developer/Library/Frameworks", - "$(inherited)", - ); - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - INFOPLIST_FILE = SiliconLabsAppTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "com.silabs.$(PRODUCT_NAME:rfc1034identifier)"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "SiliconLabsAppTests/SiliconLabsAppTests-Bridging-Header.h"; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 3.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SiliconLabsApp.app/SiliconLabsApp"; - }; - name = "Debug-Wireless-Gecko"; - }; - B0C18E941F87DB1600B7401F /* Release-Wireless-Gecko */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "iPhone Distribution: Silicon Laboratories Inc (52444FG85C)"; - COPY_PHASE_STRIP = YES; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.3; - MTL_ENABLE_DEBUG_INFO = NO; - PROVISIONING_PROFILE = "25eb3815-e469-43a3-9bff-b43eec840700"; - SDKROOT = iphoneos; - SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - TARGETED_DEVICE_FAMILY = 2; - VALIDATE_PRODUCT = YES; - }; - name = "Release-Wireless-Gecko"; + name = Debug; }; - B0C18E951F87DB1600B7401F /* Release-Wireless-Gecko */ = { + 0F4E51CA21525FDC00F58ACE /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 62E0D0F50D4DF9406BE2453B /* Pods-SiliconLabsApp.release-wireless-gecko.xcconfig */; + baseConfigurationReference = BBA88A0DF7A10843B48785CA /* Pods-WirelessGecko.release.xcconfig */; buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon${BUNDLE_ID_SUFFIX}"; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIconWirelessGecko; ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; - BUNDLE_ID_SUFFIX = .wireless; - BUNDLE_VERSION_STRING = 1.1; CLANG_ENABLE_MODULES = YES; CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS = NO; - CODE_SIGN_ENTITLEMENTS = SiliconLabsApp/SiliconLabsApp.entitlements; + CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/SiliconLabsApp/SupportingFiles/WirelessGecko/Entitlements.entitlements"; + CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_RESOURCE_RULES_PATH = ""; + CODE_SIGN_STYLE = Automatic; DEFINES_MODULE = YES; - DEVELOPMENT_TEAM = THP5EV5EJ9; + DEVELOPMENT_TEAM = 52444FG85C; DISPLAY_NAME = "Wireless Gecko"; ENABLE_BITCODE = YES; - GCC_PREFIX_HEADER = SiliconLabsApp.pch; + GCC_PREFIX_HEADER = "$(SRCROOT)/SiliconLabsApp/SupportingFiles/WirelessGecko/WirelessGecko.pch"; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", "WIRELESS=1", - "ENABLE_HOMEKIT=1", ); - INFOPLIST_FILE = SiliconLabsApp/SupportingFiles/Info.plist; + INFOPLIST_FILE = "$(SRCROOT)/SiliconLabsApp/SupportingFiles/WirelessGecko/Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.3; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = io.intrepid.silabs.WirelessGecko; + PRODUCT_BUNDLE_IDENTIFIER = com.silabs.WirelessGeckoDemoApp; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = "3fb001eb-6cda-4a08-ad26-df8584eb539a"; - PROVISIONING_PROFILE_SPECIFIER = "SiLabs Wireless Gecko Development"; + PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_OBJC_BRIDGING_HEADER = "SiliconLabsApp-Bridging-Header.h"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = "1,2"; }; - name = "Release-Wireless-Gecko"; - }; - B0C18E961F87DB1600B7401F /* Release-Wireless-Gecko */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - BUNDLE_LOADER = "$(TEST_HOST)"; - CLANG_ENABLE_MODULES = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - FRAMEWORK_SEARCH_PATHS = ( - "$(SDKROOT)/Developer/Library/Frameworks", - "$(inherited)", - ); - INFOPLIST_FILE = SiliconLabsAppTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "com.silabs.$(PRODUCT_NAME:rfc1034identifier)"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "SiliconLabsAppTests/SiliconLabsAppTests-Bridging-Header.h"; - SWIFT_VERSION = 3.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SiliconLabsApp.app/SiliconLabsApp"; - }; - name = "Release-Wireless-Gecko"; + name = Release; }; E6CAA2411A64011900A49DAF /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; @@ -2829,18 +3289,27 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; @@ -2869,73 +3338,71 @@ }; E6CAA2441A64011900A49DAF /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 257E756EE6E82EC7E361629D /* Pods-SiliconLabsApp.debug.xcconfig */; + baseConfigurationReference = 06CC32BDFF67F87AF59FFD4D /* Pods-BlueGeckoWithHomeKit.debug.xcconfig */; buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIconBlueGecko; ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; - BUNDLE_ID_SUFFIX = ""; - BUNDLE_VERSION_STRING = 1.4.1; CLANG_ENABLE_MODULES = YES; CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS = NO; - CODE_SIGN_ENTITLEMENTS = SiliconLabsApp/SiliconLabsApp.entitlements; + CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/SiliconLabsApp/SupportingFiles/BlueGeckoWithHomeKit/Entitlements.entitlements"; + CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_RESOURCE_RULES_PATH = ""; + CODE_SIGN_STYLE = Automatic; DEFINES_MODULE = YES; - DEVELOPMENT_TEAM = THP5EV5EJ9; + DEVELOPMENT_TEAM = 52444FG85C; DISPLAY_NAME = "Blue Gecko"; ENABLE_BITCODE = YES; - GCC_PREFIX_HEADER = SiliconLabsApp.pch; + GCC_PREFIX_HEADER = "$(SRCROOT)/SiliconLabsApp/SupportingFiles/BlueGeckoWithHomeKit/BlueGeckoWithHomeKit.pch"; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", "COCOAPODS=1", "ENABLE_HOMEKIT=1", ); - INFOPLIST_FILE = SiliconLabsApp/SupportingFiles/Info.plist; + INFOPLIST_FILE = "$(SRCROOT)/SiliconLabsApp/SupportingFiles/BlueGeckoWithHomeKit/Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.3; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = io.intrepid.SiliconLabsApp; + PRODUCT_BUNDLE_IDENTIFIER = com.silabs.BlueGeckoDemoApp; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = "d51efe94-6463-4b3f-b81f-a33d0d27956b"; - PROVISIONING_PROFILE_SPECIFIER = "Silicon Labs Development"; + PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_OBJC_BRIDGING_HEADER = "SiliconLabsApp-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; E6CAA2451A64011900A49DAF /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = E406AEFE9A8583311524FBD8 /* Pods-SiliconLabsApp.release.xcconfig */; + baseConfigurationReference = F3FCDDB05872DDFD08FD595A /* Pods-BlueGeckoWithHomeKit.release.xcconfig */; buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIconBlueGecko; ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; - BUNDLE_ID_SUFFIX = ""; - BUNDLE_VERSION_STRING = 1.4.1; CLANG_ENABLE_MODULES = YES; CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS = NO; - CODE_SIGN_ENTITLEMENTS = SiliconLabsApp/SiliconLabsApp.entitlements; + CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/SiliconLabsApp/SupportingFiles/BlueGeckoWithHomeKit/Entitlements.entitlements"; + CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_RESOURCE_RULES_PATH = ""; + CODE_SIGN_STYLE = Automatic; DEFINES_MODULE = YES; - DEVELOPMENT_TEAM = THP5EV5EJ9; + DEVELOPMENT_TEAM = 52444FG85C; DISPLAY_NAME = "Blue Gecko"; ENABLE_BITCODE = YES; - GCC_PREFIX_HEADER = SiliconLabsApp.pch; + GCC_PREFIX_HEADER = "$(SRCROOT)/SiliconLabsApp/SupportingFiles/BlueGeckoWithHomeKit/BlueGeckoWithHomeKit.pch"; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", "COCOAPODS=1", "ENABLE_HOMEKIT=1", ); - INFOPLIST_FILE = SiliconLabsApp/SupportingFiles/Info.plist; + INFOPLIST_FILE = "$(SRCROOT)/SiliconLabsApp/SupportingFiles/BlueGeckoWithHomeKit/Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.3; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = io.intrepid.SiliconLabsApp; + PRODUCT_BUNDLE_IDENTIFIER = com.silabs.BlueGeckoDemoApp; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = "de9548e1-7b8f-4ff0-bded-728c42e8646e"; - PROVISIONING_PROFILE_SPECIFIER = "Silicon Labs Development"; + PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_OBJC_BRIDGING_HEADER = "SiliconLabsApp-Bridging-Header.h"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Release; @@ -2990,13 +3457,20 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 0C2FCBD51F9A542300F4F259 /* Build configuration list for PBXNativeTarget "SiliconLabsAppWithoutHomeKit" */ = { + 0C2FCBD51F9A542300F4F259 /* Build configuration list for PBXNativeTarget "BlueGecko" */ = { isa = XCConfigurationList; buildConfigurations = ( 0C2FCBD61F9A542300F4F259 /* Debug */, - 0C2FCBD71F9A542300F4F259 /* Debug-Wireless-Gecko */, 0C2FCBD81F9A542300F4F259 /* Release */, - 0C2FCBD91F9A542300F4F259 /* Release-Wireless-Gecko */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 0F4E51C721525FDC00F58ACE /* Build configuration list for PBXNativeTarget "WirelessGecko" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0F4E51C821525FDC00F58ACE /* Debug */, + 0F4E51CA21525FDC00F58ACE /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -3005,20 +3479,16 @@ isa = XCConfigurationList; buildConfigurations = ( E6CAA2411A64011900A49DAF /* Debug */, - B0C18E911F87DAFD00B7401F /* Debug-Wireless-Gecko */, E6CAA2421A64011900A49DAF /* Release */, - B0C18E941F87DB1600B7401F /* Release-Wireless-Gecko */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - E6CAA2431A64011900A49DAF /* Build configuration list for PBXNativeTarget "SiliconLabsApp" */ = { + E6CAA2431A64011900A49DAF /* Build configuration list for PBXNativeTarget "BlueGeckoWithHomeKit" */ = { isa = XCConfigurationList; buildConfigurations = ( E6CAA2441A64011900A49DAF /* Debug */, - B0C18E921F87DAFD00B7401F /* Debug-Wireless-Gecko */, E6CAA2451A64011900A49DAF /* Release */, - B0C18E951F87DB1600B7401F /* Release-Wireless-Gecko */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -3027,9 +3497,7 @@ isa = XCConfigurationList; buildConfigurations = ( E6CAA2471A64011900A49DAF /* Debug */, - B0C18E931F87DAFD00B7401F /* Debug-Wireless-Gecko */, E6CAA2481A64011900A49DAF /* Release */, - B0C18E961F87DB1600B7401F /* Release-Wireless-Gecko */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; diff --git a/SiliconLabsApp.xcodeproj/xcshareddata/xcschemes/SiliconLabsAppWithoutHomeKit.xcscheme b/SiliconLabsApp.xcodeproj/xcshareddata/xcschemes/BlueGecko.xcscheme similarity index 84% rename from SiliconLabsApp.xcodeproj/xcshareddata/xcschemes/SiliconLabsAppWithoutHomeKit.xcscheme rename to SiliconLabsApp.xcodeproj/xcshareddata/xcschemes/BlueGecko.xcscheme index 0b66a5ac..b0b6b153 100644 --- a/SiliconLabsApp.xcodeproj/xcshareddata/xcschemes/SiliconLabsAppWithoutHomeKit.xcscheme +++ b/SiliconLabsApp.xcodeproj/xcshareddata/xcschemes/BlueGecko.xcscheme @@ -1,6 +1,6 @@ @@ -26,7 +26,6 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - language = "" shouldUseLaunchSchemeArgsEnv = "YES"> @@ -34,8 +33,8 @@ @@ -46,7 +45,6 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - language = "" launchStyle = "0" useCustomWorkingDirectory = "NO" ignoresPersistentStateOnLaunch = "NO" @@ -58,8 +56,8 @@ @@ -77,8 +75,8 @@ diff --git a/SiliconLabsApp.xcodeproj/xcshareddata/xcschemes/SiliconLabsApp.xcscheme b/SiliconLabsApp.xcodeproj/xcshareddata/xcschemes/BlueGeckoWithHomeKit.xcscheme similarity index 89% rename from SiliconLabsApp.xcodeproj/xcshareddata/xcschemes/SiliconLabsApp.xcscheme rename to SiliconLabsApp.xcodeproj/xcshareddata/xcschemes/BlueGeckoWithHomeKit.xcscheme index 7d873d71..10509a45 100644 --- a/SiliconLabsApp.xcodeproj/xcshareddata/xcschemes/SiliconLabsApp.xcscheme +++ b/SiliconLabsApp.xcodeproj/xcshareddata/xcschemes/BlueGeckoWithHomeKit.xcscheme @@ -1,6 +1,6 @@ @@ -40,7 +40,6 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - language = "" shouldUseLaunchSchemeArgsEnv = "YES"> @@ -70,7 +69,6 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - language = "" launchStyle = "0" useCustomWorkingDirectory = "NO" ignoresPersistentStateOnLaunch = "NO" @@ -82,8 +80,8 @@ @@ -101,8 +99,8 @@ diff --git a/SiliconLabsApp.xcodeproj/xcshareddata/xcschemes/SiliconLabsApp-WirelessGecko.xcscheme b/SiliconLabsApp.xcodeproj/xcshareddata/xcschemes/WirelessGecko.xcscheme similarity index 58% rename from SiliconLabsApp.xcodeproj/xcshareddata/xcschemes/SiliconLabsApp-WirelessGecko.xcscheme rename to SiliconLabsApp.xcodeproj/xcshareddata/xcschemes/WirelessGecko.xcscheme index 4c7a988e..05b66348 100644 --- a/SiliconLabsApp.xcodeproj/xcshareddata/xcschemes/SiliconLabsApp-WirelessGecko.xcscheme +++ b/SiliconLabsApp.xcodeproj/xcshareddata/xcschemes/WirelessGecko.xcscheme @@ -1,25 +1,11 @@ - - - - @@ -57,10 +42,9 @@ @@ -81,27 +65,26 @@ - + - + + buildConfiguration = "Debug"> diff --git a/SiliconLabsApp.xcworkspace/contents.xcworkspacedata b/SiliconLabsApp.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..9bf94500 --- /dev/null +++ b/SiliconLabsApp.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/SiliconLabsApp.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/SiliconLabsApp.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/SiliconLabsApp.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/SiliconLabsApp/Base.lproj/AppSelection/SILAppSelectionHelpViewController.xib b/SiliconLabsApp/Base.lproj/AppSelection/SILAppSelectionHelpViewController.xib index 13206224..2bc01026 100644 --- a/SiliconLabsApp/Base.lproj/AppSelection/SILAppSelectionHelpViewController.xib +++ b/SiliconLabsApp/Base.lproj/AppSelection/SILAppSelectionHelpViewController.xib @@ -1,16 +1,16 @@ - + - - + + @@ -24,7 +24,7 @@ diff --git a/SiliconLabsApp/Base.lproj/AppSelection/SILAppSelectionViewController.xib b/SiliconLabsApp/Base.lproj/AppSelection/SILAppSelectionViewController.xib index 24c814f1..3b332275 100644 --- a/SiliconLabsApp/Base.lproj/AppSelection/SILAppSelectionViewController.xib +++ b/SiliconLabsApp/Base.lproj/AppSelection/SILAppSelectionViewController.xib @@ -1,47 +1,49 @@ - - + + + + + - - + + + + - + - + - - + @@ -51,34 +53,34 @@ - + + + + + - + - - + - @@ -86,16 +88,10 @@ - - - - - - - - + + @@ -111,34 +107,36 @@ - - + + + + + + - - - + + @@ -153,19 +151,18 @@ - - - + + - - + - + + @@ -173,15 +170,11 @@ - + - - - - - + @@ -190,7 +183,6 @@ - diff --git a/SiliconLabsApp/Base.lproj/Debug/Popover/SILTextFieldEntryCell.xib b/SiliconLabsApp/Base.lproj/Debug/Popover/SILTextFieldEntryCell.xib index 851d5de9..caa26300 100644 --- a/SiliconLabsApp/Base.lproj/Debug/Popover/SILTextFieldEntryCell.xib +++ b/SiliconLabsApp/Base.lproj/Debug/Popover/SILTextFieldEntryCell.xib @@ -1,13 +1,11 @@ - + - - - + @@ -16,19 +14,28 @@ - + + - + - + @@ -47,20 +54,20 @@ - + - + @@ -77,16 +84,6 @@ - @@ -97,14 +94,14 @@ + - - + diff --git a/SiliconLabsApp/Base.lproj/Debug/Services/SILDebugCharacteristicTableViewCell~ipad.xib b/SiliconLabsApp/Base.lproj/Debug/Services/SILDebugCharacteristicTableViewCell~ipad.xib index 400efba8..d2b2e6ba 100644 --- a/SiliconLabsApp/Base.lproj/Debug/Services/SILDebugCharacteristicTableViewCell~ipad.xib +++ b/SiliconLabsApp/Base.lproj/Debug/Services/SILDebugCharacteristicTableViewCell~ipad.xib @@ -1,11 +1,11 @@ - + - + @@ -32,7 +32,7 @@ - + @@ -46,24 +46,26 @@ - + + + + - - - - + + + + @@ -76,57 +78,61 @@ - + + + + - - + + - - + + - + + + + - + - + - + @@ -138,25 +144,27 @@ - + + + + - + + - - - + + @@ -168,24 +176,26 @@ - + + + + - - - - + + + + @@ -200,25 +210,25 @@ - + @@ -271,22 +281,22 @@ - + - + - + - - + + - + diff --git a/SiliconLabsApp/Base.lproj/Debug/Services/SILDebugCharacteristicTableViewCell~iphone.xib b/SiliconLabsApp/Base.lproj/Debug/Services/SILDebugCharacteristicTableViewCell~iphone.xib index 89821c0d..74c80c8b 100644 --- a/SiliconLabsApp/Base.lproj/Debug/Services/SILDebugCharacteristicTableViewCell~iphone.xib +++ b/SiliconLabsApp/Base.lproj/Debug/Services/SILDebugCharacteristicTableViewCell~iphone.xib @@ -1,11 +1,11 @@ - + - + @@ -20,9 +20,49 @@ - + + + + + + - + @@ -48,30 +88,30 @@ - + + + + - - - - - - + + + + @@ -83,87 +123,86 @@ - + + + + - - - - - - + + + + - + + + + - - + - - - + - + + + + - - - - - - + + + + @@ -175,25 +214,25 @@ - + + + + - - - - - - + + + + @@ -261,20 +300,25 @@ - + + - + + - + + - - + + + + diff --git a/SiliconLabsApp/Base.lproj/RangeTest/RangeTestStoryboard.storyboard b/SiliconLabsApp/Base.lproj/RangeTest/RangeTestStoryboard.storyboard new file mode 100644 index 00000000..2d909465 --- /dev/null +++ b/SiliconLabsApp/Base.lproj/RangeTest/RangeTestStoryboard.storyboard @@ -0,0 +1,848 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/SiliconLabsApp/Base.lproj/RangeTest/SILRangeTestModeSelectionViewController.xib b/SiliconLabsApp/Base.lproj/RangeTest/SILRangeTestModeSelectionViewController.xib new file mode 100644 index 00000000..fd03dfc7 --- /dev/null +++ b/SiliconLabsApp/Base.lproj/RangeTest/SILRangeTestModeSelectionViewController.xib @@ -0,0 +1,372 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/SiliconLabsApp/Base.lproj/RetailBeacon/SILRetailBeaconAppViewController.xib b/SiliconLabsApp/Base.lproj/RetailBeacon/SILRetailBeaconAppViewController.xib index d84521f0..95644167 100644 --- a/SiliconLabsApp/Base.lproj/RetailBeacon/SILRetailBeaconAppViewController.xib +++ b/SiliconLabsApp/Base.lproj/RetailBeacon/SILRetailBeaconAppViewController.xib @@ -1,28 +1,22 @@ - + - + - - - HelveticaNeue - - - HelveticaNeue-Light - - + + @@ -113,55 +107,67 @@ - - - + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - + + + @@ -189,11 +195,12 @@ - + + diff --git a/SiliconLabsApp/Base.lproj/SILDeviceSelectionViewController.xib b/SiliconLabsApp/Base.lproj/SILDeviceSelectionViewController.xib index 27a4499f..c5e0a979 100644 --- a/SiliconLabsApp/Base.lproj/SILDeviceSelectionViewController.xib +++ b/SiliconLabsApp/Base.lproj/SILDeviceSelectionViewController.xib @@ -1,19 +1,12 @@ - - + + - - + - - - HelveticaNeue - HelveticaNeue-Medium - - @@ -30,21 +23,21 @@ - + - + - + - - + - + - + - + - + - + - + @@ -184,10 +177,10 @@ HOGP - + - + @@ -264,7 +257,7 @@ HOGP - + @@ -331,7 +324,7 @@ HOGP