From b0ef5247094b8a868e4c519fe0e83f4f123bd2ea Mon Sep 17 00:00:00 2001 From: jacobchristie Date: Fri, 21 Jul 2017 17:25:54 -0400 Subject: [PATCH 1/6] Added Swift iOS demos --- .../AppIcon.appiconset/Contents.json | 59 +++ .../AppIcon.appiconset/Icon-29@2x.png | Bin 0 -> 5677 bytes .../AppIcon.appiconset/Icon-29@3x.png | Bin 0 -> 10210 bytes .../AppIcon.appiconset/Icon-40@2x.png | Bin 0 -> 9266 bytes .../AppIcon.appiconset/Icon-40@3x.png | Bin 0 -> 14343 bytes .../AppIcon.appiconset/Icon-60@2x.png | Bin 0 -> 14343 bytes .../AppIcon.appiconset/Icon-60@3x.png | Bin 0 -> 27502 bytes .../Assets.xcassets/Contents.json | 6 + .../LaunchImage.launchimage/Contents.json | 43 +++ .../Default-568h@2x.png | Bin 0 -> 16567 bytes .../Default-667h@2x.png | Bin 0 -> 22355 bytes .../Default-736h@3x.png | Bin 0 -> 55285 bytes .../LaunchImage.launchimage/Default@2x.png | Bin 0 -> 14035 bytes .../icon.imageset/Contents.json | 23 ++ .../Assets.xcassets/icon.imageset/star-1.png | Bin 0 -> 1221 bytes .../Assets.xcassets/icon.imageset/star-2.png | Bin 0 -> 1221 bytes .../Assets.xcassets/icon.imageset/star.png | Bin 0 -> 1221 bytes .../Base.lproj/LaunchScreen.storyboard | 25 ++ .../ChartsDemo-iOS/Classes/AppDelegate.swift | 54 +++ .../Classes/Components/BalloonMarker.swift | 122 ++++++ .../Classes/Components/RadarMarkerView.swift | 27 ++ .../Classes/Components/RadarMarkerView.xib | 52 +++ .../Classes/Components/XYMarkerView.swift | 32 ++ .../Classes/DemoBaseViewController.swift | 362 ++++++++++++++++++ .../Classes/DemoListViewController.swift | 129 +++++++ .../Classes/DemoListViewController.xib | 40 ++ .../Demos/AnotherBarChartViewController.swift | 98 +++++ .../Demos/AnotherBarChartViewController.xib | 100 +++++ .../Demos/BarChartViewController.swift | 152 ++++++++ .../Classes/Demos/BarChartViewController.xib | 100 +++++ .../Demos/BubbleChartViewController.swift | 127 ++++++ .../Demos/BubbleChartViewController.xib | 100 +++++ .../CandleStickChartViewController.swift | 122 ++++++ .../Demos/CandleStickChartViewController.xib | 100 +++++ .../ColoredLineChartViewController.swift | 77 ++++ .../Demos/ColoredLineChartViewController.xib | 64 ++++ .../Demos/CombinedChartViewController.swift | 233 +++++++++++ .../Demos/CombinedChartViewController.xib | 56 +++ .../Demos/CubicLineChartViewController.swift | 155 ++++++++ .../Demos/CubicLineChartViewController.xib | 100 +++++ .../Demos/HalfPieChartViewController.swift | 142 +++++++ .../Demos/HalfPieChartViewController.xib | 56 +++ .../HorizontalBarChartViewController.swift | 124 ++++++ .../HorizontalBarChartViewController.xib | 100 +++++ .../Demos/LineChart1ViewController.swift | 187 +++++++++ .../Demos/LineChart1ViewController.xib | 100 +++++ .../Demos/LineChart2ViewController.swift | 200 ++++++++++ .../Demos/LineChart2ViewController.xib | 100 +++++ .../Demos/LineChartFilledViewController.swift | 117 ++++++ .../Demos/LineChartFilledViewController.xib | 86 +++++ .../Demos/LineChartTimeViewController.swift | 161 ++++++++ .../Demos/LineChartTimeViewController.xib | 78 ++++ .../MultipleBarChartViewController.swift | 154 ++++++++ .../Demos/MultipleBarChartViewController.xib | 99 +++++ .../MultipleLinesChartViewController.swift | 138 +++++++ .../MultipleLinesChartViewController.xib | 100 +++++ ...egativeStackedBarChartViewController.swift | 134 +++++++ .../NegativeStackedBarChartViewController.xib | 56 +++ .../Demos/PieChartViewController.swift | 153 ++++++++ .../Classes/Demos/PieChartViewController.xib | 100 +++++ .../PiePolylineChartViewController.swift | 145 +++++++ .../Demos/PiePolylineChartViewController.xib | 114 ++++++ ...sitiveNegativeBarChartViewController.swift | 120 ++++++ ...PositiveNegativeBarChartViewController.xib | 56 +++ .../Demos/RadarChartViewController.swift | 203 ++++++++++ .../Demos/RadarChartViewController.xib | 65 ++++ .../Demos/ScatterChartViewController.swift | 124 ++++++ .../Demos/ScatterChartViewController.xib | 100 +++++ .../Demos/SinusBarChartViewController.swift | 108 ++++++ .../Demos/SinusBarChartViewController.xib | 78 ++++ .../Demos/StackedBarChartViewController.swift | 125 ++++++ .../Demos/StackedBarChartViewController.xib | 100 +++++ .../Formatters/DateValueFormatter.swift | 22 ++ .../Formatters/DayAxisValueFormatter.swift | 109 ++++++ .../Formatters/IntAxisValueFormatter.swift | 16 + .../Formatters/LargeValueFormatter.swift | 56 +++ ChartsDemo-iOS/ChartsDemo-iOS/Info.plist | 43 +++ 77 files changed, 6527 insertions(+) create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Assets.xcassets/AppIcon.appiconset/Icon-29@2x.png create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Assets.xcassets/AppIcon.appiconset/Icon-29@3x.png create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Assets.xcassets/AppIcon.appiconset/Icon-40@2x.png create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Assets.xcassets/AppIcon.appiconset/Icon-40@3x.png create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Assets.xcassets/AppIcon.appiconset/Icon-60@3x.png create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Assets.xcassets/Contents.json create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Assets.xcassets/LaunchImage.launchimage/Contents.json create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Assets.xcassets/LaunchImage.launchimage/Default-568h@2x.png create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Assets.xcassets/LaunchImage.launchimage/Default-667h@2x.png create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Assets.xcassets/LaunchImage.launchimage/Default-736h@3x.png create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Assets.xcassets/LaunchImage.launchimage/Default@2x.png create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Assets.xcassets/icon.imageset/Contents.json create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Assets.xcassets/icon.imageset/star-1.png create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Assets.xcassets/icon.imageset/star-2.png create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Assets.xcassets/icon.imageset/star.png create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Base.lproj/LaunchScreen.storyboard create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/AppDelegate.swift create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/Components/BalloonMarker.swift create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/Components/RadarMarkerView.swift create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/Components/RadarMarkerView.xib create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/Components/XYMarkerView.swift create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/DemoBaseViewController.swift create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/DemoListViewController.swift create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/DemoListViewController.xib create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/AnotherBarChartViewController.swift create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/AnotherBarChartViewController.xib create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/BarChartViewController.swift create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/BarChartViewController.xib create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/BubbleChartViewController.swift create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/BubbleChartViewController.xib create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/CandleStickChartViewController.swift create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/CandleStickChartViewController.xib create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/ColoredLineChartViewController.swift create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/ColoredLineChartViewController.xib create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/CombinedChartViewController.swift create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/CombinedChartViewController.xib create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/CubicLineChartViewController.swift create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/CubicLineChartViewController.xib create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/HalfPieChartViewController.swift create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/HalfPieChartViewController.xib create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/HorizontalBarChartViewController.swift create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/HorizontalBarChartViewController.xib create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChart1ViewController.swift create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChart1ViewController.xib create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChart2ViewController.swift create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChart2ViewController.xib create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChartFilledViewController.swift create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChartFilledViewController.xib create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChartTimeViewController.swift create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChartTimeViewController.xib create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/MultipleBarChartViewController.swift create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/MultipleBarChartViewController.xib create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/MultipleLinesChartViewController.swift create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/MultipleLinesChartViewController.xib create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/NegativeStackedBarChartViewController.swift create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/NegativeStackedBarChartViewController.xib create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/PieChartViewController.swift create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/PieChartViewController.xib create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/PiePolylineChartViewController.swift create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/PiePolylineChartViewController.xib create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/PositiveNegativeBarChartViewController.swift create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/PositiveNegativeBarChartViewController.xib create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/RadarChartViewController.swift create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/RadarChartViewController.xib create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/ScatterChartViewController.swift create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/ScatterChartViewController.xib create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/SinusBarChartViewController.swift create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/SinusBarChartViewController.xib create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/StackedBarChartViewController.swift create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/StackedBarChartViewController.xib create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/Formatters/DateValueFormatter.swift create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/Formatters/DayAxisValueFormatter.swift create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/Formatters/IntAxisValueFormatter.swift create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Classes/Formatters/LargeValueFormatter.swift create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS/Info.plist diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Assets.xcassets/AppIcon.appiconset/Contents.json b/ChartsDemo-iOS/ChartsDemo-iOS/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000000..32d8413dd0 --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,59 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-60@3x.png", + "scale" : "3x" + }, + { + "idiom" : "ios-marketing", + "size" : "1024x1024", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Assets.xcassets/AppIcon.appiconset/Icon-29@2x.png b/ChartsDemo-iOS/ChartsDemo-iOS/Assets.xcassets/AppIcon.appiconset/Icon-29@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..33b2e63ab491d39425e104e7ef5916dd41cf6bcb GIT binary patch literal 5677 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 IIm^g@0c)79&;S4c literal 0 HcmV?d00001 diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Assets.xcassets/AppIcon.appiconset/Icon-29@3x.png b/ChartsDemo-iOS/ChartsDemo-iOS/Assets.xcassets/AppIcon.appiconset/Icon-29@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..ef18aba824097d907faf79251338789f90356692 GIT binary patch literal 10210 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 Wi~3w&#sBk@?u(@Sr!sMUzyATj7qnOa literal 0 HcmV?d00001 diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Assets.xcassets/AppIcon.appiconset/Icon-40@2x.png b/ChartsDemo-iOS/ChartsDemo-iOS/Assets.xcassets/AppIcon.appiconset/Icon-40@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..775e7277c87f33e5894daa86b314de4fd2e4b07a GIT binary patch literal 9266 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 U7%vlQ|B3)&f9CH~?#)m6H}^Ndr~m)} literal 0 HcmV?d00001 diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Assets.xcassets/LaunchImage.launchimage/Default-667h@2x.png b/ChartsDemo-iOS/ChartsDemo-iOS/Assets.xcassets/LaunchImage.launchimage/Default-667h@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a3bc101148bbb81e66044955d9d9ff5f6f6f6d74 GIT binary patch literal 22355 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 literal 0 HcmV?d00001 diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Assets.xcassets/LaunchImage.launchimage/Default@2x.png b/ChartsDemo-iOS/ChartsDemo-iOS/Assets.xcassets/LaunchImage.launchimage/Default@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..16802b260b097c043a1d96e7cf24a3a0b5405506 GIT binary patch literal 14035 zcmeAS@N?(olHy`uVBq!ia0y~yU}|7sU_QXX1{7KP=)`Xz=R>BmbAYF_vqC^oep+Tu zDg%Q>Z*S<`{M#WS_MQ1LOT_FKZ0zF`?Oq=m9KBOoYV9#L&&f+)I!Wz3dqZo<$?nFwWr=OcEr*QB-~}_ddm%&Y##nf5tTHFh$Puj_O|=mM^RJ+ZCh7 zq<5^<{o3Jp#e?_E*>Ao6UtAitayhfgJg1y++giDgnGI7`TCd|*xaaosgXVq5J0EQx z$?B6mHSrzQuX{IM*l+Mo*XLPOo!INes_)zj?q5E3x}#d4{>80VEaxL5 zmZil#{nx797tdELa7}k}$P>Fxm%R&)IlQ~R{MZg%%Lk7Yi=vHUjr&BL{!L0|+uX5p z;^#c)wJmd`XU#rcZ2!b=tJcEvSJthXmbzEgrADGp)nq}!VV-wZ5gQndR!nH;*(X~N z7|hJFV+~P&vuc^LtVSW9V?_$}% zC(g;#o?pR!;4t5o8O$Glt=IdzLHpB2C%rw@n_s^Y^08UDf936!U$1bzTfK5?$HZT@ zTif=BdL-wiO}J=d=Qg2T{Io*c;nbR%3kCm~E6aMet0tYbx-OgX}hY$ZF$eB z_ovuT6@AM6bWc%v^z_?hop_1i{^ z^-WRCeypMuj_tY@n{)p;XJ7Je^GLjXg>Q3Yp5c)>Gej>dbXOl0EcB2`-!XOm4)#*z z9nZJ<%>6fmE2BqreX+s}E3?&SsuV9&I@DI(N*8~-;_aNm-kZDh-v>{*{?w#y)ry!6 zUk=tq8v9xXRBrONeWiEdmBNPi3i}tyuQ>Q!cjMzCHb_`sNdc^+B->Ug!Z$#{ zIlm}X!Bo#g&p^qJOF==wrYI%ND#*nRsvXF)RmvzSDX`MlFE20GD>v55FG|-pw6wI; zH!#vSGSUUA&@HaaD@m--%_~-h7y>iLCAB!YD6^m>Ge1uOWNuJ**9#9ZqJ{ZIDce;{r$hM(47(sY92y*a4lwkH>ghrG zKo2pGdT2C;fXQJr$pJIMXdVIY(bmss>u0p} zGurwYZT*b4enwkA!>aW&IzvetTZ1;}VwJ6hI42G>R#V51GN(RFU43-?BsRx*vQ z6$Op2j4pl!w!cSL^8)LH#?kfGz{#i41>~cJ0%Y8oriDTy{~vSiNdYI-9Y9-8JYD@< J);T3K0RVdZWCZ{K literal 0 HcmV?d00001 diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Assets.xcassets/icon.imageset/Contents.json b/ChartsDemo-iOS/ChartsDemo-iOS/Assets.xcassets/icon.imageset/Contents.json new file mode 100644 index 0000000000..8c89aaaae3 --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Assets.xcassets/icon.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "star-2.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "star-1.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "star.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Assets.xcassets/icon.imageset/star-1.png b/ChartsDemo-iOS/ChartsDemo-iOS/Assets.xcassets/icon.imageset/star-1.png new file mode 100644 index 0000000000000000000000000000000000000000..c7811ef2b89b0097f0c64f26718cc07e5a5b64b8 GIT binary patch literal 1221 zcmV;$1UmbPP)U=4^(ZyKr5oQs+34wu%k3i zNrRP02!%k}R7xn6hXLd3$C)m$1Abpf`mL-pbLRVIe9oD<1dF&C47!xayF?TakzQhM zS4ugv<`@CXL=;uPlm=Yy8ykyRiA&WSrh~z50)|-R0+<~Z_3i{Nx z4%V9S_?HZP0zk7!T!^%YdaaVv3{NeCoRRJ@> z;G0793j^NgM7|G^)r`oQ{_*j-vI4T1|7wYx2;LKo0D!eS>y||bk^gWdIQL^N6spUX z-BRX_-7d5STF@G3fxF9PO#qRPfFEYgovSGlunT-)`9CMXd+I=^ug?ci)eDtF4>=s4 z=Lwh&2D`JT-4YtQ+^F#$+{jv=1MW^|g&jrsbS4z)d@6u|Ay~a?M0wfgP-?9LY$P%S z05p64ygQ}qPpm#N?pK{?d;jH6YOp~>%_NeWDI~X&5G6&v%v_5^;;fB`0)-jC0S&P30N){L?eO+cHH@{;!IHze|*0P4|J3)aTZEsiHRs$DG&o_ z_7L_>shqtl-rBvKZ zCU0#s0Ad~+n4H|P0RS?YVQAV%0Boh4YYQrnPAV+je2k^v zo&Zef^f%*`lg-d{KD4K{EV)uDB{th-Alrh!zISi^ z%&!;vZ+jS?HYfg$uEG`v8Vq~U^~#7~GnIm>0bV@e!`g!woSVg6P?U7O}^7nU=4^(ZyKr5oQs+34wu%k3i zNrRP02!%k}R7xn6hXLd3$C)m$1Abpf`mL-pbLRVIe9oD<1dF&C47!xayF?TakzQhM zS4ugv<`@CXL=;uPlm=Yy8ykyRiA&WSrh~z50)|-R0+<~Z_3i{Nx z4%V9S_?HZP0zk7!T!^%YdaaVv3{NeCoRRJ@> z;G0793j^NgM7|G^)r`oQ{_*j-vI4T1|7wYx2;LKo0D!eS>y||bk^gWdIQL^N6spUX z-BRX_-7d5STF@G3fxF9PO#qRPfFEYgovSGlunT-)`9CMXd+I=^ug?ci)eDtF4>=s4 z=Lwh&2D`JT-4YtQ+^F#$+{jv=1MW^|g&jrsbS4z)d@6u|Ay~a?M0wfgP-?9LY$P%S z05p64ygQ}qPpm#N?pK{?d;jH6YOp~>%_NeWDI~X&5G6&v%v_5^;;fB`0)-jC0S&P30N){L?eO+cHH@{;!IHze|*0P4|J3)aTZEsiHRs$DG&o_ z_7L_>shqtl-rBvKZ zCU0#s0Ad~+n4H|P0RS?YVQAV%0Boh4YYQrnPAV+je2k^v zo&Zef^f%*`lg-d{KD4K{EV)uDB{th-Alrh!zISi^ z%&!;vZ+jS?HYfg$uEG`v8Vq~U^~#7~GnIm>0bV@e!`g!woSVg6P?U7O}^7nU=4^(ZyKr5oQs+34wu%k3i zNrRP02!%k}R7xn6hXLd3$C)m$1Abpf`mL-pbLRVIe9oD<1dF&C47!xayF?TakzQhM zS4ugv<`@CXL=;uPlm=Yy8ykyRiA&WSrh~z50)|-R0+<~Z_3i{Nx z4%V9S_?HZP0zk7!T!^%YdaaVv3{NeCoRRJ@> z;G0793j^NgM7|G^)r`oQ{_*j-vI4T1|7wYx2;LKo0D!eS>y||bk^gWdIQL^N6spUX z-BRX_-7d5STF@G3fxF9PO#qRPfFEYgovSGlunT-)`9CMXd+I=^ug?ci)eDtF4>=s4 z=Lwh&2D`JT-4YtQ+^F#$+{jv=1MW^|g&jrsbS4z)d@6u|Ay~a?M0wfgP-?9LY$P%S z05p64ygQ}qPpm#N?pK{?d;jH6YOp~>%_NeWDI~X&5G6&v%v_5^;;fB`0)-jC0S&P30N){L?eO+cHH@{;!IHze|*0P4|J3)aTZEsiHRs$DG&o_ z_7L_>shqtl-rBvKZ zCU0#s0Ad~+n4H|P0RS?YVQAV%0Boh4YYQrnPAV+je2k^v zo&Zef^f%*`lg-d{KD4K{EV)uDB{th-Alrh!zISi^ z%&!;vZ+jS?HYfg$uEG`v8Vq~U^~#7~GnIm>0bV@e!`g!woSVg6P?U7O}^7n + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/AppDelegate.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/AppDelegate.swift new file mode 100644 index 0000000000..7f13108e70 --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/AppDelegate.swift @@ -0,0 +1,54 @@ +// +// AppDelegate.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-03. +// Copyright © 2017 jc. All rights reserved. +// + +import UIKit + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + + var window: UIWindow? + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { + // Override point for customization after application launch. + self.window = UIWindow(frame: UIScreen.main.bounds) + + + let vc = DemoListViewController() + let nav = UINavigationController(rootViewController: vc) + + window?.rootViewController = nav + window?.makeKeyAndVisible() + + return true + } + + func applicationWillResignActive(_ application: UIApplication) { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. + } + + func applicationDidEnterBackground(_ application: UIApplication) { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. + } + + func applicationWillEnterForeground(_ application: UIApplication) { + // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. + } + + func applicationDidBecomeActive(_ application: UIApplication) { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. + } + + func applicationWillTerminate(_ application: UIApplication) { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. + } + + +} + diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Components/BalloonMarker.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Components/BalloonMarker.swift new file mode 100644 index 0000000000..d18b3d2823 --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Components/BalloonMarker.swift @@ -0,0 +1,122 @@ +// +// BalloonMarker.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-09. +// Copyright © 2017 jc. All rights reserved. +// + +import Foundation +import Charts + +public class BalloonMarker: MarkerImage { + public var color: UIColor + public var arrowSize = CGSize(width: 15, height: 11) + public var font: UIFont + public var textColor: UIColor + public var insets: UIEdgeInsets + public var minimumSize = CGSize() + + fileprivate var label: String? + fileprivate var _labelSize: CGSize = CGSize() + fileprivate var _paragraphStyle: NSMutableParagraphStyle? + fileprivate var _drawAttributes = [NSAttributedStringKey : AnyObject]() + + public init(color: UIColor, font: UIFont, textColor: UIColor, insets: UIEdgeInsets) { + self.color = color + self.font = font + self.textColor = textColor + self.insets = insets + + _paragraphStyle = NSParagraphStyle.default.mutableCopy() as? NSMutableParagraphStyle + _paragraphStyle?.alignment = .center + super.init() + } + + public override func offsetForDrawing(atPoint point: CGPoint) -> CGPoint { + let size = self.size + var point = point + point.x -= size.width / 2.0 + point.y -= size.height + return super.offsetForDrawing(atPoint: point) + } + + public override func draw(context: CGContext, point: CGPoint) { + guard let label = label else { return } + + let offset = self.offsetForDrawing(atPoint: point) + let size = self.size + + var rect = CGRect( + origin: CGPoint( + x: point.x + offset.x, + y: point.y + offset.y), + size: size) + rect.origin.x -= size.width / 2.0 + rect.origin.y -= size.height + + context.saveGState() + + context.setFillColor(color.cgColor) + context.beginPath() + context.move(to: CGPoint( + x: rect.origin.x, + y: rect.origin.y)) + context.addLine(to: CGPoint( + x: rect.origin.x + rect.size.width, + y: rect.origin.y)) + context.addLine(to: CGPoint( + x: rect.origin.x + rect.size.width, + y: rect.origin.y + rect.size.height - arrowSize.height)) + context.addLine(to: CGPoint( + x: rect.origin.x + (rect.size.width + arrowSize.width) / 2.0, + y: rect.origin.y + rect.size.height - arrowSize.height)) + context.addLine(to: CGPoint( + x: rect.origin.x + rect.size.width / 2.0, + y: rect.origin.y + rect.size.height)) + context.addLine(to: CGPoint( + x: rect.origin.x + (rect.size.width - arrowSize.width) / 2.0, + y: rect.origin.y + rect.size.height - arrowSize.height)) + context.addLine(to: CGPoint( + x: rect.origin.x, + y: rect.origin.y + rect.size.height - arrowSize.height)) + context.addLine(to: CGPoint( + x: rect.origin.x, + y: rect.origin.y)) + context.fillPath() + + rect.origin.y += self.insets.top + rect.size.height -= self.insets.top + self.insets.bottom + + UIGraphicsPushContext(context) + + label.draw(in: rect, withAttributes: _drawAttributes) + + UIGraphicsPopContext() + + context.restoreGState() + } + + public override func refreshContent(entry: ChartDataEntry, highlight: Highlight) { + setLabel(String(entry.y)) + } + + public func setLabel(_ newLabel: String) { + label = newLabel + + _drawAttributes.removeAll() + _drawAttributes[.font] = self.font + _drawAttributes[.paragraphStyle] = _paragraphStyle + _drawAttributes[.foregroundColor] = self.textColor + + _labelSize = label?.size(withAttributes: _drawAttributes) ?? CGSize.zero + + var size = CGSize() + size.width = _labelSize.width + self.insets.left + self.insets.right + size.height = _labelSize.height + self.insets.top + self.insets.bottom + size.width = max(minimumSize.width, size.width) + size.height = max(minimumSize.height, size.height) + self.size = size + } + +} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Components/RadarMarkerView.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Components/RadarMarkerView.swift new file mode 100644 index 0000000000..019196d5e8 --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Components/RadarMarkerView.swift @@ -0,0 +1,27 @@ +// +// RadarMarkerView.swift +// ChartsDemo +// +// 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 Charts + +public class RadarMarkerView: MarkerView { + @IBOutlet var label: UILabel! + + public override func awakeFromNib() { + self.offset.x = -self.frame.size.width / 2.0 + self.offset.y = -self.frame.size.height - 7.0 + } + + public override func refreshContent(entry: ChartDataEntry, highlight: Highlight) { + label.text = String.init(format: "%d %%", Int(round(entry.y))) + layoutIfNeeded() + } +} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Components/RadarMarkerView.xib b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Components/RadarMarkerView.xib new file mode 100644 index 0000000000..687b73c95b --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Components/RadarMarkerView.xib @@ -0,0 +1,52 @@ + + + + + + + + + + + + HelveticaNeue-Light + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Components/XYMarkerView.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Components/XYMarkerView.swift new file mode 100644 index 0000000000..290ab85011 --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Components/XYMarkerView.swift @@ -0,0 +1,32 @@ +// +// XYMarkerView.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-09. +// Copyright © 2017 jc. All rights reserved. +// + +import Foundation +import Charts + +public class XYMarkerView: BalloonMarker { + public var xAxisValueFormatter: AxisValueFormatter + fileprivate var yFormatter = NumberFormatter() + + public init(color: UIColor, font: UIFont, textColor: UIColor, insets: UIEdgeInsets, + xAxisValueFormatter: AxisValueFormatter) { + self.xAxisValueFormatter = xAxisValueFormatter + yFormatter.minimumFractionDigits = 1 + yFormatter.maximumFractionDigits = 1 + super.init(color: color, font: font, textColor: textColor, insets: insets) + } + + public override func refreshContent(entry: ChartDataEntry, highlight: Highlight) { + let string = "x: " + + xAxisValueFormatter.stringForValue(entry.x, axis: XAxis()) + + ", y: " + + yFormatter.string(from: NSNumber(floatLiteral: entry.y))! + setLabel(string) + } + +} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/DemoBaseViewController.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/DemoBaseViewController.swift new file mode 100644 index 0000000000..2de87b60dc --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/DemoBaseViewController.swift @@ -0,0 +1,362 @@ +// +// DemoBaseViewController.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-03. +// Copyright © 2017 jc. All rights reserved. +// + +import UIKit +import Charts + +enum Option { + case toggleValues + case toggleIcons + case toggleHighlight + case animateX + case animateY + case animateXY + case saveToGallery + case togglePinchZoom + case toggleAutoScaleMinMax + case toggleData + case toggleBarBorders + // CandleChart + case toggleShadowColorSameAsCandle + // CombinedChart + case toggleLineValues + case toggleBarValues + case removeDataSet + // CubicLineSampleFillFormatter + case toggleFilled + case toggleCircles + case toggleCubic + case toggleHorizontalCubic + case toggleStepped + // HalfPieChartController + case toggleXValues + case togglePercent + case toggleHole + case spin + case drawCenter + // RadarChart + case toggleXLabels + case toggleYLabels + case toggleRotate + case toggleHighlightCircle + + var label: String { + switch self { + case .toggleValues: return "Toggle Y-Values" + case .toggleIcons: return "Toggle Icons" + case .toggleHighlight: return "Toggle Highlight" + case .animateX: return "Animate X" + case .animateY: return "Animate Y" + case .animateXY: return "Animate XY" + case .saveToGallery: return "Save to Camera Roll" + case .togglePinchZoom: return "Toggle PinchZoom" + case .toggleAutoScaleMinMax: return "Toggle auto scale min/max" + case .toggleData: return "Toggle Data" + case .toggleBarBorders: return "Toggle Bar Borders" + // CandleChart + case .toggleShadowColorSameAsCandle: return "Toggle shadow same color" + // CombinedChart + case .toggleLineValues: return "Toggle Line Values" + case .toggleBarValues: return "Toggle Bar Values" + case .removeDataSet: return "Remove Random Set" + // CubicLineSampleFillFormatter + case .toggleFilled: return "Toggle Filled" + case .toggleCircles: return "Toggle Circles" + case .toggleCubic: return "Toggle Cubic" + case .toggleHorizontalCubic: return "Toggle Horizontal Cubic" + case .toggleStepped: return "Toggle Stepped" + // HalfPieChartController + case .toggleXValues: return "Toggle X-Values" + case .togglePercent: return "Toggle Percent" + case .toggleHole: return "Toggle Hole" + case .spin: return "Spin" + case .drawCenter: return "Draw CenterText" + // RadarChart + case .toggleXLabels: return "Toggle X-Labels" + case .toggleYLabels: return "Toggle Y-Labels" + case .toggleRotate: return "Toggle Rotate" + case .toggleHighlightCircle: return "Toggle highlight circle" + } + } +} + +class DemoBaseViewController: UIViewController, ChartViewDelegate { + private var optionsTableView: UITableView? = nil + let parties = ["Party A", "Party B", "Party C", "Party D", "Party E", "Party F", + "Party G", "Party H", "Party I", "Party J", "Party K", "Party L", + "Party M", "Party N", "Party O", "Party P", "Party Q", "Party R", + "Party S", "Party T", "Party U", "Party V", "Party W", "Party X", + "Party Y", "Party Z"] + + @IBOutlet weak var optionsButton: UIButton! + var options: [Option]! + + var shouldHideData: Bool = false + + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + self.initialize() + } + + override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { + super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) + self.initialize() + } + + private func initialize() { + self.edgesForExtendedLayout = [] + } + + func optionTapped(_ option: Option) {} + + func handleOption(_ option: Option, forChartView chartView: ChartViewBase) { + switch option { + case .toggleValues: + for set in chartView.data!.dataSets { + set.isDrawValuesEnabled = !set.isDrawValuesEnabled + } + chartView.setNeedsDisplay() + + case .toggleIcons: + for set in chartView.data!.dataSets { + set.isDrawIconsEnabled = !set.isDrawIconsEnabled + } + chartView.setNeedsDisplay() + + case .toggleHighlight: + chartView.data!.highlightEnabled = !chartView.data!.isHighlightEnabled + chartView.setNeedsDisplay() + + case .animateX: + chartView.animate(xAxisDuration: 3) + + case .animateY: + chartView.animate(yAxisDuration: 3) + + case .animateXY: + chartView.animate(xAxisDuration: 3, yAxisDuration: 3) + + case .saveToGallery: + UIImageWriteToSavedPhotosAlbum(chartView.getChartImage(transparent: false)!, nil, nil, nil) + + case .togglePinchZoom: + let barLineChart = chartView as! BarLineChartViewBase + barLineChart.isPinchZoomEnabled = !barLineChart.isPinchZoomEnabled + chartView.setNeedsDisplay() + + case .toggleAutoScaleMinMax: + let barLineChart = chartView as! BarLineChartViewBase + barLineChart.autoScaleMinMaxEnabled = !barLineChart.isAutoScaleMinMaxEnabled + chartView.notifyDataSetChanged() + + case .toggleData: + shouldHideData = !shouldHideData + updateChartData() + + case .toggleBarBorders: + for set in chartView.data!.dataSets { + if let set = set as? BarChartDataSet { + set.barBorderWidth = set.barBorderWidth == 1.0 ? 0.0 : 1.0 + } + } + chartView.setNeedsDisplay() + default: + break + } + } + + @IBAction func optionsButtonTapped(_ sender: Any) { + if let optionsTableView = self.optionsTableView { + optionsTableView.removeFromSuperview() + self.optionsTableView = nil + return + } + + let optionsTableView = UITableView() + optionsTableView.backgroundColor = UIColor(white: 0, alpha: 0.9) + optionsTableView.delegate = self + optionsTableView.dataSource = self + + optionsTableView.translatesAutoresizingMaskIntoConstraints = false + + self.optionsTableView = optionsTableView + + var constraints = [NSLayoutConstraint]() + + constraints.append(NSLayoutConstraint(item: optionsTableView, + attribute: .leading, + relatedBy: .equal, + toItem: self.view, + attribute: .leading, + multiplier: 1, + constant: 40)) + + constraints.append(NSLayoutConstraint(item: optionsTableView, + attribute: .trailing, + relatedBy: .equal, + toItem: sender as! UIView, + attribute: .trailing, + multiplier: 1, + constant: 0)) + + constraints.append(NSLayoutConstraint(item: optionsTableView, + attribute: .top, + relatedBy: .equal, + toItem: sender, + attribute: .bottom, + multiplier: 1, + constant: 5)) + + self.view.addSubview(optionsTableView) + constraints.forEach { $0.isActive = true } + + let constraint = NSLayoutConstraint(item: optionsTableView, + attribute: .height, + relatedBy: .equal, + toItem: nil, + attribute: .height, + multiplier: 1, + constant: 220) + constraint.isActive = true + } + + func updateChartData() { + fatalError("updateChartData not overridden") + } + + func setup(pieChartView chartView: PieChartView) { + chartView.usePercentValues = true + chartView.isDrawSlicesUnderHoleEnabled = false + chartView.holeRadiusPercent = 0.58 + chartView.transparentCircleRadiusPercent = 0.61 + chartView.chartDescription?.isEnabled = false + chartView.setExtraOffsets(left: 5, top: 10, right: 5, bottom: 5) + + chartView.isDrawCenterTextEnabled = true + + let paragraphStyle = NSParagraphStyle.default.mutableCopy() as! NSMutableParagraphStyle + paragraphStyle.lineBreakMode = .byTruncatingTail + paragraphStyle.alignment = .center + + let centerText = NSMutableAttributedString(string: "Charts\nby Daniel Cohen Gindi") + centerText.setAttributes([.font : UIFont(name: "HelveticaNeue-Light", size: 13)!, + .paragraphStyle : paragraphStyle], range: NSRange(location: 0, length: centerText.length)) + centerText.addAttributes([.font : UIFont(name: "HelveticaNeue-Light", size: 11)!, + .foregroundColor : UIColor.gray], range: NSRange(location: 10, length: centerText.length - 10)) + centerText.addAttributes([.font : UIFont(name: "HelveticaNeue-Light", size: 11)!, + .foregroundColor : UIColor(red: 51/255, green: 181/255, blue: 229/255, alpha: 1)], range: NSRange(location: centerText.length - 19, length: 19)) + chartView.centerAttributedText = centerText; + + chartView.isDrawHoleEnabled = true + chartView.rotationAngle = 0 + chartView.isRotationEnabled = true + chartView.isHighlightPerTapEnabled = true + + var l = chartView.legend + l.horizontalAlignment = .right + l.verticalAlignment = .top + l.orientation = .vertical + l.drawInside = false + l.xEntrySpace = 7 + l.yEntrySpace = 0 + l.yOffset = 0 + chartView.legend = l + } + + func setup(radarChartView chartView: RadarChartView) { + chartView.chartDescription?.isEnabled = false + } + + func setup(barLineChartView chartView: BarLineChartViewBase) { + chartView.chartDescription?.isEnabled = false + + chartView.isDragEnabled = true + chartView.setScaleEnabled(true) + chartView.isPinchZoomEnabled = false + + // ChartYAxis *leftAxis = chartView.leftAxis; + + let xAxis = chartView.xAxis + xAxis.labelPosition = .bottom + + chartView.rightAxis.isEnabled = false + } + // TODO: Cannot override from extensions + //extension DemoBaseViewController: ChartViewDelegate { + func chartValueSelected(_ chartView: ChartViewBase, entry: ChartDataEntry, highlight: Highlight) { + NSLog("chartValueSelected"); + } + + func chartValueNothingSelected(_ chartView: ChartViewBase) { + NSLog("chartValueNothingSelected"); + } + + func chartScaled(_ chartView: ChartViewBase, scaleX: CGFloat, scaleY: CGFloat) { + + } + + func chartTranslated(_ chartView: ChartViewBase, dX: CGFloat, dY: CGFloat) { + + } +} + +extension DemoBaseViewController: UITableViewDelegate, UITableViewDataSource { + func numberOfSections(in tableView: UITableView) -> Int { + if optionsTableView != nil { + return 1 + } + + return 0 + } + + @available(iOS 2.0, *) + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + if optionsTableView != nil { + return options.count + } + + return 0 + + } + + func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { + if optionsTableView != nil { + return 40.0; + } + + return 44.0; + } + + @available(iOS 2.0, *) + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + var cell = tableView.dequeueReusableCell(withIdentifier: "Cell") + + if cell == nil { + cell = UITableViewCell(style: .default, reuseIdentifier: "Cell") + cell?.backgroundView = nil + cell?.backgroundColor = .clear + cell?.textLabel?.textColor = .white + } + cell?.textLabel?.text = self.options[indexPath.row].label + + return cell! + } + + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + if optionsTableView != nil { + tableView.deselectRow(at: indexPath, animated: true) + + optionsTableView?.removeFromSuperview() + self.optionsTableView = nil + + self.optionTapped(self.options[indexPath.row]) + } + + } +} + diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/DemoListViewController.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/DemoListViewController.swift new file mode 100644 index 0000000000..1322e488cb --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/DemoListViewController.swift @@ -0,0 +1,129 @@ +// +// DemoListViewController.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-09. +// Copyright © 2017 jc. All rights reserved. +// + +import UIKit + +private struct ItemDef { + let title: String + let subtitle: String + let `class`: AnyClass +} + +class DemoListViewController: UIViewController { + + @IBOutlet var tableView: UITableView! + private var itemDefs = [ItemDef(title: "Line Chart", + subtitle: "A simple demonstration of the linechart.", + class: LineChart1ViewController.self), + ItemDef(title: "Line Chart (Dual YAxis)", + subtitle: "Demonstration of the linechart with dual y-axis.", + class: LineChart2ViewController.self), + ItemDef(title: "Bar Chart", + subtitle: "A simple demonstration of the bar chart.", + class: BarChartViewController.self), + ItemDef(title: "Horizontal Bar Chart", + subtitle: "A simple demonstration of the horizontal bar chart.", + class: HorizontalBarChartViewController.self), + ItemDef(title: "Combined Chart", + subtitle: "Demonstrates how to create a combined chart (bar and line in this case).", + class: CombinedChartViewController.self), + ItemDef(title: "Pie Chart", + subtitle: "A simple demonstration of the pie chart.", + class: PieChartViewController.self), + ItemDef(title: "Pie Chart with value lines", + subtitle: "A simple demonstration of the pie chart with polyline notes.", + class: PiePolylineChartViewController.self), + ItemDef(title: "Scatter Chart", + subtitle: "A simple demonstration of the scatter chart.", + class: ScatterChartViewController.self), + ItemDef(title: "Bubble Chart", + subtitle: "A simple demonstration of the bubble chart.", + class: BubbleChartViewController.self), + ItemDef(title: "Stacked Bar Chart", + subtitle: "A simple demonstration of a bar chart with stacked bars.", + class: StackedBarChartViewController.self), + ItemDef(title: "Stacked Bar Chart Negative", + subtitle: "A simple demonstration of stacked bars with negative and positive values.", + class: NegativeStackedBarChartViewController.self), + ItemDef(title: "Another Bar Chart", + subtitle: "Implementation of a BarChart that only shows values at the bottom.", + class: AnotherBarChartViewController.self), + ItemDef(title: "Multiple Lines Chart", + subtitle: "A line chart with multiple DataSet objects. One color per DataSet.", + class: MultipleLinesChartViewController.self), + ItemDef(title: "Multiple Bars Chart", + subtitle: "A bar chart with multiple DataSet objects. One multiple colors per DataSet.", + class: MultipleBarChartViewController.self), + ItemDef(title: "Candle Stick Chart", + subtitle: "Demonstrates usage of the CandleStickChart.", + class: CandleStickChartViewController.self), + ItemDef(title: "Cubic Line Chart", + subtitle: "Demonstrates cubic lines in a LineChart.", + class: CubicLineChartViewController.self), + ItemDef(title: "Radar Chart", + subtitle: "Demonstrates the use of a spider-web like (net) chart.", + class: RadarChartViewController.self), + ItemDef(title: "Colored Line Chart", + subtitle: "Shows a LineChart with different background and line color.", + class: ColoredLineChartViewController.self), + ItemDef(title: "Sinus Bar Chart", + subtitle: "A Bar Chart plotting the sinus function with 8.000 values.", + class: SinusBarChartViewController.self), + ItemDef(title: "BarChart positive / negative", + subtitle: "This demonstrates how to create a BarChart with positive and negative values in different colors.", + class: PositiveNegativeBarChartViewController.self), + ItemDef(title: "Time Line Chart", + subtitle: "Simple demonstration of a time-chart. This chart draws one line entry per hour originating from the current time in milliseconds.", + class: LineChartTimeViewController.self), + ItemDef(title: "Filled Line Chart", + subtitle: "This demonstrates how to fill an area between two LineDataSets.", + class: LineChartFilledViewController.self), + ItemDef(title: "Half Pie Chart", + subtitle: "This demonstrates how to create a 180 degree PieChart.", + class: HalfPieChartViewController.self) + ] + + override func viewDidLoad() { + super.viewDidLoad() + + self.title = "Charts Demonstration" + self.tableView.rowHeight = 70 + //FIXME: Add TimeLineChart + + } +} + +extension DemoListViewController: UITableViewDelegate, UITableViewDataSource { + func numberOfSections(in tableView: UITableView) -> Int { + return 1 + } + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return self.itemDefs.count + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let def = self.itemDefs[indexPath.row] + let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") ?? UITableViewCell(style: .subtitle, reuseIdentifier: "Cell") + cell.textLabel?.text = def.title + cell.detailTextLabel?.text = def.subtitle + cell.detailTextLabel?.numberOfLines = 0 + + return cell + } + + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + let def = self.itemDefs[indexPath.row] + + let vcClass = def.class as! UIViewController.Type + let vc = vcClass.init() + + self.navigationController?.pushViewController(vc, animated: true) + tableView.deselectRow(at: indexPath, animated: true) + } +} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/DemoListViewController.xib b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/DemoListViewController.xib new file mode 100644 index 0000000000..40845c0a91 --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/DemoListViewController.xib @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/AnotherBarChartViewController.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/AnotherBarChartViewController.swift new file mode 100644 index 0000000000..8e84fa699c --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/AnotherBarChartViewController.swift @@ -0,0 +1,98 @@ +// +// AnotherBarChartViewController.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-09. +// Copyright © 2017 jc. All rights reserved. +// + +import UIKit +import Charts + +class AnotherBarChartViewController: DemoBaseViewController { + + @IBOutlet var chartView: BarChartView! + @IBOutlet var sliderX: UISlider! + @IBOutlet var sliderY: UISlider! + @IBOutlet var sliderTextX: UITextField! + @IBOutlet var sliderTextY: UITextField! + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + self.options = [.toggleValues, + .toggleHighlight, + .animateX, + .animateY, + .animateXY, + .saveToGallery, + .togglePinchZoom, + .toggleData, + .toggleBarBorders] + + chartView.delegate = self + + chartView.chartDescription?.isEnabled = false + chartView.maxVisibleCount = 60 + chartView.isPinchZoomEnabled = false + chartView.isDrawBarShadowEnabled = false + + let xAxis = chartView.xAxis + xAxis.labelPosition = .bottom + + chartView.legend.isEnabled = false + + sliderX.value = 10 + sliderY.value = 100 + self.slidersValueChanged(nil) + } + + + override func updateChartData() { + if self.shouldHideData { + chartView.data = nil + return + } + + self.setDataCount(Int(sliderX.value) + 1, range: Double(sliderY.value)) + } + + func setDataCount(_ count: Int, range: Double) { + let yVals = (0.. BarChartDataEntry in + let mult = range + 1 + let val = Double(arc4random_uniform(UInt32(mult))) + mult/3 + return BarChartDataEntry(x: Double(i), y: val) + } + + var set1: BarChartDataSet! = nil + if let set = chartView.data?.dataSets.first as? BarChartDataSet { + set1 = set + set1?.values = yVals + chartView.data?.notifyDataChanged() + chartView.notifyDataSetChanged() + } else { + set1 = BarChartDataSet(values: yVals, label: "Data Set") + set1.colors = ChartColorTemplates.vordiplom + set1.isDrawValuesEnabled = false + + let data = BarChartData(dataSet: set1) + chartView.data = data + chartView.fitBars = true + } + + chartView.setNeedsDisplay() + } + + override func optionTapped(_ option: Option) { + super.handleOption(option, forChartView: chartView) + } + + // MARK: - Actions + @IBAction func slidersValueChanged(_ sender: Any?) { + sliderTextX.text = "\(Int(sliderX.value))" + sliderTextY.text = "\(Int(sliderY.value))" + + self.updateChartData() + } +} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/AnotherBarChartViewController.xib b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/AnotherBarChartViewController.xib new file mode 100644 index 0000000000..330b30940b --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/AnotherBarChartViewController.xib @@ -0,0 +1,100 @@ + + + + + + + + + + + + HelveticaNeue-Light + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/BarChartViewController.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/BarChartViewController.swift new file mode 100644 index 0000000000..f2f9c38978 --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/BarChartViewController.swift @@ -0,0 +1,152 @@ +// +// BarChartViewController.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-09. +// Copyright © 2017 jc. All rights reserved. +// + +import UIKit +import Charts + +class BarChartViewController: DemoBaseViewController { + + @IBOutlet var chartView: BarChartView! + @IBOutlet var sliderX: UISlider! + @IBOutlet var sliderY: UISlider! + @IBOutlet var sliderTextX: UITextField! + @IBOutlet var sliderTextY: UITextField! + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + self.title = "Bar Chart" + + self.options = [.toggleValues, + .toggleHighlight, + .animateX, + .animateY, + .animateXY, + .saveToGallery, + .togglePinchZoom, + .toggleData, + .toggleBarBorders] + + self.setup(barLineChartView: chartView) + + chartView.delegate = self + + chartView.isDrawBarShadowEnabled = false + chartView.isDrawValueAboveBarEnabled = false + + chartView.maxVisibleCount = 60 + + let xAxis = chartView.xAxis + xAxis.labelPosition = .bottom + xAxis.labelFont = .systemFont(ofSize: 10) + xAxis.granularity = 1 + xAxis.labelCount = 7 + xAxis.valueFormatter = DayAxisValueFormatter(chart: chartView) + + let leftAxisFormatter = NumberFormatter() + leftAxisFormatter.minimumFractionDigits = 0 + leftAxisFormatter.maximumFractionDigits = 1 + leftAxisFormatter.negativeSuffix = " $" + leftAxisFormatter.positiveSuffix = " $" + + let leftAxis = chartView.leftAxis + leftAxis.labelFont = .systemFont(ofSize: 10) + leftAxis.labelCount = 8 + leftAxis.valueFormatter = DefaultAxisValueFormatter(formatter: leftAxisFormatter) + leftAxis.labelPosition = .outsideChart + leftAxis.spaceTop = 0.15 + leftAxis.axisMinimum = 0 // FIXME: HUH?? this replaces startAtZero = YES + + let rightAxis = chartView.rightAxis + rightAxis.isEnabled = true + rightAxis.labelFont = .systemFont(ofSize: 10) + rightAxis.labelCount = 8 + rightAxis.valueFormatter = leftAxis.valueFormatter + rightAxis.spaceTop = 0.15 + rightAxis.axisMinimum = 0 + + var l = chartView.legend + l.horizontalAlignment = .left + l.verticalAlignment = .bottom + l.orientation = .horizontal + l.drawInside = false + l.form = .circle + l.formSize = 9 + l.font = UIFont(name: "HelveticaNeue-Light", size: 11)! + l.xEntrySpace = 4 + chartView.legend = l + + let marker = XYMarkerView(color: UIColor(white: 180/250, alpha: 1), + font: .systemFont(ofSize: 12), + textColor: .white, + insets: UIEdgeInsets(top: 8, left: 8, bottom: 20, right: 8), + xAxisValueFormatter: chartView.xAxis.valueFormatter!) + marker.chartView = chartView + marker.minimumSize = CGSize(width: 80, height: 40) + chartView.marker = marker + + sliderX.value = 12 + sliderY.value = 50 + slidersValueChanged(nil) + } + + override func updateChartData() { + if self.shouldHideData { + chartView.data = nil + return + } + + self.setDataCount(Int(sliderX.value) + 1, range: UInt32(sliderY.value)) + } + + func setDataCount(_ count: Int, range: UInt32) { + let start = 1 + + let yVals = (start.. BarChartDataEntry in + let mult = range + 1 + let val = Double(arc4random_uniform(mult)) + if arc4random_uniform(100) < 25 { + return BarChartDataEntry(x: Double(i), y: val, icon: UIImage(named: "icon")) + } else { + return BarChartDataEntry(x: Double(i), y: val) + } + } + + var set1: BarChartDataSet! = nil + if let set = chartView.data?.dataSets.first as? BarChartDataSet { + set1 = set + set1.values = yVals + chartView.data?.notifyDataChanged() + chartView.notifyDataSetChanged() + } else { + set1 = BarChartDataSet(values: yVals, label: "The year 2017") + set1.colors = ChartColorTemplates.material + set1.isDrawValuesEnabled = false + + let data = BarChartData(dataSet: set1) + data.setValueFont(UIFont(name: "HelveticaNeue-Light", size: 10)!) + data.barWidth = 0.9 + chartView.data = data + } + +// chartView.setNeedsDisplay() + } + + override func optionTapped(_ option: Option) { + super.handleOption(option, forChartView: chartView) + } + + // MARK: - Actions + @IBAction func slidersValueChanged(_ sender: Any?) { + sliderTextX.text = "\(Int(sliderX.value + 2))" + sliderTextY.text = "\(Int(sliderY.value))" + + self.updateChartData() + } +} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/BarChartViewController.xib b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/BarChartViewController.xib new file mode 100644 index 0000000000..1c769416b8 --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/BarChartViewController.xib @@ -0,0 +1,100 @@ + + + + + + + + + + + + HelveticaNeue-Light + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/BubbleChartViewController.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/BubbleChartViewController.swift new file mode 100644 index 0000000000..3df67ae068 --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/BubbleChartViewController.swift @@ -0,0 +1,127 @@ +// +// BubbleChartViewController.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-09. +// Copyright © 2017 jc. All rights reserved. +// + +import UIKit +import Charts + +class BubbleChartViewController: DemoBaseViewController { + + @IBOutlet var chartView: BubbleChartView! + @IBOutlet var sliderX: UISlider! + @IBOutlet var sliderY: UISlider! + @IBOutlet var sliderTextX: UITextField! + @IBOutlet var sliderTextY: UITextField! + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + self.title = "Bubble Chart" + self.options = [.toggleValues, + .toggleIcons, + .toggleHighlight, + .animateX, + .animateY, + .animateXY, + .saveToGallery, + .togglePinchZoom, + .toggleAutoScaleMinMax, + .toggleData] + + chartView.delegate = self + + chartView.chartDescription?.isEnabled = false + + chartView.isDragEnabled = false + chartView.setScaleEnabled(true) + chartView.maxVisibleCount = 200 + chartView.isPinchZoomEnabled = true + + chartView.legend.horizontalAlignment = .right + chartView.legend.verticalAlignment = .top + chartView.legend.orientation = .vertical + chartView.legend.drawInside = false + chartView.legend.font = UIFont(name: "HelveticaNeue-Light", size: 10)! + + chartView.leftAxis.labelFont = UIFont(name: "HelveticaNeue-Light", size: 10)! + chartView.leftAxis.spaceTop = 0.3 + chartView.leftAxis.spaceBottom = 0.3 + chartView.leftAxis.axisMinimum = 0 + + chartView.rightAxis.isEnabled = false + + chartView.xAxis.labelPosition = .bottom + chartView.xAxis.labelFont = UIFont(name: "HelveticaNeue-Light", size: 10)! + + sliderX.value = 10 + sliderY.value = 50 + slidersValueChanged(nil) + } + + override func updateChartData() { + if self.shouldHideData { + chartView.data = nil + return + } + + self.setDataCount(Int(sliderX.value), range: UInt32(sliderY.value)) + } + + func setDataCount(_ count: Int, range: UInt32) { + let yVals1 = (0.. BubbleChartDataEntry in + let val = Double(arc4random_uniform(range)) + let size = CGFloat(arc4random_uniform(range)) + return BubbleChartDataEntry(x: Double(i), y: val, size: size, icon: UIImage(named: "icon")) + } + let yVals2 = (0.. BubbleChartDataEntry in + let val = Double(arc4random_uniform(range)) + let size = CGFloat(arc4random_uniform(range)) + return BubbleChartDataEntry(x: Double(i), y: val, size: size, icon: UIImage(named: "icon")) + } + let yVals3 = (0.. BubbleChartDataEntry in + let val = Double(arc4random_uniform(range)) + let size = CGFloat(arc4random_uniform(range)) + return BubbleChartDataEntry(x: Double(i), y: val, size: size) + } + + let set1 = BubbleChartDataSet(values: yVals1, label: "DS 1") + set1.isDrawIconsEnabled = false + set1.setColor(ChartColorTemplates.colorful[0], alpha: 0.5) + set1.isDrawValuesEnabled = true + + let set2 = BubbleChartDataSet(values: yVals2, label: "DS 2") + set2.isDrawIconsEnabled = false + set2.iconsOffset = CGPoint(x: 0, y: 15) + set2.setColor(ChartColorTemplates.colorful[1], alpha: 0.5) + set2.isDrawValuesEnabled = true + + let set3 = BubbleChartDataSet(values: yVals3, label: "DS 3") + set3.setColor(ChartColorTemplates.colorful[2], alpha: 0.5) + set3.isDrawValuesEnabled = true + + let data = BubbleChartData(dataSets: [set1, set2, set3]) + data.setDrawValues(false) + data.setValueFont(UIFont(name: "HelveticaNeue-Light", size: 7)!) + data.setHighlightCircleWidth(1.5) + data.setValueTextColor(.white) + + chartView.data = data + } + + override func optionTapped(_ option: Option) { + super.handleOption(option, forChartView: chartView) + } + + // MARK: - Actions + @IBAction func slidersValueChanged(_ sender: Any?) { + sliderTextX.text = "\(Int(sliderX.value))" + sliderTextY.text = "\(Int(sliderY.value))" + + self.updateChartData() + } +} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/BubbleChartViewController.xib b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/BubbleChartViewController.xib new file mode 100644 index 0000000000..f49a384cbe --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/BubbleChartViewController.xib @@ -0,0 +1,100 @@ + + + + + + + + + + + + HelveticaNeue-Light + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/CandleStickChartViewController.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/CandleStickChartViewController.swift new file mode 100644 index 0000000000..df04b90db1 --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/CandleStickChartViewController.swift @@ -0,0 +1,122 @@ +// +// CandleStickChartViewController.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-09. +// Copyright © 2017 jc. All rights reserved. +// + +import UIKit +import Charts + +class CandleStickChartViewController: DemoBaseViewController { + + @IBOutlet var chartView: CandleStickChartView! + @IBOutlet var sliderX: UISlider! + @IBOutlet var sliderY: UISlider! + @IBOutlet var sliderTextX: UITextField! + @IBOutlet var sliderTextY: UITextField! + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + self.title = "Bubble Chart" + self.options = [.toggleValues, + .toggleIcons, + .toggleHighlight, + .animateX, + .animateY, + .animateXY, + .saveToGallery, + .togglePinchZoom, + .toggleAutoScaleMinMax, + .toggleShadowColorSameAsCandle, + .toggleData] + + chartView.delegate = self + + chartView.chartDescription?.isEnabled = false + + chartView.isDragEnabled = false + chartView.setScaleEnabled(true) + chartView.maxVisibleCount = 200 + chartView.isPinchZoomEnabled = true + + chartView.legend.horizontalAlignment = .right + chartView.legend.verticalAlignment = .top + chartView.legend.orientation = .vertical + chartView.legend.drawInside = false + chartView.legend.font = UIFont(name: "HelveticaNeue-Light", size: 10)! + + chartView.leftAxis.labelFont = UIFont(name: "HelveticaNeue-Light", size: 10)! + chartView.leftAxis.spaceTop = 0.3 + chartView.leftAxis.spaceBottom = 0.3 + chartView.leftAxis.axisMinimum = 0 + + chartView.rightAxis.isEnabled = false + + chartView.xAxis.labelPosition = .bottom + chartView.xAxis.labelFont = UIFont(name: "HelveticaNeue-Light", size: 10)! + + sliderX.value = 10 + sliderY.value = 50 + slidersValueChanged(nil) + } + + override func updateChartData() { + if self.shouldHideData { + chartView.data = nil + return + } + + self.setDataCount(Int(sliderX.value), range: UInt32(sliderY.value)) + } + + func setDataCount(_ count: Int, range: UInt32) { + let yVals1 = (0.. CandleChartDataEntry in + let mult = range + 1 + let val = Double(arc4random_uniform(40) + mult) + let high = Double(arc4random_uniform(9) + 8) + let low = Double(arc4random_uniform(9) + 8) + let open = Double(arc4random_uniform(6) + 1) + let close = Double(arc4random_uniform(6) + 1) + let even = i % 2 == 0 + + return CandleChartDataEntry(x: Double(i), shadowH: val + high, shadowL: val - low, open: even ? val + open : val - open, close: even ? val - close : val + close, icon: UIImage(named: "icon")!) + } + + let set1 = CandleChartDataSet(values: yVals1, label: "Data Set") + set1.axisDependency = .left + set1.setColor(UIColor(white: 80/255, alpha: 1)) + set1.isDrawIconsEnabled = false + set1.shadowColor = .darkGray + set1.shadowWidth = 0.7 + set1.decreasingColor = .red + set1.decreasingFilled = true + set1.increasingColor = UIColor(red: 122/255, green: 242/255, blue: 84/255, alpha: 1) + set1.increasingFilled = false + set1.neutralColor = .blue + + let data = CandleChartData(dataSet: set1) + chartView.data = data + } + + override func optionTapped(_ option: Option) { + if .toggleShadowColorSameAsCandle ~= option { + for set in chartView.data!.dataSets as! [CandleChartDataSet] { + set.shadowColorSameAsCandle = !set.shadowColorSameAsCandle + } + chartView.notifyDataSetChanged() + } else { + super.handleOption(option, forChartView: chartView) + } + } + + // MARK: - Actions + @IBAction func slidersValueChanged(_ sender: Any?) { + sliderTextX.text = "\(Int(sliderX.value))" + sliderTextY.text = "\(Int(sliderY.value))" + + self.updateChartData() + }} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/CandleStickChartViewController.xib b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/CandleStickChartViewController.xib new file mode 100644 index 0000000000..598f366e54 --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/CandleStickChartViewController.xib @@ -0,0 +1,100 @@ + + + + + + + + + + + + HelveticaNeue-Light + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/ColoredLineChartViewController.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/ColoredLineChartViewController.swift new file mode 100644 index 0000000000..0c2e651594 --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/ColoredLineChartViewController.swift @@ -0,0 +1,77 @@ +// +// ColoredLineChartViewController.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-04. +// Copyright © 2017 jc. All rights reserved. +// + +import UIKit +import Charts + +class ColoredLineChartViewController: DemoBaseViewController { + @IBOutlet var chartViews: [LineChartView]! + + override func viewDidLoad() { + super.viewDidLoad() + + self.title = "Colored Line Chart" + + let colors = [UIColor(red: 137/255, green: 230/255, blue: 81/255, alpha: 1), + UIColor(red: 240/255, green: 240/255, blue: 30/255, alpha: 1), + UIColor(red: 89/255, green: 199/255, blue: 250/255, alpha: 1), + UIColor(red: 250/255, green: 104/255, blue: 104/255, alpha: 1)] + + for (i, chartView) in chartViews.enumerated() { + let data = dataWithCount(36, range: 100) + data.setValueFont(UIFont(name: "HelveticaNeue", size: 7)!) + + setupChart(chartView, data: data, color: colors[i % colors.count]) + } + } + + func setupChart(_ chart: LineChartView, data: LineChartData, color: UIColor) { + (data.getDataSetByIndex(0) as! LineChartDataSet).circleHoleColor = color + + chart.delegate = self + chart.backgroundColor = color + + chart.chartDescription?.isEnabled = false + + chart.isDragEnabled = true + chart.setScaleEnabled(true) + chart.isPinchZoomEnabled = false + chart.setViewPortOffsets(left: 10, top: 0, right: 10, bottom: 0) + + chart.legend.isEnabled = false + + chart.leftAxis.isEnabled = false + chart.leftAxis.spaceTop = 0.4 + chart.leftAxis.spaceBottom = 0.4 + chart.rightAxis.isEnabled = false + chart.xAxis.isEnabled = false + + chart.data = data + + chart.animate(xAxisDuration: 2.5) + } + + func dataWithCount(_ count: Int, range: UInt32) -> LineChartData { + let yVals = (0.. ChartDataEntry in + let val = Double(arc4random_uniform(range)) + 3 + return ChartDataEntry(x: Double(i), y: val) + } + + let set1 = LineChartDataSet(values: yVals, label: "DataSet 1") + + set1.lineWidth = 1.75 + set1.circleRadius = 5.0 + set1.circleHoleRadius = 2.5 + set1.setColor(.white) + set1.setCircleColor(.white) + set1.highlightColor = .white + set1.isDrawValuesEnabled = false + + return LineChartData(dataSet: set1) + } +} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/ColoredLineChartViewController.xib b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/ColoredLineChartViewController.xib new file mode 100644 index 0000000000..bb0f701ec3 --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/ColoredLineChartViewController.xib @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/CombinedChartViewController.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/CombinedChartViewController.swift new file mode 100644 index 0000000000..b5c14ac68e --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/CombinedChartViewController.swift @@ -0,0 +1,233 @@ +// +// CombinedChartViewController.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-09. +// Copyright © 2017 jc. All rights reserved. +// + +import UIKit +import Charts + +private let ITEM_COUNT = 12 + +class CombinedChartViewController: DemoBaseViewController { + @IBOutlet var chartView: CombinedChartView! + + let months = ["Jan", "Feb", "Mar", + "Apr", "May", "Jun", + "Jul", "Aug", "Sep", + "Oct", "Nov", "Dec"] + + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + self.title = "Combined Chart" + self.options = [.toggleLineValues, + .toggleBarValues, + .saveToGallery, + .toggleData, + .toggleBarBorders, + .removeDataSet] + + chartView.delegate = self + + chartView.chartDescription?.isEnabled = false + + chartView.isDrawBarShadowEnabled = false + chartView.isHighlightFullBarEnabled = false + + + chartView.drawOrder = [.bar, + .bubble, + .candle, + .line, + .scatter] + + var l = chartView.legend + l.wordWrapEnabled = true + l.horizontalAlignment = .center + l.verticalAlignment = .bottom + l.orientation = .horizontal + l.drawInside = false + chartView.legend = l + + let rightAxis = chartView.rightAxis + rightAxis.axisMinimum = 0 + + let leftAxis = chartView.leftAxis + leftAxis.axisMinimum = 0 + + let xAxis = chartView.xAxis + xAxis.labelPosition = .bothSided + xAxis.axisMinimum = 0 + xAxis.granularity = 1 + xAxis.valueFormatter = self + + self.updateChartData() + } + + override func updateChartData() { + if self.shouldHideData { + chartView.data = nil + return + } + + self.setChartData() + } + + func setChartData() { + let data = CombinedChartData() + data.lineData = generateLineData() + data.barData = generateBarData() + data.bubbleData = generateBubbleData() + data.scatterData = generateScatterData() + data.candleData = generateCandleData() + + chartView.xAxis.axisMaximum = data.xMax + 0.25 + + chartView.data = data + } + + override func optionTapped(_ option: Option) { + switch option { + case .toggleLineValues: + for set in chartView.data!.dataSets { + if let set = set as? LineChartDataSet { + set.isDrawValuesEnabled = !set .isDrawValuesEnabled + + } + } + chartView.setNeedsDisplay() + + case .toggleBarValues: + for set in chartView.data!.dataSets { + if let set = set as? BarChartDataSet { + set.isDrawValuesEnabled = !set .isDrawValuesEnabled + } + } + chartView.setNeedsDisplay() + + case .removeDataSet: + let rnd = Int(arc4random_uniform(UInt32(chartView.data!.dataSetCount))) + chartView.data?.removeDataSet(chartView.data!.getDataSetByIndex(rnd)) + chartView.data?.notifyDataChanged() + chartView.notifyDataSetChanged() + + default: + super.handleOption(option, forChartView: chartView) + } + } + + func generateLineData() -> LineChartData { + let entries = (0.. ChartDataEntry in + return ChartDataEntry(x: Double(i) + 0.5, y: Double(arc4random_uniform(15) + 5)) + } + + let set = LineChartDataSet(values: entries, label: "Line DataSet") + set.setColor(UIColor(red: 240/255, green: 238/255, blue: 70/255, alpha: 1)) + set.lineWidth = 2.5 + set.setCircleColor(UIColor(red: 240/255, green: 238/255, blue: 70/255, alpha: 1)) + set.circleRadius = 5 + set.circleHoleRadius = 2.5 + set.fillColor = UIColor(red: 240/255, green: 238/255, blue: 70/255, alpha: 1) + set.mode = .cubicBezier + set.isDrawValuesEnabled = true + set.valueFont = .systemFont(ofSize: 10) + set.valueTextColor = UIColor(red: 240/255, green: 238/255, blue: 70/255, alpha: 1) + + set.axisDependency = .left + + return LineChartData(dataSet: set) + } + + func generateBarData() -> BarChartData { + let entries1 = (0.. BarChartDataEntry in + return BarChartDataEntry(x: 0, y: Double(arc4random_uniform(25) + 25)) + } + let entries2 = (0.. BarChartDataEntry in + return BarChartDataEntry(x: 0, yValues: [Double(arc4random_uniform(13) + 12), Double(arc4random_uniform(13) + 12)]) + } + + let set1 = BarChartDataSet(values: entries1, label: "Bar 1") + set1.setColor(UIColor(red: 60/255, green: 220/255, blue: 78/255, alpha: 1)) + set1.valueTextColor = UIColor(red: 60/255, green: 220/255, blue: 78/255, alpha: 1) + set1.valueFont = .systemFont(ofSize: 10) + set1.axisDependency = .left + + let set2 = BarChartDataSet(values: entries2, label: "") + set2.stackLabels = ["Stack 1", "Stack 2"] + set2.colors = [UIColor(red: 61/255, green: 165/255, blue: 255/255, alpha: 1), + UIColor(red: 23/255, green: 197/255, blue: 255/255, alpha: 1) + ] + set2.valueTextColor = UIColor(red: 61/255, green: 165/255, blue: 255/255, alpha: 1) + set2.valueFont = .systemFont(ofSize: 10) + set2.axisDependency = .left + + let groupSpace = 0.06 + let barSpace = 0.02 // x2 dataset + let barWidth = 0.45 // x2 dataset + // (0.45 + 0.02) * 2 + 0.06 = 1.00 -> interval per "group" + + let data = BarChartData(dataSets: [set1, set2]) + data.barWidth = barWidth + + // make this BarData object grouped + data.groupBars(fromX: 0, groupSpace: groupSpace, barSpace: barSpace) + + return data + } + + func generateScatterData() -> ScatterChartData { + let entries = stride(from: 0.0, to: Double(ITEM_COUNT), by: 0.5).map { (i) -> ChartDataEntry in + return ChartDataEntry(x: i+0.25, y: Double(arc4random_uniform(10) + 55)) + } + + let set = ScatterChartDataSet(values: entries, label: "Scatter DataSet") + set.colors = ChartColorTemplates.material + set.scatterShapeSize = 4.5 + set.isDrawValuesEnabled = false + set.valueFont = .systemFont(ofSize: 10) + + return ScatterChartData(dataSet: set) + } + + func generateCandleData() -> CandleChartData { + let entries = stride(from: 0, to: ITEM_COUNT, by: 2).map { (i) -> CandleChartDataEntry in + return CandleChartDataEntry(x: Double(i+1), shadowH: 90, shadowL: 70, open: 85, close: 75) + } + + let set = CandleChartDataSet(values: entries, label: "Candle DataSet") + set.setColor(UIColor(red: 80/255, green: 80/255, blue: 80/255, alpha: 1)) + set.decreasingColor = UIColor(red: 142/255, green: 150/255, blue: 175/255, alpha: 1) + set.shadowColor = .darkGray + set.valueFont = .systemFont(ofSize: 10) + set.isDrawValuesEnabled = false + + return CandleChartData(dataSet: set) + } + + func generateBubbleData() -> BubbleChartData { + let entries = (0.. BubbleChartDataEntry in + return BubbleChartDataEntry(x: Double(i) + 0.5, + y: Double(arc4random_uniform(10) + 105), + size: CGFloat(arc4random_uniform(50) + 105)) + } + + let set = BubbleChartDataSet(values: entries, label: "Bubble DataSet") + set.setColors(ChartColorTemplates.vordiplom) + set.valueTextColor = .white + set.valueFont = .systemFont(ofSize: 10) + set.isDrawValuesEnabled = true + + return BubbleChartData(dataSet: set) + } +} + +extension CombinedChartViewController: AxisValueFormatter { + func stringForValue(_ value: Double, axis: AxisBase) -> String { + return months[Int(value) % months.count] + } +} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/CombinedChartViewController.xib b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/CombinedChartViewController.xib new file mode 100644 index 0000000000..6d4e1009b0 --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/CombinedChartViewController.xib @@ -0,0 +1,56 @@ + + + + + + + + + + + + HelveticaNeue-Light + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/CubicLineChartViewController.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/CubicLineChartViewController.swift new file mode 100644 index 0000000000..1018141ba6 --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/CubicLineChartViewController.swift @@ -0,0 +1,155 @@ +// +// CubicLineChartViewController.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-09. +// Copyright © 2017 jc. All rights reserved. +// + +import UIKit +import Charts + +private class CubicLineSampleFillFormatter: FillFormatter { + func getFillLinePosition(dataSet: LineChartDataSet, dataProvider: LineChartDataProvider) -> CGFloat { + return -10 + } +} + +class CubicLineChartViewController: DemoBaseViewController { + + @IBOutlet var chartView: LineChartView! + @IBOutlet var sliderX: UISlider! + @IBOutlet var sliderY: UISlider! + @IBOutlet var sliderTextX: UITextField! + @IBOutlet var sliderTextY: UITextField! + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + self.title = "Cubic Line Chart" + + self.options = [.toggleValues, + .toggleFilled, + .toggleCircles, + .toggleCubic, + .toggleHorizontalCubic, + .toggleStepped, + .toggleHighlight, + .animateX, + .animateY, + .animateXY, + .saveToGallery, + .togglePinchZoom, + .toggleAutoScaleMinMax, + .toggleData] + + chartView.delegate = self + + chartView.setViewPortOffsets(left: 0, top: 20, right: 0, bottom: 0) + chartView.backgroundColor = UIColor(red: 104/255, green: 241/255, blue: 175/255, alpha: 1) + + chartView.isDragEnabled = true + chartView.setScaleEnabled(true) + chartView.isPinchZoomEnabled = false + chartView.maxHighlightDistance = 300 + + chartView.xAxis.isEnabled = false + + let yAxis = chartView.leftAxis + yAxis.labelFont = UIFont(name: "HelveticaNeue-Light", size:12)! + yAxis.setLabelCount(6, force: false) + yAxis.labelTextColor = .white + yAxis.labelPosition = .insideChart + yAxis.axisLineColor = .white + + chartView.rightAxis.isEnabled = false + chartView.legend.isEnabled = false + + sliderX.value = 45 + sliderY.value = 100 + self.slidersValueChanged(nil) + + chartView.animate(xAxisDuration: 2, yAxisDuration: 2) + } + + override func updateChartData() { + if self.shouldHideData { + chartView.data = nil + return + } + + self.setDataCount(Int(sliderX.value + 1), range: UInt32(sliderY.value)) + } + + func setDataCount(_ count: Int, range: UInt32) { + let yVals1 = (0.. ChartDataEntry in + let mult = range + 1 + let val = Double(arc4random_uniform(mult) + 20) + return ChartDataEntry(x: Double(i), y: val) + } + + let set1 = LineChartDataSet(values: yVals1, label: "DataSet 1") + set1.mode = .cubicBezier + set1.isDrawCirclesEnabled = false + set1.lineWidth = 1.8 + set1.circleRadius = 4 + set1.setCircleColor(.white) + set1.highlightColor = UIColor(red: 244/255, green: 117/255, blue: 117/255, alpha: 1) + set1.fillColor = .white + set1.fillAlpha = 1 + set1.isHorizontalHighlightIndicatorEnabled = false + set1.fillFormatter = CubicLineSampleFillFormatter() + + let data = LineChartData(dataSet: set1) + data.setValueFont(UIFont(name: "HelveticaNeue-Light", size: 9)!) + data.setDrawValues(false) + + chartView.data = data + } + + override func optionTapped(_ option: Option) { + switch option { + case .toggleFilled: + for set in chartView.data!.dataSets as! [LineChartDataSet] { + set.isDrawFilledEnabled = !set.isDrawFilledEnabled + } + chartView.setNeedsDisplay() + + case .toggleCircles: + for set in chartView.data!.dataSets as! [LineChartDataSet] { + set.isDrawCirclesEnabled = !set.isDrawCirclesEnabled + } + chartView.setNeedsDisplay() + + case .toggleCubic: + for set in chartView.data!.dataSets as! [LineChartDataSet] { + set.mode = (set.mode == .cubicBezier) ? .linear : .cubicBezier + } + chartView.setNeedsDisplay() + + case .toggleStepped: + for set in chartView.data!.dataSets as! [LineChartDataSet] { + set.mode = (set.mode == .stepped) ? .linear : .stepped + } + chartView.setNeedsDisplay() + + case .toggleHorizontalCubic: + for set in chartView.data!.dataSets as! [LineChartDataSet] { + set.mode = (set.mode == .cubicBezier) ? .horizontalBezier : .cubicBezier + } + chartView.setNeedsDisplay() + + default: + super.handleOption(option, forChartView: chartView) + } + } + + // MARK: - Actions + @IBAction func slidersValueChanged(_ sender: Any?) { + sliderTextX.text = "\(Int(sliderX.value))" + sliderTextY.text = "\(Int(sliderY.value))" + + self.updateChartData() + } +} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/CubicLineChartViewController.xib b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/CubicLineChartViewController.xib new file mode 100644 index 0000000000..debfd87e93 --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/CubicLineChartViewController.xib @@ -0,0 +1,100 @@ + + + + + + + + + + + + HelveticaNeue-Light + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/HalfPieChartViewController.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/HalfPieChartViewController.swift new file mode 100644 index 0000000000..e203833273 --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/HalfPieChartViewController.swift @@ -0,0 +1,142 @@ +// +// HalfPieChartViewController.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-09. +// Copyright © 2017 jc. All rights reserved. +// + +import UIKit +import Charts + +class HalfPieChartViewController: DemoBaseViewController { + + @IBOutlet var chartView: PieChartView! + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + self.title = "Half Pie Bar Chart" + + self.options = [.toggleValues, + .toggleXValues, + .togglePercent, + .toggleHole, + .animateX, + .animateY, + .animateXY, + .spin, + .drawCenter, + .saveToGallery, + .toggleData] + + self.setup(pieChartView: chartView) + + chartView.delegate = self + + chartView.holeColor = .white + chartView.transparentCircleColor = Color.white.withAlphaComponent(0.43) + chartView.holeRadiusPercent = 0.58 + chartView.isRotationEnabled = false + chartView.isHighlightPerTapEnabled = true + + chartView.maxAngle = 180 // Half chart + chartView.rotationAngle = 180 // Rotate to make the half on the upper side + chartView.centerTextOffset = CGPoint(x: 0, y: -20) + + var l = chartView.legend + l.horizontalAlignment = .center + l.verticalAlignment = .top + l.orientation = .horizontal + l.drawInside = false + l.xEntrySpace = 7 + l.yEntrySpace = 0 + l.yOffset = 0 + chartView.legend = l + + // entry label styling + chartView.entryLabelColor = .white + chartView.entryLabelFont = UIFont(name:"HelveticaNeue-Light", size:12)! + + self.updateChartData() + + chartView.animate(xAxisDuration: 1.4, easingOption: .easeOutBack) + } + + override func updateChartData() { + if self.shouldHideData { + chartView.data = nil + return + } + + self.setDataCount(4, range: 100) + } + + func setDataCount(_ count: Int, range: UInt32) { + let entries = (0.. PieChartDataEntry in + // IMPORTANT: In a PieChart, no values (Entry) should have the same xIndex (even if from different DataSets), since no values can be drawn above each other. + return PieChartDataEntry(value: Double(arc4random_uniform(range) + range / 5), + label: parties[i % parties.count]) + } + + let set = PieChartDataSet(values: entries, label: "Election Results") + set.sliceSpace = 3 + set.selectionShift = 5 + set.colors = ChartColorTemplates.material + + let data = PieChartData(dataSet: set) + + let pFormatter = NumberFormatter() + pFormatter.numberStyle = .percent + pFormatter.maximumFractionDigits = 1 + pFormatter.multiplier = 1 + pFormatter.percentSymbol = " %" + data.setValueFormatter(DefaultValueFormatter(formatter: pFormatter)) + + data.setValueFont(UIFont(name: "HelveticaNeue-Light", size: 11)!) + data.setValueTextColor(.white) + + chartView.data = data + + chartView.setNeedsDisplay() + } + + override func optionTapped(_ option: Option) { + switch option { + case .toggleXValues: + chartView.isDrawEntryLabelsEnabled = !chartView.isDrawEntryLabelsEnabled + chartView.setNeedsDisplay() + + case .togglePercent: + chartView.usePercentValues = !chartView.usePercentValues + chartView.setNeedsDisplay() + + case .toggleHole: + chartView.isDrawHoleEnabled = !chartView.isDrawHoleEnabled + chartView.setNeedsDisplay() + + case .drawCenter: + chartView.isDrawCenterTextEnabled = !chartView.isDrawCenterTextEnabled + chartView.setNeedsDisplay() + + case .animateX: + chartView.animate(xAxisDuration: 1.4) + + case .animateY: + chartView.animate(yAxisDuration: 1.4) + + case .animateXY: + chartView.animate(xAxisDuration: 1.4, yAxisDuration: 1.4) + + case .spin: + chartView.spin(duration: 2, + fromAngle: chartView.rotationAngle, + toAngle: chartView.rotationAngle + 360, + easingOption: .easeInCubic) + + default: + handleOption(option, forChartView: chartView) + } + } +} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/HalfPieChartViewController.xib b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/HalfPieChartViewController.xib new file mode 100644 index 0000000000..d757d173bf --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/HalfPieChartViewController.xib @@ -0,0 +1,56 @@ + + + + + + + + + + + + HelveticaNeue-Light + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/HorizontalBarChartViewController.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/HorizontalBarChartViewController.swift new file mode 100644 index 0000000000..896b655a57 --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/HorizontalBarChartViewController.swift @@ -0,0 +1,124 @@ +// +// HorizontalBarChartViewController.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-09. +// Copyright © 2017 jc. All rights reserved. +// + +import UIKit +import Charts + +class HorizontalBarChartViewController: DemoBaseViewController { + + @IBOutlet var chartView: HorizontalBarChartView! + @IBOutlet var sliderX: UISlider! + @IBOutlet var sliderY: UISlider! + @IBOutlet var sliderTextX: UITextField! + @IBOutlet var sliderTextY: UITextField! + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + self.title = "Horizontal Bar Char" + self.options = [.toggleValues, + .toggleIcons, + .toggleHighlight, + .animateX, + .animateY, + .animateXY, + .saveToGallery, + .togglePinchZoom, + .toggleAutoScaleMinMax, + .toggleData, + .toggleBarBorders] + + self.setup(barLineChartView: chartView) + + chartView.delegate = self + + chartView.isDrawBarShadowEnabled = false + chartView.isDrawValueAboveBarEnabled = true + + chartView.maxVisibleCount = 60 + + let xAxis = chartView.xAxis + xAxis.labelPosition = .bottom + xAxis.labelFont = .systemFont(ofSize: 10) + xAxis.isDrawAxisLineEnabled = true + xAxis.granularity = 10 + + let leftAxis = chartView.leftAxis + leftAxis.labelFont = .systemFont(ofSize: 10) + leftAxis.isDrawAxisLineEnabled = true + leftAxis.isDrawGridLinesEnabled = true + leftAxis.axisMinimum = 0 + + let rightAxis = chartView.rightAxis + rightAxis.isEnabled = true + rightAxis.labelFont = .systemFont(ofSize: 10) + rightAxis.isDrawAxisLineEnabled = true + rightAxis.axisMinimum = 0 + + var l = chartView.legend + l.horizontalAlignment = .left + l.verticalAlignment = .bottom + l.orientation = .horizontal + l.drawInside = false + l.form = .square + l.formSize = 8 + l.font = UIFont(name: "HelveticaNeue-Light", size: 11)! + l.xEntrySpace = 4 + chartView.legend = l + + chartView.fitBars = true + + sliderX.value = 12 + sliderY.value = 50 + slidersValueChanged(nil) + + chartView.animate(yAxisDuration: 2.5) + } + + override func updateChartData() { + if self.shouldHideData { + chartView.data = nil + return + } + + self.setDataCount(Int(sliderX.value) + 1, range: UInt32(sliderY.value)) + } + + func setDataCount(_ count: Int, range: UInt32) { + let barWidth = 9.0 + let spaceForBar = 10.0 + + let yVals = (0.. BarChartDataEntry in + let mult = range + 1 + let val = Double(arc4random_uniform(mult)) + return BarChartDataEntry(x: Double(i)*spaceForBar, y: val, icon: #imageLiteral(resourceName: "icon")) + } + + let set1 = BarChartDataSet(values: yVals, label: "DataSet") + set1.isDrawIconsEnabled = false + + let data = BarChartData(dataSet: set1) + data.setValueFont(UIFont(name:"HelveticaNeue-Light", size:10)!) + data.barWidth = barWidth + + chartView.data = data + } + + override func optionTapped(_ option: Option) { + super.handleOption(option, forChartView: chartView) + } + + // MARK: - Actions + @IBAction func slidersValueChanged(_ sender: Any?) { + sliderTextX.text = "\(Int(sliderX.value))" + sliderTextY.text = "\(Int(sliderY.value))" + + self.updateChartData() + } +} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/HorizontalBarChartViewController.xib b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/HorizontalBarChartViewController.xib new file mode 100644 index 0000000000..19560cd484 --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/HorizontalBarChartViewController.xib @@ -0,0 +1,100 @@ + + + + + + + + + + + + HelveticaNeue-Light + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChart1ViewController.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChart1ViewController.swift new file mode 100644 index 0000000000..8681cd099d --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChart1ViewController.swift @@ -0,0 +1,187 @@ +// +// LineChart1ViewController.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-09. +// Copyright © 2017 jc. All rights reserved. +// + +import UIKit +import Charts + +class LineChart1ViewController: DemoBaseViewController { + + @IBOutlet var chartView: LineChartView! + @IBOutlet var sliderX: UISlider! + @IBOutlet var sliderY: UISlider! + @IBOutlet var sliderTextX: UITextField! + @IBOutlet var sliderTextY: UITextField! + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + self.title = "Line Chart 1" + self.options = [.toggleValues, + .toggleFilled, + .toggleCircles, + .toggleCubic, + .toggleHorizontalCubic, + .toggleIcons, + .toggleStepped, + .toggleHighlight, + .animateX, + .animateY, + .animateXY, + .saveToGallery, + .togglePinchZoom, + .toggleAutoScaleMinMax, + .toggleData] + + chartView.delegate = self + + chartView.chartDescription?.isEnabled = false + chartView.isDragEnabled = true + chartView.setScaleEnabled(true) + chartView.isPinchZoomEnabled = true + + // x-axis limit line + let llXAxis = ChartLimitLine(limit: 10, label: "Index 10") + llXAxis.lineWidth = 4 + llXAxis.lineDashLengths = [10, 10, 0] + llXAxis.labelPosition = .rightBottom + llXAxis.valueFont = .systemFont(ofSize: 10) + + chartView.xAxis.gridLineDashLengths = [10, 10] + chartView.xAxis.gridLineDashPhase = 0 + + let ll1 = ChartLimitLine(limit: 150, label: "Upper Limit") + ll1.lineWidth = 4 + ll1.lineDashLengths = [5, 5] + ll1.labelPosition = .rightTop + ll1.valueFont = .systemFont(ofSize: 10) + + let ll2 = ChartLimitLine(limit: -30, label: "Lower Limit") + ll2.lineWidth = 4 + ll2.lineDashLengths = [5,5] + ll2.labelPosition = .rightBottom + ll2.valueFont = .systemFont(ofSize: 10) + + let leftAxis = chartView.leftAxis + leftAxis.removeAllLimitLines() + leftAxis.addLimitLine(ll1) + leftAxis.addLimitLine(ll2) + leftAxis.axisMaximum = 200 + leftAxis.axisMinimum = -50 + leftAxis.gridLineDashLengths = [5, 5] + leftAxis.isDrawLimitLinesBehindDataEnabled = true + + chartView.rightAxis.isEnabled = false + + //[_chartView.viewPortHandler setMaximumScaleY: 2.f]; + //[_chartView.viewPortHandler setMaximumScaleX: 2.f]; + + let marker = BalloonMarker(color: UIColor(white: 180/255, alpha: 1), + font: .systemFont(ofSize: 12), + textColor: .white, + insets: UIEdgeInsets(top: 8, left: 8, bottom: 20, right: 8)) + marker.chartView = chartView + marker.minimumSize = CGSize(width: 80, height: 40) + chartView.marker = marker + + chartView.legend.form = .line + + sliderX.value = 45 + sliderY.value = 100 + slidersValueChanged(nil) + + chartView.animate(xAxisDuration: 2.5) + } + + override func updateChartData() { + if self.shouldHideData { + chartView.data = nil + return + } + + self.setDataCount(Int(sliderX.value), range: UInt32(sliderY.value)) + } + + func setDataCount(_ count: Int, range: UInt32) { + let values = (0.. ChartDataEntry in + let val = Double(arc4random_uniform(range) + 3) + return ChartDataEntry(x: Double(i), y: val, icon: #imageLiteral(resourceName: "icon")) + } + + let set1 = LineChartDataSet(values: values, label: "DataSet 1") + set1.isDrawIconsEnabled = false + + set1.lineDashLengths = [5, 2.5] + set1.highlightLineDashLengths = [5, 2.5] + set1.setColor(.black) + set1.setCircleColor(.black) + set1.lineWidth = 1 + set1.circleRadius = 3 + set1.isDrawCircleHoleEnabled = false + set1.valueFont = .systemFont(ofSize: 9) + set1.formLineDashLengths = [5, 2.5] + set1.formLineWidth = 1 + set1.formLineWidth = 15 + + let gradientColors = [Color(string: "#00ff0000").cgColor, + Color(string: "#ffff0000").cgColor] as CFArray + let gradient = CGGradient(colorsSpace: nil, colors: gradientColors, locations: nil)! + + set1.fillAlpha = 1 + set1.fill = .linearGradient(gradient, angle: 90) + set1.isDrawFilledEnabled = true + + let data = LineChartData(dataSet: set1) + + chartView.data = data + } + + override func optionTapped(_ option: Option) { + switch option { + case .toggleFilled: + for set in chartView.data!.dataSets as! [LineChartDataSet] { + set.isDrawFilledEnabled = !set.isDrawFilledEnabled + } + chartView.setNeedsDisplay() + + case .toggleCircles: + for set in chartView.data!.dataSets as! [LineChartDataSet] { + set.isDrawCirclesEnabled = !set.isDrawCirclesEnabled + } + chartView.setNeedsDisplay() + + case .toggleCubic: + for set in chartView.data!.dataSets as! [LineChartDataSet] { + set.mode = (set.mode == .cubicBezier) ? .linear : .cubicBezier + } + chartView.setNeedsDisplay() + + case .toggleStepped: + for set in chartView.data!.dataSets as! [LineChartDataSet] { + set.mode = (set.mode == .stepped) ? .linear : .stepped + } + chartView.setNeedsDisplay() + + case .toggleHorizontalCubic: + for set in chartView.data!.dataSets as! [LineChartDataSet] { + set.mode = (set.mode == .cubicBezier) ? .horizontalBezier : .cubicBezier + } + chartView.setNeedsDisplay() + + default: + super.handleOption(option, forChartView: chartView) + } + } + + @IBAction func slidersValueChanged(_ sender: Any?) { + sliderTextX.text = "\(Int(sliderX.value))" + sliderTextY.text = "\(Int(sliderY.value))" + + self.updateChartData() + } +} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChart1ViewController.xib b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChart1ViewController.xib new file mode 100644 index 0000000000..274c26069c --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChart1ViewController.xib @@ -0,0 +1,100 @@ + + + + + + + + + + + + HelveticaNeue-Light + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChart2ViewController.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChart2ViewController.swift new file mode 100644 index 0000000000..8f9206e173 --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChart2ViewController.swift @@ -0,0 +1,200 @@ +// +// LineChart2ViewController.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-09. +// Copyright © 2017 jc. All rights reserved. +// + +import UIKit +import Charts + +class LineChart2ViewController: DemoBaseViewController { + + @IBOutlet var chartView: LineChartView! + @IBOutlet var sliderX: UISlider! + @IBOutlet var sliderY: UISlider! + @IBOutlet var sliderTextX: UITextField! + @IBOutlet var sliderTextY: UITextField! + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + self.title = "Line Chart 2" + self.options = [.toggleValues, + .toggleFilled, + .toggleCircles, + .toggleCubic, + .toggleHorizontalCubic, + .toggleStepped, + .toggleHighlight, + .animateX, + .animateY, + .animateXY, + .saveToGallery, + .togglePinchZoom, + .toggleAutoScaleMinMax, + .toggleData] + + chartView.delegate = self + + chartView.chartDescription?.isEnabled = false + chartView.isDragEnabled = true + chartView.setScaleEnabled(true) + chartView.isPinchZoomEnabled = true + + var l = chartView.legend + l.form = .line + l.font = UIFont(name: "HelveticaNeue-Light", size: 11)! + l.textColor = .white + l.horizontalAlignment = .left + l.verticalAlignment = .bottom + l.orientation = .horizontal + l.drawInside = false + + let xAxis = chartView.xAxis + xAxis.labelFont = .systemFont(ofSize: 11) + xAxis.labelTextColor = .white + xAxis.isDrawAxisLineEnabled = false + + let leftAxis = chartView.leftAxis + leftAxis.labelTextColor = UIColor(red: 51/255, green: 181/255, blue: 229/255, alpha: 1) + leftAxis.axisMaximum = 200 + leftAxis.axisMinimum = 0 + leftAxis.isDrawGridLinesEnabled = true + leftAxis.isGranularityEnabled = true + + let rightAxis = chartView.rightAxis + rightAxis.labelTextColor = .red + rightAxis.axisMaximum = 900 + rightAxis.axisMinimum = -200 + rightAxis.isGranularityEnabled = false + + sliderX.value = 20 + sliderY.value = 30 + slidersValueChanged(nil) + + chartView.animate(xAxisDuration: 2.5) + } + + override func updateChartData() { + if self.shouldHideData { + chartView.data = nil + return + } + + self.setDataCount(Int(sliderX.value + 1), range: UInt32(sliderY.value)) + } + + func setDataCount(_ count: Int, range: UInt32) { + let yVals1 = (0.. ChartDataEntry in + let mult = range / 2 + let val = Double(arc4random_uniform(mult) + 50) + return ChartDataEntry(x: Double(i), y: val) + } + let yVals2 = (0.. ChartDataEntry in + let val = Double(arc4random_uniform(range) + 450) + return ChartDataEntry(x: Double(i), y: val) + } + let yVals3 = (0.. ChartDataEntry in + let val = Double(arc4random_uniform(range) + 500) + return ChartDataEntry(x: Double(i), y: val) + } + + let set1 = LineChartDataSet(values: yVals1, label: "DataSet 1") + set1.axisDependency = .left + set1.setColor(UIColor(red: 51/255, green: 181/255, blue: 229/255, alpha: 1)) + set1.setCircleColor(.white) + set1.lineWidth = 2 + set1.circleRadius = 3 + set1.fillAlpha = 65/255 + set1.fillColor = UIColor(red: 51/255, green: 181/255, blue: 229/255, alpha: 1) + set1.highlightColor = UIColor(red: 244/255, green: 117/255, blue: 117/255, alpha: 1) + set1.isDrawCircleHoleEnabled = false + + let set2 = LineChartDataSet(values: yVals2, label: "DataSet 2") + set2.axisDependency = .right + set2.setColor(.red) + set2.setCircleColor(.white) + set2.lineWidth = 2 + set2.circleRadius = 3 + set2.fillAlpha = 65/255 + set2.fillColor = .red + set2.highlightColor = UIColor(red: 244/255, green: 117/255, blue: 117/255, alpha: 1) + set2.isDrawCircleHoleEnabled = false + + let set3 = LineChartDataSet(values: yVals3, label: "DataSet 3") + set3.axisDependency = .right + set3.setColor(.yellow) + set3.setCircleColor(.white) + set3.lineWidth = 2 + set3.circleRadius = 3 + set3.fillAlpha = 65/255 + set3.fillColor = UIColor.yellow.withAlphaComponent(200/255) + set3.highlightColor = UIColor(red: 244/255, green: 117/255, blue: 117/255, alpha: 1) + set3.isDrawCircleHoleEnabled = false + + let data = LineChartData(dataSets: [set1, set2, set3]) + data.setValueTextColor(.white) + data.setValueFont(.systemFont(ofSize: 9)) + + chartView.data = data + } + + override func optionTapped(_ option: Option) { + switch option { + case .toggleFilled: + for set in chartView.data!.dataSets as! [LineChartDataSet] { + set.isDrawFilledEnabled = !set.isDrawFilledEnabled + } + chartView.setNeedsDisplay() + + case .toggleCircles: + for set in chartView.data!.dataSets as! [LineChartDataSet] { + set.isDrawCirclesEnabled = !set.isDrawCirclesEnabled + } + chartView.setNeedsDisplay() + + case .toggleCubic: + for set in chartView.data!.dataSets as! [LineChartDataSet] { + set.mode = (set.mode == .cubicBezier) ? .linear : .cubicBezier + } + chartView.setNeedsDisplay() + + case .toggleStepped: + for set in chartView.data!.dataSets as! [LineChartDataSet] { + set.mode = (set.mode == .stepped) ? .linear : .stepped + } + chartView.setNeedsDisplay() + + case .toggleHorizontalCubic: + for set in chartView.data!.dataSets as! [LineChartDataSet] { + set.mode = (set.mode == .cubicBezier) ? .horizontalBezier : .cubicBezier + } + chartView.setNeedsDisplay() + + default: + super.handleOption(option, forChartView: chartView) + } + } + + @IBAction func slidersValueChanged(_ sender: Any?) { + sliderTextX.text = "\(Int(sliderX.value))" + sliderTextY.text = "\(Int(sliderY.value))" + + self.updateChartData() + } +//} + // TODO: Declarations in extensions cannot override yet. +//extension LineChart2ViewController { + override func chartValueSelected(_ chartView: ChartViewBase, entry: ChartDataEntry, highlight: Highlight) { + super.chartValueSelected(chartView, entry: entry, highlight: highlight) + + self.chartView.centerViewToAnimated(xValue: entry.x, yValue: entry.y, + axis: self.chartView.data!.getDataSetByIndex(highlight.dataSetIndex).axisDependency, + duration: 1) + //[_chartView moveViewToAnimatedWithXValue:entry.x yValue:entry.y axis:[_chartView.data getDataSetByIndex:dataSetIndex].axisDependency duration:1.0]; + //[_chartView zoomAndCenterViewAnimatedWithScaleX:1.8 scaleY:1.8 xValue:entry.x yValue:entry.y axis:[_chartView.data getDataSetByIndex:dataSetIndex].axisDependency duration:1.0]; + } +} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChart2ViewController.xib b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChart2ViewController.xib new file mode 100644 index 0000000000..08ccd86308 --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChart2ViewController.xib @@ -0,0 +1,100 @@ + + + + + + + + + + + + HelveticaNeue-Light + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChartFilledViewController.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChartFilledViewController.swift new file mode 100644 index 0000000000..01f87f69cb --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChartFilledViewController.swift @@ -0,0 +1,117 @@ +// +// LineChartFilledViewController.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-09. +// Copyright © 2017 jc. All rights reserved. +// + +import UIKit +import Charts + +class LineChartFilledViewController: DemoBaseViewController { + + @IBOutlet var chartView: LineChartView! + @IBOutlet var sliderX: UISlider! + @IBOutlet var sliderY: UISlider! + @IBOutlet var sliderTextX: UITextField! + @IBOutlet var sliderTextY: UITextField! + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + self.title = "Filled Line Chart" + + chartView.delegate = self + + chartView.backgroundColor = .white + chartView.gridBackgroundColor = UIColor(red: 51/255, green: 181/255, blue: 229/255, alpha: 150/255) + chartView.isDrawGridBackgroundEnabled = true + + chartView.isDrawBordersEnabled = true + + chartView.chartDescription?.isEnabled = false + + chartView.isPinchZoomEnabled = false + chartView.isDragEnabled = true + chartView.setScaleEnabled(true) + + chartView.legend.isEnabled = false + + chartView.xAxis.isEnabled = false + + let leftAxis = chartView.leftAxis + leftAxis.axisMaximum = 900 + leftAxis.axisMinimum = -250 + leftAxis.isDrawAxisLineEnabled = false + + chartView.rightAxis.isEnabled = false + + sliderX.value = 100 + sliderY.value = 60 + slidersValueChanged(nil) + } + + override func updateChartData() { + if self.shouldHideData { + chartView.data = nil + return + } + + self.setDataCount(Int(sliderX.value), range: UInt32(sliderY.value)) + } + + func setDataCount(_ count: Int, range: UInt32) { + let yVals1 = (0.. ChartDataEntry in + let val = Double(arc4random_uniform(range) + 50) + return ChartDataEntry(x: Double(i), y: val) + } + let yVals2 = (0.. ChartDataEntry in + let val = Double(arc4random_uniform(range) + 450) + return ChartDataEntry(x: Double(i), y: val) + } + + let set1 = LineChartDataSet(values: yVals1, label: "DataSet 1") + set1.axisDependency = .left + set1.setColor(UIColor(red: 255/255, green: 241/255, blue: 46/255, alpha: 1)) + set1.isDrawCirclesEnabled = false + set1.lineWidth = 2 + set1.circleRadius = 3 + set1.fillAlpha = 1 + set1.isDrawFilledEnabled = true + set1.fillColor = .white + set1.highlightColor = UIColor(red: 244/255, green: 117/255, blue: 117/255, alpha: 1) + set1.isDrawCircleHoleEnabled = false + set1.fillFormatter = DefaultFillFormatter { _,_ -> CGFloat in + return CGFloat(self.chartView.leftAxis.axisMinimum) + } + + let set2 = LineChartDataSet(values: yVals2, label: "DataSet 2") + set2.axisDependency = .left + set2.setColor(UIColor(red: 255/255, green: 241/255, blue: 46/255, alpha: 1)) + set2.isDrawCirclesEnabled = false + set2.lineWidth = 2 + set2.circleRadius = 3 + set2.fillAlpha = 1 + set2.isDrawFilledEnabled = true + set2.fillColor = .white + set2.highlightColor = UIColor(red: 244/255, green: 117/255, blue: 117/255, alpha: 1) + set2.isDrawCircleHoleEnabled = false + set2.fillFormatter = DefaultFillFormatter { _,_ -> CGFloat in + return CGFloat(self.chartView.leftAxis.axisMaximum) + } + + let data = LineChartData(dataSets: [set1, set2]) + data.setDrawValues(false) + + chartView.data = data + } + + @IBAction func slidersValueChanged(_ sender: Any?) { + sliderTextX.text = "\(Int(sliderX.value))" + sliderTextY.text = "\(Int(sliderY.value))" + + self.updateChartData() + } +} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChartFilledViewController.xib b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChartFilledViewController.xib new file mode 100644 index 0000000000..08c6253a69 --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChartFilledViewController.xib @@ -0,0 +1,86 @@ + + + + + + + + + + + + HelveticaNeue-Light + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChartTimeViewController.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChartTimeViewController.swift new file mode 100644 index 0000000000..e41761ec9b --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChartTimeViewController.swift @@ -0,0 +1,161 @@ +// +// LineChartTimeViewController.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-09. +// Copyright © 2017 jc. All rights reserved. +// + +import UIKit +import Charts + +class LineChartTimeViewController: DemoBaseViewController { + @IBOutlet var chartView: LineChartView! + @IBOutlet var sliderX: UISlider! + @IBOutlet var sliderTextX: UITextField! + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + self.title = "Line Chart 2" + self.options = [.toggleValues, + .toggleFilled, + .toggleCircles, + .toggleCubic, + .toggleHorizontalCubic, + .toggleStepped, + .toggleHighlight, + .animateX, + .animateY, + .animateXY, + .saveToGallery, + .togglePinchZoom, + .toggleAutoScaleMinMax, + .toggleData] + + chartView.delegate = self + + chartView.chartDescription?.isEnabled = false + + chartView.isDragEnabled = true + chartView.setScaleEnabled(true) + chartView.isPinchZoomEnabled = false + chartView.isHighlightPerDragEnabled = true + + chartView.backgroundColor = .white + + chartView.legend.isEnabled = false + + let xAxis = chartView.xAxis + xAxis.labelPosition = .topInside + xAxis.labelFont = .systemFont(ofSize: 10, weight: .light) + xAxis.labelTextColor = UIColor(red: 255/255, green: 192/255, blue: 56/255, alpha: 1) + xAxis.isDrawAxisLineEnabled = false + xAxis.isDrawGridLinesEnabled = true + xAxis.isCenterAxisLabelsEnabled = true + xAxis.granularity = 3600 + xAxis.valueFormatter = DateValueFormatter() + + let leftAxis = chartView.leftAxis + leftAxis.labelPosition = .insideChart + leftAxis.labelFont = .systemFont(ofSize: 12, weight: .light) + leftAxis.isDrawGridLinesEnabled = true + leftAxis.isGranularityEnabled = true + leftAxis.axisMinimum = 0 + leftAxis.axisMaximum = 170 + leftAxis.yOffset = -9 + leftAxis.labelTextColor = UIColor(red: 255/255, green: 192/255, blue: 56/255, alpha: 1) + + + chartView.rightAxis.isEnabled = false + + chartView.legend.form = .line + + sliderX.value = 100 + slidersValueChanged(nil) + + chartView.animate(xAxisDuration: 2.5) + } + + override func updateChartData() { + if self.shouldHideData { + chartView.data = nil + return + } + + self.setDataCount(Int(sliderX.value), range: 30) + } + + func setDataCount(_ count: Int, range: UInt32) { + let now = Date().timeIntervalSince1970 + let hourSeconds: TimeInterval = 3600 + + let from = now - (Double(count) / 2) * hourSeconds + let to = now + (Double(count) / 2) * hourSeconds + + let values = stride(from: from, to: to, by: hourSeconds).map { (x) -> ChartDataEntry in + let y = arc4random_uniform(range) + 50 + return ChartDataEntry(x: x, y: Double(y)) + } + + let set1 = LineChartDataSet(values: values, label: "DataSet 1") + set1.axisDependency = .left + set1.setColor(UIColor(red: 51/255, green: 181/255, blue: 229/255, alpha: 1)) + set1.lineWidth = 1.5 + set1.isDrawCirclesEnabled = false + set1.isDrawValuesEnabled = false + set1.fillAlpha = 0.26 + set1.fillColor = UIColor(red: 51/255, green: 181/255, blue: 229/255, alpha: 1) + set1.highlightColor = UIColor(red: 244/255, green: 117/255, blue: 117/255, alpha: 1) + set1.isDrawCircleHoleEnabled = false + + let data = LineChartData(dataSet: set1) + data.setValueTextColor(.white) + data.setValueFont(.systemFont(ofSize: 9, weight: .light)) + + chartView.data = data + } + + override func optionTapped(_ option: Option) { + switch option { + case .toggleFilled: + for set in chartView.data!.dataSets as! [LineChartDataSet] { + set.isDrawFilledEnabled = !set.isDrawFilledEnabled + } + chartView.setNeedsDisplay() + + case .toggleCircles: + for set in chartView.data!.dataSets as! [LineChartDataSet] { + set.isDrawCirclesEnabled = !set.isDrawCirclesEnabled + } + chartView.setNeedsDisplay() + + case .toggleCubic: + for set in chartView.data!.dataSets as! [LineChartDataSet] { + set.mode = (set.mode == .cubicBezier) ? .linear : .cubicBezier + } + chartView.setNeedsDisplay() + + case .toggleStepped: + for set in chartView.data!.dataSets as! [LineChartDataSet] { + set.mode = (set.mode == .stepped) ? .linear : .stepped + } + chartView.setNeedsDisplay() + + case .toggleHorizontalCubic: + for set in chartView.data!.dataSets as! [LineChartDataSet] { + set.mode = (set.mode == .cubicBezier) ? .horizontalBezier : .cubicBezier + } + chartView.setNeedsDisplay() + + default: + super.handleOption(option, forChartView: chartView) + } + } + + @IBAction func slidersValueChanged(_ sender: Any?) { + sliderTextX.text = "\(Int(sliderX.value))" + self.updateChartData() + } +} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChartTimeViewController.xib b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChartTimeViewController.xib new file mode 100644 index 0000000000..f4daf06a19 --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChartTimeViewController.xib @@ -0,0 +1,78 @@ + + + + + + + + + + + + HelveticaNeue-Light + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/MultipleBarChartViewController.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/MultipleBarChartViewController.swift new file mode 100644 index 0000000000..2e9b3ad992 --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/MultipleBarChartViewController.swift @@ -0,0 +1,154 @@ +// +// MultipleBarChartViewController.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-09. +// Copyright © 2017 jc. All rights reserved. +// + +import UIKit +import Charts + +class MultipleBarChartViewController: DemoBaseViewController { + + @IBOutlet var chartView: BarChartView! + @IBOutlet var sliderX: UISlider! + @IBOutlet var sliderY: UISlider! + @IBOutlet var sliderTextX: UITextField! + @IBOutlet var sliderTextY: UITextField! + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + self.title = "Multiple Bar Chart" + + self.options = [.toggleValues, + .toggleHighlight, + .animateX, + .animateY, + .animateXY, + .saveToGallery, + .togglePinchZoom, + .toggleAutoScaleMinMax, + .toggleData, + .toggleBarBorders] + + chartView.delegate = self + + chartView.chartDescription?.isEnabled = false + + chartView.isPinchZoomEnabled = false + chartView.isDrawBarShadowEnabled = false + + let marker = BalloonMarker(color: UIColor(white: 180/255, alpha: 1), font: .systemFont(ofSize: 12), textColor: .white, insets: UIEdgeInsets(top: 8, left: 8, bottom: 20, right: 8)) + marker.chartView = chartView + marker.minimumSize = CGSize(width: 80, height: 40) + chartView.marker = marker + + var l = chartView.legend + l.horizontalAlignment = .right + l.verticalAlignment = .top + l.orientation = .vertical + l.drawInside = true + l.font = .systemFont(ofSize: 8, weight: .light) + l.yOffset = 10 + l.xOffset = 10 + l.yEntrySpace = 0 + chartView.legend = l + + let xAxis = chartView.xAxis + xAxis.labelFont = .systemFont(ofSize: 10, weight: .light) + xAxis.granularity = 1 + xAxis.isCenterAxisLabelsEnabled = true + xAxis.valueFormatter = IntAxisValueFormatter() + + let leftAxisFormatter = NumberFormatter() + leftAxisFormatter.maximumFractionDigits = 1 + + let leftAxis = chartView.leftAxis + leftAxis.labelFont = .systemFont(ofSize: 10, weight: .light) + leftAxis.valueFormatter = LargeValueFormatter() + leftAxis.spaceTop = 0.35 + leftAxis.axisMinimum = 0 + + chartView.rightAxis.isEnabled = false + + sliderX.value = 10 + sliderY.value = 100 + slidersValueChanged(nil) + } + + override func updateChartData() { + if self.shouldHideData { + chartView.data = nil + return + } + + self.setDataCount(Int(sliderX.value), range: UInt32(sliderY.value)) + } + + func setDataCount(_ count: Int, range: UInt32) { + let groupSpace = 0.08 + let barSpace = 0.03 + let barWidth = 0.2 + // (0.2 + 0.03) * 4 + 0.08 = 1.00 -> interval per "group" + + let randomMultiplier = range * 100000 + let groupCount = count + 1 + let startYear = 1980 + let endYear = startYear + groupCount + + let block: (Int) -> BarChartDataEntry = { (i) -> BarChartDataEntry in + return BarChartDataEntry(x: Double(i), y: Double(arc4random_uniform(randomMultiplier))) + } + let yVals1 = (startYear ..< endYear).map(block) + let yVals2 = (startYear ..< endYear).map(block) + let yVals3 = (startYear ..< endYear).map(block) + let yVals4 = (startYear ..< endYear).map(block) + + let set1 = BarChartDataSet(values: yVals1, label: "Company A") + set1.setColor(UIColor(red: 104/255, green: 241/255, blue: 175/255, alpha: 1)) + + let set2 = BarChartDataSet(values: yVals2, label: "Company B") + set2.setColor(UIColor(red: 164/255, green: 228/255, blue: 251/255, alpha: 1)) + + let set3 = BarChartDataSet(values: yVals3, label: "Company C") + set3.setColor(UIColor(red: 242/255, green: 247/255, blue: 158/255, alpha: 1)) + + let set4 = BarChartDataSet(values: yVals4, label: "Company D") + set4.setColor(UIColor(red: 255/255, green: 102/255, blue: 0/255, alpha: 1)) + + let data = BarChartData(dataSets: [set1, set2, set3, set4]) + data.setValueFont(.systemFont(ofSize: 10, weight: .light)) + data.setValueFormatter(LargeValueFormatter()) + + // specify the width each bar should have + data.barWidth = barWidth + + // restrict the x-axis range + chartView.xAxis.axisMinimum = Double(startYear) + + // groupWidthWithGroupSpace(...) is a helper that calculates the width each group needs based on the provided parameters + chartView.xAxis.axisMaximum = Double(startYear) + data.groupWidth(groupSpace: groupSpace, barSpace: barSpace) * Double(groupCount) + + data.groupBars(fromX: Double(startYear), groupSpace: groupSpace, barSpace: barSpace) + + chartView.data = data + } + + override func optionTapped(_ option: Option) { + super.handleOption(option, forChartView: chartView) + } + + // MARK: - Actions + @IBAction func slidersValueChanged(_ sender: Any?) { + let startYear = 1980 + let endYear = startYear + Int(sliderX.value) + + sliderTextX.text = "\(startYear)-\(endYear)" + sliderTextY.text = "\(Int(sliderY.value))" + + self.updateChartData() + } +} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/MultipleBarChartViewController.xib b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/MultipleBarChartViewController.xib new file mode 100644 index 0000000000..5a67858835 --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/MultipleBarChartViewController.xib @@ -0,0 +1,99 @@ + + + + + + + + + + + + HelveticaNeue-Light + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/MultipleLinesChartViewController.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/MultipleLinesChartViewController.swift new file mode 100644 index 0000000000..7ccb56c029 --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/MultipleLinesChartViewController.swift @@ -0,0 +1,138 @@ +// +// MultipleLinesChartViewController.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-09. +// Copyright © 2017 jc. All rights reserved. +// + +import UIKit +import Charts + +class MultipleLinesChartViewController: DemoBaseViewController { + + @IBOutlet var chartView: LineChartView! + @IBOutlet var sliderX: UISlider! + @IBOutlet var sliderY: UISlider! + @IBOutlet var sliderTextX: UITextField! + @IBOutlet var sliderTextY: UITextField! + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + self.title = "Multiple Lines Chart" + self.options = [.toggleValues, + .toggleFilled, + .toggleCircles, + .toggleCubic, + .toggleStepped, + .toggleHighlight, + .animateX, + .animateY, + .animateXY, + .saveToGallery, + .togglePinchZoom, + .toggleAutoScaleMinMax, + .toggleData] + + chartView.delegate = self + + chartView.chartDescription?.isEnabled = false + + chartView.leftAxis.isEnabled = false + chartView.rightAxis.isDrawAxisLineEnabled = false + chartView.xAxis.isDrawAxisLineEnabled = false + + chartView.isDrawBordersEnabled = false + chartView.setScaleEnabled(true) + + var l = chartView.legend + l.horizontalAlignment = .right + l.verticalAlignment = .top + l.orientation = .vertical + l.drawInside = false + chartView.legend = l + + sliderX.value = 20 + sliderY.value = 100 + slidersValueChanged(nil) + } + + override func updateChartData() { + if self.shouldHideData { + chartView.data = nil + return + } + + self.setDataCount(Int(sliderX.value), range: UInt32(sliderY.value)) + } + + // TODO: Refine data creation + func setDataCount(_ count: Int, range: UInt32) { + let colors = ChartColorTemplates.vordiplom[0...2] + + let block: (Int) -> ChartDataEntry = { (i) -> ChartDataEntry in + let val = Double(arc4random_uniform(range) + 3) + return ChartDataEntry(x: Double(i), y: val) + } + let dataSets = (0..<3).map { i -> LineChartDataSet in + let yVals = (0.. + + + + + + + + + + + HelveticaNeue-Light + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/NegativeStackedBarChartViewController.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/NegativeStackedBarChartViewController.swift new file mode 100644 index 0000000000..6edcd712b5 --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/NegativeStackedBarChartViewController.swift @@ -0,0 +1,134 @@ +// +// NegativeStackedBarChartViewController.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-09. +// Copyright © 2017 jc. All rights reserved. +// + +import UIKit +import Charts + +class NegativeStackedBarChartViewController: DemoBaseViewController { + + @IBOutlet var chartView: HorizontalBarChartView! + + lazy var customFormatter: NumberFormatter = { + let formatter = NumberFormatter() + formatter.negativePrefix = "" + formatter.positiveSuffix = "m" + formatter.negativeSuffix = "m" + formatter.minimumSignificantDigits = 1 + formatter.minimumFractionDigits = 1 + return formatter + }() + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + self.title = "Stacked Bar Chart Negative" + self.options = [.toggleValues, + .toggleIcons, + .toggleHighlight, + .animateX, + .animateY, + .animateXY, + .saveToGallery, + .togglePinchZoom, + .toggleAutoScaleMinMax, + .toggleData, + .toggleBarBorders] + + + chartView.delegate = self + + chartView.chartDescription?.isEnabled = false + + chartView.isDrawBarShadowEnabled = false + chartView.isDrawValueAboveBarEnabled = true + + chartView.leftAxis.isEnabled = false + let rightAxis = chartView.rightAxis + rightAxis.axisMaximum = 25 + rightAxis.axisMinimum = -25 + rightAxis.isDrawZeroLineEnabled = true + rightAxis.labelCount = 7 + rightAxis.valueFormatter = DefaultAxisValueFormatter(formatter: customFormatter) + rightAxis.labelFont = .systemFont(ofSize: 9) + + let xAxis = chartView.xAxis + xAxis.labelPosition = .bothSided + xAxis.isDrawAxisLineEnabled = false + xAxis.axisMinimum = 0 + xAxis.axisMaximum = 110 + xAxis.isCenterAxisLabelsEnabled = true + xAxis.labelCount = 12 + xAxis.granularity = 10 + xAxis.valueFormatter = self + xAxis.labelFont = .systemFont(ofSize: 9) + + var l = chartView.legend + l.horizontalAlignment = .right + l.verticalAlignment = .bottom + l.orientation = .horizontal + l.formSize = 8 + l.formToTextSpace = 8 + l.xEntrySpace = 6 + chartView.legend = l + + self.updateChartData() + } + + override func updateChartData() { + if self.shouldHideData { + chartView.data = nil + return + } + + self.setChartData() + } + + func setChartData() { + let yVals = [BarChartDataEntry(x: 5, yValues: [-10, 10]), + BarChartDataEntry(x: 15, yValues: [-12, 13]), + BarChartDataEntry(x: 25, yValues: [-15, 15]), + BarChartDataEntry(x: 35, yValues: [-17, 17]), + BarChartDataEntry(x: 45, yValues: [-19, 120]), + BarChartDataEntry(x: 55, yValues: [-19, 19]), + BarChartDataEntry(x: 65, yValues: [-16, 16]), + BarChartDataEntry(x: 75, yValues: [-13, 14]), + BarChartDataEntry(x: 85, yValues: [-10, 11]), + BarChartDataEntry(x: 95, yValues: [-5, 6]), + BarChartDataEntry(x: 105, yValues: [-1, 2]) + ] + + let set = BarChartDataSet(values: yVals, label: "Age Distribution") + set.isDrawIconsEnabled = false + set.valueFormatter = DefaultValueFormatter(formatter: customFormatter) + set.valueFont = .systemFont(ofSize: 7) + set.axisDependency = .right + set.colors = [UIColor(red: 67/255, green: 67/255, blue: 72/255, alpha: 1), + UIColor(red: 124/255, green: 181/255, blue: 236/255, alpha: 1) + ] + set.stackLabels = ["Men", "Women"] + + let data = BarChartData(dataSet: set) + data.barWidth = 8.5 + + chartView.data = data + chartView.setNeedsDisplay() + } + + override func optionTapped(_ option: Option) { + super.handleOption(option, forChartView: chartView) + } +} + +extension NegativeStackedBarChartViewController: AxisValueFormatter { + func stringForValue(_ value: Double, axis: AxisBase) -> String { + return String(format: "%03.0f-%03.0f", value, value + 10) + } + + +} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/NegativeStackedBarChartViewController.xib b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/NegativeStackedBarChartViewController.xib new file mode 100644 index 0000000000..f30f9f8646 --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/NegativeStackedBarChartViewController.xib @@ -0,0 +1,56 @@ + + + + + + + + + + + + HelveticaNeue-Light + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/PieChartViewController.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/PieChartViewController.swift new file mode 100644 index 0000000000..d5c4d4d9ad --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/PieChartViewController.swift @@ -0,0 +1,153 @@ +// +// PieChartViewController.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-09. +// Copyright © 2017 jc. All rights reserved. +// + +import UIKit +import Charts + +class PieChartViewController: DemoBaseViewController { + + @IBOutlet var chartView: PieChartView! + @IBOutlet var sliderX: UISlider! + @IBOutlet var sliderY: UISlider! + @IBOutlet var sliderTextX: UITextField! + @IBOutlet var sliderTextY: UITextField! + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + self.title = "Half Pie Bar Chart" + + self.options = [.toggleValues, + .toggleXValues, + .togglePercent, + .toggleHole, + .toggleIcons, + .animateX, + .animateY, + .animateXY, + .spin, + .drawCenter, + .saveToGallery, + .toggleData] + + self.setup(pieChartView: chartView) + + chartView.delegate = self + + var l = chartView.legend + l.horizontalAlignment = .right + l.verticalAlignment = .top + l.orientation = .vertical + l.xEntrySpace = 7 + l.yEntrySpace = 0 + l.yOffset = 0 + chartView.legend = l + + // entry label styling + chartView.entryLabelColor = .white + chartView.entryLabelFont = .systemFont(ofSize: 12, weight: .light) + + sliderX.value = 4 + sliderY.value = 100 + self.slidersValueChanged(nil) + + chartView.animate(xAxisDuration: 1.4, easingOption: .easeOutBack) + } + + override func updateChartData() { + if self.shouldHideData { + chartView.data = nil + return + } + + self.setDataCount(Int(sliderX.value), range: UInt32(sliderY.value)) + } + + func setDataCount(_ count: Int, range: UInt32) { + let entries = (0.. PieChartDataEntry in + // IMPORTANT: In a PieChart, no values (Entry) should have the same xIndex (even if from different DataSets), since no values can be drawn above each other. + return PieChartDataEntry(value: Double(arc4random_uniform(range) + range / 5), + label: parties[i % parties.count], + icon: #imageLiteral(resourceName: "icon")) + } + + let set = PieChartDataSet(values: entries, label: "Election Results") + set.isDrawIconsEnabled = false + set.sliceSpace = 2 + + + set.colors = ChartColorTemplates.vordiplom + + ChartColorTemplates.joyful + + ChartColorTemplates.colorful + + ChartColorTemplates.liberty + + ChartColorTemplates.pastel + + [UIColor(red: 51/255, green: 181/255, blue: 229/255, alpha: 1)] + + let data = PieChartData(dataSet: set) + + let pFormatter = NumberFormatter() + pFormatter.numberStyle = .percent + pFormatter.maximumFractionDigits = 1 + pFormatter.multiplier = 1 + pFormatter.percentSymbol = " %" + data.setValueFormatter(DefaultValueFormatter(formatter: pFormatter)) + + data.setValueFont(.systemFont(ofSize: 11, weight: .light)) + data.setValueTextColor(.white) + + chartView.data = data + chartView.highlightValues(nil) + } + + override func optionTapped(_ option: Option) { + switch option { + case .toggleXValues: + chartView.isDrawEntryLabelsEnabled = !chartView.isDrawEntryLabelsEnabled + chartView.setNeedsDisplay() + + case .togglePercent: + chartView.usePercentValues = !chartView.usePercentValues + chartView.setNeedsDisplay() + + case .toggleHole: + chartView.isDrawHoleEnabled = !chartView.isDrawHoleEnabled + chartView.setNeedsDisplay() + + case .drawCenter: + chartView.isDrawCenterTextEnabled = !chartView.isDrawCenterTextEnabled + chartView.setNeedsDisplay() + + case .animateX: + chartView.animate(xAxisDuration: 1.4) + + case .animateY: + chartView.animate(yAxisDuration: 1.4) + + case .animateXY: + chartView.animate(xAxisDuration: 1.4, yAxisDuration: 1.4) + + case .spin: + chartView.spin(duration: 2, + fromAngle: chartView.rotationAngle, + toAngle: chartView.rotationAngle + 360, + easingOption: .easeInCubic) + + default: + handleOption(option, forChartView: chartView) + } + } + + // MARK: - Actions + @IBAction func slidersValueChanged(_ sender: Any?) { + sliderTextX.text = "\(Int(sliderX.value))" + sliderTextY.text = "\(Int(sliderY.value))" + + self.updateChartData() + } +} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/PieChartViewController.xib b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/PieChartViewController.xib new file mode 100644 index 0000000000..1fc7060ae3 --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/PieChartViewController.xib @@ -0,0 +1,100 @@ + + + + + + + + + + + + HelveticaNeue-Light + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/PiePolylineChartViewController.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/PiePolylineChartViewController.swift new file mode 100644 index 0000000000..8e9ff773de --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/PiePolylineChartViewController.swift @@ -0,0 +1,145 @@ +// +// PiePolylineChartViewController.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-09. +// Copyright © 2017 jc. All rights reserved. +// + +import UIKit +import Charts + +class PiePolylineChartViewController: DemoBaseViewController { + + @IBOutlet var chartView: PieChartView! + @IBOutlet var sliderX: UISlider! + @IBOutlet var sliderY: UISlider! + @IBOutlet var sliderTextX: UITextField! + @IBOutlet var sliderTextY: UITextField! + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + self.title = "Pie Bar Chart" + + self.options = [.toggleValues, + .toggleXValues, + .togglePercent, + .toggleHole, + .animateX, + .animateY, + .animateXY, + .spin, + .drawCenter, + .saveToGallery, + .toggleData] + + self.setup(pieChartView: chartView) + + chartView.delegate = self + + chartView.legend.isEnabled = false + chartView.setExtraOffsets(left: 20, top: 0, right: 20, bottom: 0) + + sliderX.value = 40 + sliderY.value = 100 + self.slidersValueChanged(nil) + + chartView.animate(xAxisDuration: 1.4, easingOption: .easeOutBack) + } + + override func updateChartData() { + if self.shouldHideData { + chartView.data = nil + return + } + + self.setDataCount(Int(sliderX.value), range: UInt32(sliderY.value)) + } + + func setDataCount(_ count: Int, range: UInt32) { + let entries = (0.. PieChartDataEntry in + // IMPORTANT: In a PieChart, no values (Entry) should have the same xIndex (even if from different DataSets), since no values can be drawn above each other. + return PieChartDataEntry(value: Double(arc4random_uniform(range) + range / 5), + label: parties[i % parties.count]) + } + + let set = PieChartDataSet(values: entries, label: "Election Results") + set.sliceSpace = 2 + + + set.colors = ChartColorTemplates.vordiplom + + ChartColorTemplates.joyful + + ChartColorTemplates.colorful + + ChartColorTemplates.liberty + + ChartColorTemplates.pastel + + [UIColor(red: 51/255, green: 181/255, blue: 229/255, alpha: 1)] + + set.valueLinePart1OffsetPercentage = 0.8 + set.valueLinePart1Length = 0.2 + set.valueLinePart2Length = 0.4 + //set.xValuePosition = .outsideSlice + set.yValuePosition = .outsideSlice + + let data = PieChartData(dataSet: set) + + let pFormatter = NumberFormatter() + pFormatter.numberStyle = .percent + pFormatter.maximumFractionDigits = 1 + pFormatter.multiplier = 1 + pFormatter.percentSymbol = " %" + data.setValueFormatter(DefaultValueFormatter(formatter: pFormatter)) + data.setValueFont(.systemFont(ofSize: 11, weight: .light)) + data.setValueTextColor(.black) + + chartView.data = data + chartView.highlightValues(nil) + } + + override func optionTapped(_ option: Option) { + switch option { + case .toggleXValues: + chartView.isDrawEntryLabelsEnabled = !chartView.isDrawEntryLabelsEnabled + chartView.setNeedsDisplay() + + case .togglePercent: + chartView.usePercentValues = !chartView.usePercentValues + chartView.setNeedsDisplay() + + case .toggleHole: + chartView.isDrawHoleEnabled = !chartView.isDrawHoleEnabled + chartView.setNeedsDisplay() + + case .drawCenter: + chartView.isDrawCenterTextEnabled = !chartView.isDrawCenterTextEnabled + chartView.setNeedsDisplay() + + case .animateX: + chartView.animate(xAxisDuration: 1.4) + + case .animateY: + chartView.animate(yAxisDuration: 1.4) + + case .animateXY: + chartView.animate(xAxisDuration: 1.4, yAxisDuration: 1.4) + + case .spin: + chartView.spin(duration: 2, + fromAngle: chartView.rotationAngle, + toAngle: chartView.rotationAngle + 360, + easingOption: .easeInCubic) + + default: + handleOption(option, forChartView: chartView) + } + } + + // MARK: - Actions + @IBAction func slidersValueChanged(_ sender: Any?) { + sliderTextX.text = "\(Int(sliderX.value))" + sliderTextY.text = "\(Int(sliderY.value))" + + self.updateChartData() + } +} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/PiePolylineChartViewController.xib b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/PiePolylineChartViewController.xib new file mode 100644 index 0000000000..d355365551 --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/PiePolylineChartViewController.xib @@ -0,0 +1,114 @@ + + + + + + + + + + + + HelveticaNeue-Light + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/PositiveNegativeBarChartViewController.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/PositiveNegativeBarChartViewController.swift new file mode 100644 index 0000000000..75aacbd6c5 --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/PositiveNegativeBarChartViewController.swift @@ -0,0 +1,120 @@ +// +// PositiveNegativeBarChartViewController.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-09. +// Copyright © 2017 jc. All rights reserved. +// + +import UIKit +import Charts + +class PositiveNegativeBarChartViewController: DemoBaseViewController { + + @IBOutlet var chartView: BarChartView! + + let dataLabels = ["12-19", + "12-30", + "12-31", + "01-01", + "01-02"] + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + self.title = "Bar Chart" + self.options = [.toggleValues, + .toggleHighlight, + .animateX, + .animateY, + .animateXY, + .saveToGallery, + .togglePinchZoom, + .toggleAutoScaleMinMax, + .toggleData, + .toggleBarBorders] + + self.setup(barLineChartView: chartView) + + chartView.delegate = self + + chartView.setExtraOffsets(left: 70, top: -30, right: 70, bottom: 10) + + chartView.isDrawBarShadowEnabled = false + chartView.isDrawValueAboveBarEnabled = true + + chartView.chartDescription?.isEnabled = false + + chartView.rightAxis.isEnabled = false + + let xAxis = chartView.xAxis + xAxis.labelPosition = .bottom + xAxis.labelFont = .systemFont(ofSize: 13) + xAxis.isDrawAxisLineEnabled = false + xAxis.labelTextColor = .lightGray + xAxis.labelCount = 5 + xAxis.isCenterAxisLabelsEnabled = true + xAxis.granularity = 1 + xAxis.valueFormatter = self + + let leftAxis = chartView.leftAxis + leftAxis.isDrawLabelsEnabled = false + leftAxis.spaceTop = 0.25 + leftAxis.spaceBottom = 0.25 + leftAxis.isDrawAxisLineEnabled = false + leftAxis.isDrawZeroLineEnabled = true + leftAxis.zeroLineColor = .gray + leftAxis.zeroLineWidth = 0.7 + + self.updateChartData() + } + + override func updateChartData() { + if self.shouldHideData { + chartView.data = nil + return + } + + self.setChartData() + } + + func setChartData() { + let yVals = [BarChartDataEntry(x: 0, y: -224.1), + BarChartDataEntry(x: 1, y: 238.5), + BarChartDataEntry(x: 2, y: 1280.1), + BarChartDataEntry(x: 3, y: -442.3), + BarChartDataEntry(x: 4, y: -2280.1) + ] + + let red = UIColor(red: 211/255, green: 74/255, blue: 88/255, alpha: 1) + let green = UIColor(red: 110/255, green: 190/255, blue: 102/255, alpha: 1) + let colors = yVals.map { (entry) -> Color in + return entry.y > 0 ? red : green + } + + let set = BarChartDataSet(values: yVals, label: "Values") + set.colors = colors + set.valueColors = colors + + let data = BarChartData(dataSet: set) + data.setValueFont(.systemFont(ofSize: 13)) + + let formatter = NumberFormatter() + formatter.maximumFractionDigits = 1 + data.setValueFormatter(DefaultValueFormatter(formatter: formatter)) + data.barWidth = 0.8 + + chartView.data = data + } + + override func optionTapped(_ option: Option) { + super.handleOption(option, forChartView: chartView) + } +} + +extension PositiveNegativeBarChartViewController: AxisValueFormatter { + func stringForValue(_ value: Double, axis: AxisBase) -> String { + return dataLabels[min(max(Int(value), 0), dataLabels.count - 1)] + } +} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/PositiveNegativeBarChartViewController.xib b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/PositiveNegativeBarChartViewController.xib new file mode 100644 index 0000000000..9b13e52d8d --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/PositiveNegativeBarChartViewController.xib @@ -0,0 +1,56 @@ + + + + + + + + + + + + HelveticaNeue-Light + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/RadarChartViewController.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/RadarChartViewController.swift new file mode 100644 index 0000000000..f04db3cfb5 --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/RadarChartViewController.swift @@ -0,0 +1,203 @@ +// +// RadarChartViewController.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-09. +// Copyright © 2017 jc. All rights reserved. +// + +import UIKit +import Charts + +class RadarChartViewController: DemoBaseViewController { + + @IBOutlet var chartView: RadarChartView! + + let activities = ["Burger", "Steak", "Salad", "Pasta", "Pizza"] + var originalBarBgColor: UIColor! + var originalBarTintColor: UIColor! + var originalBarStyle: UIBarStyle! + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + self.title = "Radar Bar Chart" + self.options = [.toggleValues, + .toggleHighlight, + .toggleHighlightCircle, + .toggleXLabels, + .toggleYLabels, + .toggleRotate, + .toggleFilled, + .animateX, + .animateY, + .animateXY, + .spin, + .saveToGallery, + .toggleData] + + chartView.delegate = self + + chartView.chartDescription?.isEnabled = false + chartView.webLineWidth = 1 + chartView.innerWebLineWidth = 1 + chartView.webColor = .lightGray + chartView.innerWebColor = .lightGray + chartView.webAlpha = 1 + + let marker = RadarMarkerView.viewFromXib()! + marker.chartView = chartView + chartView.marker = marker + + let xAxis = chartView.xAxis + xAxis.labelFont = .systemFont(ofSize: 9, weight: .light) + xAxis.xOffset = 0 + xAxis.yOffset = 0 + xAxis.valueFormatter = self + xAxis.labelTextColor = .white + + let yAxis = chartView.yAxis + yAxis.labelFont = .systemFont(ofSize: 9, weight: .light) + yAxis.labelCount = 5 + yAxis.axisMinimum = 0 + yAxis.axisMaximum = 80 + yAxis.isDrawLabelsEnabled = false + + var l = chartView.legend + l.horizontalAlignment = .center + l.verticalAlignment = .top + l.orientation = .horizontal + l.drawInside = false + l.font = .systemFont(ofSize: 10, weight: .light) + l.xEntrySpace = 7 + l.yEntrySpace = 5 + l.textColor = .white + chartView.legend = l + + self.updateChartData() + + chartView.animate(xAxisDuration: 1.4, yAxisDuration: 1.4, easingOption: .easeOutBack) + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + UIView.animate(withDuration: 0.15) { + let navBar = self.navigationController!.navigationBar + self.originalBarBgColor = navBar.barTintColor + self.originalBarTintColor = navBar.tintColor + self.originalBarStyle = navBar.barStyle + + navBar.barTintColor = self.view.backgroundColor + navBar.tintColor = .white + navBar.barStyle = .black + } + } + + override func viewWillDisappear(_ animated: Bool) { + super.viewWillDisappear(animated) + + UIView.animate(withDuration: 0.15) { + let navBar = self.navigationController!.navigationBar + navBar.barTintColor = self.originalBarBgColor + navBar.tintColor = self.originalBarTintColor + navBar.barStyle = self.originalBarStyle + } + } + + override func updateChartData() { + if self.shouldHideData { + chartView.data = nil + return + } + + self.setChartData() + } + + func setChartData() { + let mult: UInt32 = 80 + let min: UInt32 = 20 + let cnt = 5 + + let block: (Int) -> RadarChartDataEntry = { _ in return RadarChartDataEntry(value: Double(arc4random_uniform(mult) + min))} + let entries1 = (0.. String { + return activities[Int(value) % activities.count] + } +} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/RadarChartViewController.xib b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/RadarChartViewController.xib new file mode 100644 index 0000000000..a3dfdabb90 --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/RadarChartViewController.xib @@ -0,0 +1,65 @@ + + + + + + + + + + + + + HelveticaNeue-Light + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/ScatterChartViewController.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/ScatterChartViewController.swift new file mode 100644 index 0000000000..54e9b52774 --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/ScatterChartViewController.swift @@ -0,0 +1,124 @@ +// +// ScatterChartViewController.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-09. +// Copyright © 2017 jc. All rights reserved. +// + +import UIKit +import Charts + +class ScatterChartViewController: DemoBaseViewController { + + @IBOutlet var chartView: ScatterChartView! + @IBOutlet var sliderX: UISlider! + @IBOutlet var sliderY: UISlider! + @IBOutlet var sliderTextX: UITextField! + @IBOutlet var sliderTextY: UITextField! + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + self.title = "Scatter Bar Chart" + self.options = [.toggleValues, + .toggleHighlight, + .animateX, + .animateY, + .animateXY, + .saveToGallery, + .togglePinchZoom, + .toggleAutoScaleMinMax, + .toggleData] + + chartView.delegate = self + + chartView.chartDescription?.isEnabled = false + + chartView.isDragEnabled = true + chartView.setScaleEnabled(true) + chartView.maxVisibleCount = 200 + chartView.isPinchZoomEnabled = true + + var l = chartView.legend + l.horizontalAlignment = .right + l.verticalAlignment = .top + l.orientation = .vertical + l.drawInside = false + l.font = .systemFont(ofSize: 10, weight: .light) + l.xOffset = 5 + + let leftAxis = chartView.leftAxis + leftAxis.labelFont = .systemFont(ofSize: 10, weight: .light) + leftAxis.axisMinimum = 0 + + chartView.rightAxis.isEnabled = false + + + let xAxis = chartView.xAxis + xAxis.labelFont = .systemFont(ofSize: 10, weight: .light) + + sliderX.value = 45 + sliderY.value = 100 + slidersValueChanged(nil) + } + + override func updateChartData() { + if self.shouldHideData { + chartView.data = nil + return + } + + self.setDataCount(Int(sliderX.value + 1), range: UInt32(sliderY.value)) + } + + func setDataCount(_ count: Int, range: UInt32) { + let values1 = (0.. ChartDataEntry in + let val = Double(arc4random_uniform(range) + 3) + return ChartDataEntry(x: Double(i), y: val) + } + let values2 = (0.. ChartDataEntry in + let val = Double(arc4random_uniform(range) + 3) + return ChartDataEntry(x: Double(i) + 0.33, y: val) + } + let values3 = (0.. ChartDataEntry in + let val = Double(arc4random_uniform(range) + 3) + return ChartDataEntry(x: Double(i) + 0.66, y: val) + } + + + let set1 = ScatterChartDataSet(values: values1, label: "DS 1") + set1.setScatterShape(.square) + set1.setColor(ChartColorTemplates.colorful[0]) + set1.scatterShapeSize = 8 + + let set2 = ScatterChartDataSet(values: values2, label: "DS 2") + set2.setScatterShape(.circle) + set2.scatterShapeHoleColor = ChartColorTemplates.colorful[3] + set2.scatterShapeHoleRadius = 3.5 + set2.setColor(ChartColorTemplates.colorful[1]) + set2.scatterShapeSize = 8 + + let set3 = ScatterChartDataSet(values: values3, label: "DS 3") + set3.setScatterShape(.cross) + set3.setColor(ChartColorTemplates.colorful[2]) + set3.scatterShapeSize = 8 + + let data = ScatterChartData(dataSets: [set1, set2, set3]) + data.setValueFont(.systemFont(ofSize: 7, weight: .light)) + + chartView.data = data + } + + override func optionTapped(_ option: Option) { + super.handleOption(option, forChartView: chartView) + } + + @IBAction func slidersValueChanged(_ sender: Any?) { + sliderTextX.text = "\(Int(sliderX.value))" + sliderTextY.text = "\(Int(sliderY.value))" + + self.updateChartData() + } +} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/ScatterChartViewController.xib b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/ScatterChartViewController.xib new file mode 100644 index 0000000000..289fe5fe0d --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/ScatterChartViewController.xib @@ -0,0 +1,100 @@ + + + + + + + + + + + + HelveticaNeue-Light + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/SinusBarChartViewController.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/SinusBarChartViewController.swift new file mode 100644 index 0000000000..32bbc79bb4 --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/SinusBarChartViewController.swift @@ -0,0 +1,108 @@ +// +// SinusBarChartViewController.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-09. +// Copyright © 2017 jc. All rights reserved. +// + +import UIKit +import Charts + +class SinusBarChartViewController: DemoBaseViewController { + + @IBOutlet var chartView: BarChartView! + @IBOutlet var sliderX: UISlider! + @IBOutlet var sliderTextX: UITextField! + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + self.title = "Line Chart 2" + self.options = [.toggleValues, + .toggleHighlight, + .animateX, + .animateY, + .animateXY, + .saveToGallery, + .togglePinchZoom, + .toggleAutoScaleMinMax, + .toggleData] + + chartView.delegate = self + + chartView.chartDescription?.isEnabled = false + + chartView.isDrawBarShadowEnabled = false + chartView.isDrawValueAboveBarEnabled = false + chartView.maxVisibleCount = 60 + + let xAxis = chartView.xAxis + xAxis.labelPosition = .bottom + xAxis.isEnabled = false + + let leftAxis = chartView.leftAxis + leftAxis.labelCount = 6 + leftAxis.axisMinimum = -2.5 + leftAxis.axisMaximum = 2.5 + leftAxis.isGranularityEnabled = true + leftAxis.granularity = 0.1 + + let rightAxis = chartView.rightAxis + rightAxis.labelCount = 6 + rightAxis.axisMinimum = -2.5 + rightAxis.axisMaximum = 2.5 + rightAxis.granularity = 0.1 + + var l = chartView.legend + l.horizontalAlignment = .left + l.verticalAlignment = .bottom + l.orientation = .horizontal + l.drawInside = false + l.form = .square + l.formSize = 9 + l.font = .systemFont(ofSize: 11) + l.xEntrySpace = 4 + chartView.legend = l + + sliderX.value = 150 + slidersValueChanged(nil) + + chartView.animate(xAxisDuration: 2, yAxisDuration: 2) + } + + override func updateChartData() { + if self.shouldHideData { + chartView.data = nil + return + } + + self.setDataCount(Int(sliderX.value)) + } + + func setDataCount(_ count: Int) { + let entries = (0.. + + + + + + + + + + + HelveticaNeue-Light + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/StackedBarChartViewController.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/StackedBarChartViewController.swift new file mode 100644 index 0000000000..6dd0322805 --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/StackedBarChartViewController.swift @@ -0,0 +1,125 @@ +// +// StackedBarChartViewController.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-09. +// Copyright © 2017 jc. All rights reserved. +// + +import UIKit +import Charts + +class StackedBarChartViewController: DemoBaseViewController { + + @IBOutlet var chartView: BarChartView! + @IBOutlet var sliderX: UISlider! + @IBOutlet var sliderY: UISlider! + @IBOutlet var sliderTextX: UITextField! + @IBOutlet var sliderTextY: UITextField! + + lazy var formatter: NumberFormatter = { + let formatter = NumberFormatter() + formatter.maximumFractionDigits = 1 + formatter.negativeSuffix = " $" + formatter.positiveSuffix = " $" + + return formatter + }() + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + self.title = "Stacked Bar Chart" + self.options = [.toggleValues, + .toggleIcons, + .toggleHighlight, + .animateX, + .animateY, + .animateXY, + .saveToGallery, + .togglePinchZoom, + .toggleAutoScaleMinMax, + .toggleData, + .toggleBarBorders] + + + chartView.delegate = self + + chartView.chartDescription?.isEnabled = false + + chartView.maxVisibleCount = 40 + chartView.isDrawBarShadowEnabled = false + chartView.isDrawValueAboveBarEnabled = false + chartView.isHighlightFullBarEnabled = false + + let leftAxis = chartView.leftAxis + leftAxis.valueFormatter = DefaultAxisValueFormatter(formatter: formatter) + leftAxis.axisMinimum = 0 + + chartView.rightAxis.isEnabled = false + + let xAxis = chartView.xAxis + xAxis.labelPosition = .top + + var l = chartView.legend + l.horizontalAlignment = .right + l.verticalAlignment = .bottom + l.orientation = .horizontal + l.drawInside = false + l.form = .square + l.formToTextSpace = 4 + l.xEntrySpace = 6 + chartView.legend = l + + sliderX.value = 12 + sliderY.value = 100 + slidersValueChanged(nil) + + self.updateChartData() + } + + override func updateChartData() { + if self.shouldHideData { + chartView.data = nil + return + } + + self.setChartData(count: Int(sliderX.value + 1), range: UInt32(sliderY.value)) + } + + func setChartData(count: Int, range: UInt32) { + let yVals = (0.. BarChartDataEntry in + let mult = range + 1 + let val1 = Double(arc4random_uniform(mult) + mult / 3) + let val2 = Double(arc4random_uniform(mult) + mult / 3) + let val3 = Double(arc4random_uniform(mult) + mult / 3) + + return BarChartDataEntry(x: Double(i), yValues: [val1, val2, val3], icon: #imageLiteral(resourceName: "icon")) + } + + let set = BarChartDataSet(values: yVals, label: "Statistics Vienna 2014") + set.isDrawIconsEnabled = false + set.colors = [ChartColorTemplates.material[0], ChartColorTemplates.material[1], ChartColorTemplates.material[2]] + set.stackLabels = ["Births", "Divorces", "Marriages"] + + let data = BarChartData(dataSet: set) + data.setValueFont(.systemFont(ofSize: 7, weight: .light)) + data.setValueFormatter(DefaultValueFormatter(formatter: formatter)) + data.setValueTextColor(.white) + + chartView.fitBars = true + chartView.data = data + } + + override func optionTapped(_ option: Option) { + super.handleOption(option, forChartView: chartView) + } + + @IBAction func slidersValueChanged(_ sender: Any?) { + sliderTextX.text = "\(Int(sliderX.value))" + sliderTextY.text = "\(Int(sliderY.value))" + + updateChartData() + } +} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/StackedBarChartViewController.xib b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/StackedBarChartViewController.xib new file mode 100644 index 0000000000..dca9b05421 --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/StackedBarChartViewController.xib @@ -0,0 +1,100 @@ + + + + + + + + + + + + HelveticaNeue-Light + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Formatters/DateValueFormatter.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Formatters/DateValueFormatter.swift new file mode 100644 index 0000000000..32367910ed --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Formatters/DateValueFormatter.swift @@ -0,0 +1,22 @@ +// +// DateValueFormatter.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-09. +// Copyright © 2017 jc. All rights reserved. +// + +import Foundation +import Charts + +public class DateValueFormatter: AxisValueFormatter { + private let dateFormatter = DateFormatter() + + init() { + dateFormatter.dateFormat = "dd MMM HH:mm" + } + + public func stringForValue(_ value: Double, axis: AxisBase) -> String { + return dateFormatter.string(from: Date(timeIntervalSince1970: value)) + } +} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Formatters/DayAxisValueFormatter.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Formatters/DayAxisValueFormatter.swift new file mode 100644 index 0000000000..df9e781ab7 --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Formatters/DayAxisValueFormatter.swift @@ -0,0 +1,109 @@ +// +// DayAxisValueFormatter.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-09. +// Copyright © 2017 jc. All rights reserved. +// + +import Foundation +import Charts + +public class DayAxisValueFormatter: AxisValueFormatter { + weak var chart: BarLineChartViewBase? + let months = ["Jan", "Feb", "Mar", + "Apr", "May", "Jun", + "Jul", "Aug", "Sep", + "Oct", "Nov", "Dec"] + + init(chart: BarLineChartViewBase) { + self.chart = chart + } + + public func stringForValue(_ value: Double, axis: AxisBase) -> String { + let days = Int(value) + let year = determineYear(forDays: days) + let month = determineMonth(forDayOfYear: days) + + let monthName = months[month % months.count] + let yearName = "\(year)" + + if let chart = chart, + chart.visibleXRange > 30 * 6 { + return monthName + yearName + } else { + let dayOfMonth = determineDayOfMonth(forDays: days, month: month + 12 * (year - 2016)) + var appendix: String + + switch dayOfMonth { + case 1, 21, 31: appendix = "st" + case 2, 22: appendix = "nd" + case 3, 23: appendix = "rd" + default: appendix = "th" + } + + return dayOfMonth == 0 ? "" : String(format: "%d\(appendix) \(monthName)", dayOfMonth) + } + } + + private func days(forMonth month: Int, year: Int) -> Int { + // month is 0-based + switch month { + case 1: + var is29Feb = false + if year < 1582 { + is29Feb = (year < 1 ? year + 1 : year) % 4 == 0 + } else if year > 1582 { + is29Feb = year % 4 == 0 && (year % 100 != 0 || year % 400 == 0) + } + + return is29Feb ? 29 : 28 + + case 3, 5, 8, 10: + return 30 + + default: + return 31 + } + } + + private func determineMonth(forDayOfYear dayOfYear: Int) -> Int { + var month = -1 + var days = 0 + + while days < dayOfYear { + month += 1 + if month >= 12 { + month = 0 + } + + let year = determineYear(forDays: days) + days += self.days(forMonth: month, year: year) + } + + return max(month, 0) + } + + private func determineDayOfMonth(forDays days: Int, month: Int) -> Int { + var count = 0 + var daysForMonth = 0 + + while count < month { + let year = determineYear(forDays: days) + daysForMonth += self.days(forMonth: count % 12, year: year) + count += 1 + } + + return days - daysForMonth + } + + private func determineYear(forDays days: Int) -> Int { + switch days { + case ...366: return 2016 + case 367...730: return 2017 + case 731...1094: return 2018 + case 1095...1458: return 2019 + default: return 2020 + } + } +} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Formatters/IntAxisValueFormatter.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Formatters/IntAxisValueFormatter.swift new file mode 100644 index 0000000000..3599910d1b --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Formatters/IntAxisValueFormatter.swift @@ -0,0 +1,16 @@ +// +// IntAxisValueFormatter.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-09. +// Copyright © 2017 jc. All rights reserved. +// + +import Foundation +import Charts + +public class IntAxisValueFormatter: AxisValueFormatter { + public func stringForValue(_ value: Double, axis: AxisBase) -> String { + return "\(Int(value))" + } +} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Formatters/LargeValueFormatter.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Formatters/LargeValueFormatter.swift new file mode 100644 index 0000000000..4cbe42f431 --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Formatters/LargeValueFormatter.swift @@ -0,0 +1,56 @@ +// +// LargeValueFormatter.swift +// ChartsDemo +// Copyright © 2016 dcg. All rights reserved. +// + +import Foundation +import Charts + +private let MAX_LENGTH = 5 + +public class LargeValueFormatter: ValueFormatter, AxisValueFormatter { + + /// Suffix to be appended after the values. + /// + /// **default**: suffix: ["", "k", "m", "b", "t"] + public var suffix = ["", "k", "m", "b", "t"] + + /// An appendix text to be added at the end of the formatted value. + public var appendix: String? + + public init(appendix: String? = nil) { + self.appendix = appendix + } + + fileprivate func format(value: Double) -> String { + var sig = value + var length = 0 + let maxLength = suffix.count - 1 + + while sig >= 1000.0 && length < maxLength { + sig /= 1000.0 + length += 1 + } + + var r = String(format: "%2.f", sig) + suffix[length] + + if let appendix = appendix { + r += appendix + } + + return r + } + + public func stringForValue(_ value: Double, axis: AxisBase) -> String { + return format(value: value) + } + + public func stringForValue( + _ value: Double, + entry: ChartDataEntry, + dataSetIndex: Int, + viewPortHandler: ViewPortHandler?) -> String { + return format(value: value) + } +} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Info.plist b/ChartsDemo-iOS/ChartsDemo-iOS/Info.plist new file mode 100644 index 0000000000..4222ac2dd3 --- /dev/null +++ b/ChartsDemo-iOS/ChartsDemo-iOS/Info.plist @@ -0,0 +1,43 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + From 469b6361d4943e948d518a9857eb540fa8d622af Mon Sep 17 00:00:00 2001 From: jjatie Date: Fri, 21 Jul 2017 17:30:29 -0400 Subject: [PATCH 2/6] .xcodeproj won't add to git Uploading from GitHub --- ChartsDemo-iOS/ChartsDemo-iOS.xcodeproj.zip | Bin 0 -> 38193 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 ChartsDemo-iOS/ChartsDemo-iOS.xcodeproj.zip diff --git a/ChartsDemo-iOS/ChartsDemo-iOS.xcodeproj.zip b/ChartsDemo-iOS/ChartsDemo-iOS.xcodeproj.zip new file mode 100644 index 0000000000000000000000000000000000000000..dde27ae2ba68387d5dd90877285a1aa3440e3f8f GIT binary patch literal 38193 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

S^pvhYR^W$;o%< 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 Date: Sun, 17 Sep 2017 10:01:29 -0400 Subject: [PATCH 3/6] Reorganized in preparation of merging Swift Demos --- .../ChartsDemo.xcodeproj/project.pbxproj | 82 +++++++++++-------- ChartsDemo/Classes/RealmDemosViewController.h | 18 ---- ChartsDemo/Classes/RealmDemosViewController.m | 35 -------- .../{Classes => Objective-C}/AppDelegate.h | 0 .../{Classes => Objective-C}/AppDelegate.m | 0 .../Components/BalloonMarker.swift | 0 .../Components/RadarMarkerView.swift | 0 .../Components/XYMarkerView.swift | 0 .../DemoBaseViewController.h | 0 .../DemoBaseViewController.m | 0 .../DemoListViewController.h | 0 .../DemoListViewController.m | 0 .../Demos/AnotherBarChartViewController.h | 0 .../Demos/AnotherBarChartViewController.m | 0 .../Demos/BarChartViewController.h | 0 .../Demos/BarChartViewController.m | 0 .../Demos/BubbleChartViewController.h | 0 .../Demos/BubbleChartViewController.m | 0 .../Demos/CandleStickChartViewController.h | 0 .../Demos/CandleStickChartViewController.m | 0 .../Demos/ColoredLineChartViewController.h | 0 .../Demos/ColoredLineChartViewController.m | 0 .../Demos/CombinedChartViewController.h | 0 .../Demos/CombinedChartViewController.m | 0 .../Demos/CubicLineChartViewController.h | 0 .../Demos/CubicLineChartViewController.m | 0 .../Demos/HalfPieChartViewController.h | 0 .../Demos/HalfPieChartViewController.m | 0 .../Demos/HorizontalBarChartViewController.h | 0 .../Demos/HorizontalBarChartViewController.m | 0 .../Demos/LineChart1ViewController.h | 0 .../Demos/LineChart1ViewController.m | 0 .../Demos/LineChart2ViewController.h | 0 .../Demos/LineChart2ViewController.m | 0 .../Demos/LineChartFilledViewController.h | 0 .../Demos/LineChartFilledViewController.m | 0 .../Demos/LineChartTimeViewController.h | 0 .../Demos/LineChartTimeViewController.m | 0 .../Demos/MultipleBarChartViewController.h | 0 .../Demos/MultipleBarChartViewController.m | 0 .../Demos/MultipleLinesChartViewController.h | 0 .../Demos/MultipleLinesChartViewController.m | 0 .../NegativeStackedBarChartViewController.h | 0 .../NegativeStackedBarChartViewController.m | 0 .../Demos/PieChartViewController.h | 0 .../Demos/PieChartViewController.m | 0 .../Demos/PiePolylineChartViewController.h | 0 .../Demos/PiePolylineChartViewController.m | 0 .../PositiveNegativeBarChartViewController.h | 0 .../PositiveNegativeBarChartViewController.m | 0 .../Demos/RadarChartViewController.h | 0 .../Demos/RadarChartViewController.m | 0 .../Demos/ScatterChartViewController.h | 0 .../Demos/ScatterChartViewController.m | 0 .../Demos/SinusBarChartViewController.h | 0 .../Demos/SinusBarChartViewController.m | 0 .../Demos/StackedBarChartViewController.h | 0 .../Demos/StackedBarChartViewController.m | 0 .../Formatters/DateValueFormatter.h | 0 .../Formatters/DateValueFormatter.m | 0 .../Formatters/DayAxisValueFormatter.h | 0 .../Formatters/DayAxisValueFormatter.m | 0 .../Formatters/IntAxisValueFormatter.h | 0 .../Formatters/IntAxisValueFormatter.m | 0 .../Formatters/LargeValueFormatter.swift | 0 .../DemoListViewController.xib | 0 .../Demos/AnotherBarChartViewController.xib | 0 .../Demos/BarChartViewController.xib | 0 .../Demos/BubbleChartViewController.xib | 0 .../Demos/CandleStickChartViewController.xib | 0 .../Demos/ColoredLineChartViewController.xib | 0 .../Demos/CombinedChartViewController.xib | 0 .../Demos/CubicLineChartViewController.xib | 0 .../Demos/HalfPieChartViewController.xib | 0 .../HorizontalBarChartViewController.xib | 0 .../Demos/LineChart1ViewController.xib | 0 .../Demos/LineChart2ViewController.xib | 0 .../Demos/LineChartFilledViewController.xib | 0 .../Demos/LineChartTimeViewController.xib | 0 .../Demos/MultipleBarChartViewController.xib | 0 .../MultipleLinesChartViewController.xib | 0 .../NegativeStackedBarChartViewController.xib | 0 .../Demos/PieChartViewController.xib | 0 .../Demos/PiePolylineChartViewController.xib | 0 ...PositiveNegativeBarChartViewController.xib | 0 .../Demos/RadarChartViewController.xib | 0 .../Demos}/RealmDemosViewController.xib | 0 .../Demos/ScatterChartViewController.xib | 0 .../Demos/SinusBarChartViewController.xib | 0 .../Demos/StackedBarChartViewController.xib | 20 ++++- .../Components => XIBs}/RadarMarkerView.xib | 0 91 files changed, 63 insertions(+), 92 deletions(-) delete mode 100644 ChartsDemo/Classes/RealmDemosViewController.h delete mode 100644 ChartsDemo/Classes/RealmDemosViewController.m rename ChartsDemo/{Classes => Objective-C}/AppDelegate.h (100%) rename ChartsDemo/{Classes => Objective-C}/AppDelegate.m (100%) rename ChartsDemo/{Classes => Objective-C}/Components/BalloonMarker.swift (100%) rename ChartsDemo/{Classes => Objective-C}/Components/RadarMarkerView.swift (100%) rename ChartsDemo/{Classes => Objective-C}/Components/XYMarkerView.swift (100%) rename ChartsDemo/{Classes => Objective-C}/DemoBaseViewController.h (100%) rename ChartsDemo/{Classes => Objective-C}/DemoBaseViewController.m (100%) rename ChartsDemo/{Classes => Objective-C}/DemoListViewController.h (100%) rename ChartsDemo/{Classes => Objective-C}/DemoListViewController.m (100%) rename ChartsDemo/{Classes => Objective-C}/Demos/AnotherBarChartViewController.h (100%) rename ChartsDemo/{Classes => Objective-C}/Demos/AnotherBarChartViewController.m (100%) rename ChartsDemo/{Classes => Objective-C}/Demos/BarChartViewController.h (100%) rename ChartsDemo/{Classes => Objective-C}/Demos/BarChartViewController.m (100%) rename ChartsDemo/{Classes => Objective-C}/Demos/BubbleChartViewController.h (100%) rename ChartsDemo/{Classes => Objective-C}/Demos/BubbleChartViewController.m (100%) rename ChartsDemo/{Classes => Objective-C}/Demos/CandleStickChartViewController.h (100%) rename ChartsDemo/{Classes => Objective-C}/Demos/CandleStickChartViewController.m (100%) rename ChartsDemo/{Classes => Objective-C}/Demos/ColoredLineChartViewController.h (100%) rename ChartsDemo/{Classes => Objective-C}/Demos/ColoredLineChartViewController.m (100%) rename ChartsDemo/{Classes => Objective-C}/Demos/CombinedChartViewController.h (100%) rename ChartsDemo/{Classes => Objective-C}/Demos/CombinedChartViewController.m (100%) rename ChartsDemo/{Classes => Objective-C}/Demos/CubicLineChartViewController.h (100%) rename ChartsDemo/{Classes => Objective-C}/Demos/CubicLineChartViewController.m (100%) rename ChartsDemo/{Classes => Objective-C}/Demos/HalfPieChartViewController.h (100%) rename ChartsDemo/{Classes => Objective-C}/Demos/HalfPieChartViewController.m (100%) rename ChartsDemo/{Classes => Objective-C}/Demos/HorizontalBarChartViewController.h (100%) rename ChartsDemo/{Classes => Objective-C}/Demos/HorizontalBarChartViewController.m (100%) rename ChartsDemo/{Classes => Objective-C}/Demos/LineChart1ViewController.h (100%) rename ChartsDemo/{Classes => Objective-C}/Demos/LineChart1ViewController.m (100%) rename ChartsDemo/{Classes => Objective-C}/Demos/LineChart2ViewController.h (100%) rename ChartsDemo/{Classes => Objective-C}/Demos/LineChart2ViewController.m (100%) rename ChartsDemo/{Classes => Objective-C}/Demos/LineChartFilledViewController.h (100%) rename ChartsDemo/{Classes => Objective-C}/Demos/LineChartFilledViewController.m (100%) rename ChartsDemo/{Classes => Objective-C}/Demos/LineChartTimeViewController.h (100%) rename ChartsDemo/{Classes => Objective-C}/Demos/LineChartTimeViewController.m (100%) rename ChartsDemo/{Classes => Objective-C}/Demos/MultipleBarChartViewController.h (100%) rename ChartsDemo/{Classes => Objective-C}/Demos/MultipleBarChartViewController.m (100%) rename ChartsDemo/{Classes => Objective-C}/Demos/MultipleLinesChartViewController.h (100%) rename ChartsDemo/{Classes => Objective-C}/Demos/MultipleLinesChartViewController.m (100%) rename ChartsDemo/{Classes => Objective-C}/Demos/NegativeStackedBarChartViewController.h (100%) rename ChartsDemo/{Classes => Objective-C}/Demos/NegativeStackedBarChartViewController.m (100%) rename ChartsDemo/{Classes => Objective-C}/Demos/PieChartViewController.h (100%) rename ChartsDemo/{Classes => Objective-C}/Demos/PieChartViewController.m (100%) rename ChartsDemo/{Classes => Objective-C}/Demos/PiePolylineChartViewController.h (100%) rename ChartsDemo/{Classes => Objective-C}/Demos/PiePolylineChartViewController.m (100%) rename ChartsDemo/{Classes => Objective-C}/Demos/PositiveNegativeBarChartViewController.h (100%) rename ChartsDemo/{Classes => Objective-C}/Demos/PositiveNegativeBarChartViewController.m (100%) rename ChartsDemo/{Classes => Objective-C}/Demos/RadarChartViewController.h (100%) rename ChartsDemo/{Classes => Objective-C}/Demos/RadarChartViewController.m (100%) rename ChartsDemo/{Classes => Objective-C}/Demos/ScatterChartViewController.h (100%) rename ChartsDemo/{Classes => Objective-C}/Demos/ScatterChartViewController.m (100%) rename ChartsDemo/{Classes => Objective-C}/Demos/SinusBarChartViewController.h (100%) rename ChartsDemo/{Classes => Objective-C}/Demos/SinusBarChartViewController.m (100%) rename ChartsDemo/{Classes => Objective-C}/Demos/StackedBarChartViewController.h (100%) rename ChartsDemo/{Classes => Objective-C}/Demos/StackedBarChartViewController.m (100%) rename ChartsDemo/{Classes => Objective-C}/Formatters/DateValueFormatter.h (100%) rename ChartsDemo/{Classes => Objective-C}/Formatters/DateValueFormatter.m (100%) rename ChartsDemo/{Classes => Objective-C}/Formatters/DayAxisValueFormatter.h (100%) rename ChartsDemo/{Classes => Objective-C}/Formatters/DayAxisValueFormatter.m (100%) rename ChartsDemo/{Classes => Objective-C}/Formatters/IntAxisValueFormatter.h (100%) rename ChartsDemo/{Classes => Objective-C}/Formatters/IntAxisValueFormatter.m (100%) rename ChartsDemo/{Classes => Objective-C}/Formatters/LargeValueFormatter.swift (100%) rename ChartsDemo/{Classes => XIBs}/DemoListViewController.xib (100%) rename ChartsDemo/{Classes => XIBs}/Demos/AnotherBarChartViewController.xib (100%) rename ChartsDemo/{Classes => XIBs}/Demos/BarChartViewController.xib (100%) rename ChartsDemo/{Classes => XIBs}/Demos/BubbleChartViewController.xib (100%) rename ChartsDemo/{Classes => XIBs}/Demos/CandleStickChartViewController.xib (100%) rename ChartsDemo/{Classes => XIBs}/Demos/ColoredLineChartViewController.xib (100%) rename ChartsDemo/{Classes => XIBs}/Demos/CombinedChartViewController.xib (100%) rename ChartsDemo/{Classes => XIBs}/Demos/CubicLineChartViewController.xib (100%) rename ChartsDemo/{Classes => XIBs}/Demos/HalfPieChartViewController.xib (100%) rename ChartsDemo/{Classes => XIBs}/Demos/HorizontalBarChartViewController.xib (100%) rename ChartsDemo/{Classes => XIBs}/Demos/LineChart1ViewController.xib (100%) rename ChartsDemo/{Classes => XIBs}/Demos/LineChart2ViewController.xib (100%) rename ChartsDemo/{Classes => XIBs}/Demos/LineChartFilledViewController.xib (100%) rename ChartsDemo/{Classes => XIBs}/Demos/LineChartTimeViewController.xib (100%) rename ChartsDemo/{Classes => XIBs}/Demos/MultipleBarChartViewController.xib (100%) rename ChartsDemo/{Classes => XIBs}/Demos/MultipleLinesChartViewController.xib (100%) rename ChartsDemo/{Classes => XIBs}/Demos/NegativeStackedBarChartViewController.xib (100%) rename ChartsDemo/{Classes => XIBs}/Demos/PieChartViewController.xib (100%) rename ChartsDemo/{Classes => XIBs}/Demos/PiePolylineChartViewController.xib (100%) rename ChartsDemo/{Classes => XIBs}/Demos/PositiveNegativeBarChartViewController.xib (100%) rename ChartsDemo/{Classes => XIBs}/Demos/RadarChartViewController.xib (100%) rename ChartsDemo/{Classes => XIBs/Demos}/RealmDemosViewController.xib (100%) rename ChartsDemo/{Classes => XIBs}/Demos/ScatterChartViewController.xib (100%) rename ChartsDemo/{Classes => XIBs}/Demos/SinusBarChartViewController.xib (100%) rename ChartsDemo/{Classes => XIBs}/Demos/StackedBarChartViewController.xib (88%) rename ChartsDemo/{Classes/Components => XIBs}/RadarMarkerView.xib (100%) diff --git a/ChartsDemo/ChartsDemo.xcodeproj/project.pbxproj b/ChartsDemo/ChartsDemo.xcodeproj/project.pbxproj index aa78a57d11..b4a36b455d 100644 --- a/ChartsDemo/ChartsDemo.xcodeproj/project.pbxproj +++ b/ChartsDemo/ChartsDemo.xcodeproj/project.pbxproj @@ -15,7 +15,6 @@ 55E356511ADC638F00A57971 /* BubbleChartViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 55E3564F1ADC638F00A57971 /* BubbleChartViewController.m */; }; 5B0CC7851ABB875400665592 /* PieChartViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B0CC7831ABB875400665592 /* PieChartViewController.m */; }; 5B0CC7861ABB875400665592 /* PieChartViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5B0CC7841ABB875400665592 /* PieChartViewController.xib */; }; - 5B1B5DAA1E911A15006D1375 /* RealmDemosViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B1B5DA81E911A15006D1375 /* RealmDemosViewController.m */; }; 5B1B5DAB1E911A15006D1375 /* RealmDemosViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5B1B5DA91E911A15006D1375 /* RealmDemosViewController.xib */; }; 5B4316271AB8D8AE0009FCAA /* Icon-29@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 5B43161F1AB8D8AE0009FCAA /* Icon-29@2x.png */; }; 5B4316281AB8D8AE0009FCAA /* Icon-29@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 5B4316201AB8D8AE0009FCAA /* Icon-29@3x.png */; }; @@ -136,9 +135,7 @@ 5B0CC7821ABB875400665592 /* PieChartViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PieChartViewController.h; sourceTree = ""; }; 5B0CC7831ABB875400665592 /* PieChartViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PieChartViewController.m; sourceTree = ""; }; 5B0CC7841ABB875400665592 /* PieChartViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = PieChartViewController.xib; sourceTree = ""; }; - 5B1B5DA71E911A15006D1375 /* RealmDemosViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RealmDemosViewController.h; path = Classes/RealmDemosViewController.h; sourceTree = SOURCE_ROOT; }; - 5B1B5DA81E911A15006D1375 /* RealmDemosViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RealmDemosViewController.m; path = Classes/RealmDemosViewController.m; sourceTree = SOURCE_ROOT; }; - 5B1B5DA91E911A15006D1375 /* RealmDemosViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = RealmDemosViewController.xib; path = Classes/RealmDemosViewController.xib; sourceTree = SOURCE_ROOT; }; + 5B1B5DA91E911A15006D1375 /* RealmDemosViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = RealmDemosViewController.xib; path = XIBs/Demos/RealmDemosViewController.xib; sourceTree = SOURCE_ROOT; }; 5B43161F1AB8D8AE0009FCAA /* Icon-29@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-29@2x.png"; sourceTree = ""; }; 5B4316201AB8D8AE0009FCAA /* Icon-29@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-29@3x.png"; sourceTree = ""; }; 5B4316211AB8D8AE0009FCAA /* Icon-40@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-40@2x.png"; sourceTree = ""; }; @@ -258,6 +255,47 @@ name = Products; sourceTree = ""; }; + 227136F41F6EB665006D2A11 /* XIBs */ = { + isa = PBXGroup; + children = ( + 5B8EAF231AB3271B009697AA /* DemoListViewController.xib */, + 5B613DB41D526EA8000F1E98 /* RadarMarkerView.xib */, + 227136F61F6EB69D006D2A11 /* Demos */, + ); + path = XIBs; + sourceTree = ""; + }; + 227136F61F6EB69D006D2A11 /* Demos */ = { + isa = PBXGroup; + children = ( + 5BEAED111ABBFB2B0013F194 /* AnotherBarChartViewController.xib */, + 5BD47E641ABB424E008FCEC6 /* BarChartViewController.xib */, + 55E3564D1ADC638F00A57971 /* BubbleChartViewController.xib */, + 5BEAED2B1ABC160F0013F194 /* CandleStickChartViewController.xib */, + 5BEAED3A1ABC199F0013F194 /* ColoredLineChartViewController.xib */, + 5BDEDC461ABB871E007D3A60 /* CombinedChartViewController.xib */, + 5BEAED301ABC18F00013F194 /* CubicLineChartViewController.xib */, + 5BE6737F1D5B496500A87BA2 /* HalfPieChartViewController.xib */, + 5BDEDC401ABB7F73007D3A60 /* HorizontalBarChartViewController.xib */, + 5BD8F0731AB89CE500566E05 /* LineChart1ViewController.xib */, + 5BD47E5F1ABB3C91008FCEC6 /* LineChart2ViewController.xib */, + 5BE6738E1D5B4E0900A87BA2 /* LineChartFilledViewController.xib */, + 5BE673911D5B4E0900A87BA2 /* LineChartTimeViewController.xib */, + 5BEAED211ABC0BE20013F194 /* MultipleBarChartViewController.xib */, + 5BEAED241ABC0BE20013F194 /* MultipleLinesChartViewController.xib */, + 5B9624401B38608C007763E2 /* NegativeStackedBarChartViewController.xib */, + 5B0CC7841ABB875400665592 /* PieChartViewController.xib */, + 0471CBFB1CA1090A00E52DBC /* PiePolylineChartViewController.xib */, + 5BE7E7611C693098000A0377 /* PositiveNegativeBarChartViewController.xib */, + 5BEAED351ABC192F0013F194 /* RadarChartViewController.xib */, + 5B1B5DA91E911A15006D1375 /* RealmDemosViewController.xib */, + 5BEAED171ABBFB340013F194 /* ScatterChartViewController.xib */, + 5BEAED3F1ABC1AC60013F194 /* SinusBarChartViewController.xib */, + 5BEAED1A1ABBFB340013F194 /* StackedBarChartViewController.xib */, + ); + path = Demos; + sourceTree = ""; + }; 5B43161E1AB8D8AE0009FCAA /* app-icon */ = { isa = PBXGroup; children = ( @@ -288,7 +326,8 @@ isa = PBXGroup; children = ( 066750AC1E2DB68D00E22DC6 /* Carthage.xcconfig */, - 5B57BBB11A9B26AA0036A6CC /* Classes */, + 5B57BBB11A9B26AA0036A6CC /* Objective-C */, + 227136F41F6EB665006D2A11 /* XIBs */, 5B8EAF2E1AB32E15009697AA /* Resources */, 5B57BBB21A9B26AA0036A6CC /* Supporting Files */, 5B57BBB01A9B26AA0036A6CC /* Products */, @@ -304,21 +343,20 @@ name = Products; sourceTree = ""; }; - 5B57BBB11A9B26AA0036A6CC /* Classes */ = { + 5B57BBB11A9B26AA0036A6CC /* Objective-C */ = { isa = PBXGroup; children = ( 5B57BBB61A9B26AA0036A6CC /* AppDelegate.h */, 5B57BBB71A9B26AA0036A6CC /* AppDelegate.m */, 5B57BBB91A9B26AA0036A6CC /* DemoListViewController.h */, 5B57BBBA1A9B26AA0036A6CC /* DemoListViewController.m */, - 5B8EAF231AB3271B009697AA /* DemoListViewController.xib */, 5B8EAF251AB32CF5009697AA /* DemoBaseViewController.h */, 5B8EAF261AB32CF5009697AA /* DemoBaseViewController.m */, 5BE377D41D42511A006EB34F /* Formatters */, 5BD47E541ABB0177008FCEC6 /* Components */, 5BD8F06F1AB89C7100566E05 /* Demos */, ); - path = Classes; + path = "Objective-C"; sourceTree = ""; }; 5B57BBB21A9B26AA0036A6CC /* Supporting Files */ = { @@ -355,7 +393,6 @@ children = ( 5BD47E5A1ABB0263008FCEC6 /* BalloonMarker.swift */, 5B613DB21D526DED000F1E98 /* RadarMarkerView.swift */, - 5B613DB41D526EA8000F1E98 /* RadarMarkerView.xib */, 5B613DEF1D5A50B6000F1E98 /* XYMarkerView.swift */, ); path = Components; @@ -366,76 +403,50 @@ children = ( 5BEAED0F1ABBFB2B0013F194 /* AnotherBarChartViewController.h */, 5BEAED101ABBFB2B0013F194 /* AnotherBarChartViewController.m */, - 5BEAED111ABBFB2B0013F194 /* AnotherBarChartViewController.xib */, 5BD47E621ABB424E008FCEC6 /* BarChartViewController.h */, 5BD47E631ABB424E008FCEC6 /* BarChartViewController.m */, - 5BD47E641ABB424E008FCEC6 /* BarChartViewController.xib */, 55E3564E1ADC638F00A57971 /* BubbleChartViewController.h */, 55E3564F1ADC638F00A57971 /* BubbleChartViewController.m */, - 55E3564D1ADC638F00A57971 /* BubbleChartViewController.xib */, 5BEAED291ABC160F0013F194 /* CandleStickChartViewController.h */, 5BEAED2A1ABC160F0013F194 /* CandleStickChartViewController.m */, - 5BEAED2B1ABC160F0013F194 /* CandleStickChartViewController.xib */, 5BEAED381ABC199F0013F194 /* ColoredLineChartViewController.h */, 5BEAED391ABC199F0013F194 /* ColoredLineChartViewController.m */, - 5BEAED3A1ABC199F0013F194 /* ColoredLineChartViewController.xib */, 5BDEDC441ABB871E007D3A60 /* CombinedChartViewController.h */, 5BDEDC451ABB871E007D3A60 /* CombinedChartViewController.m */, - 5BDEDC461ABB871E007D3A60 /* CombinedChartViewController.xib */, 5BEAED2E1ABC18F00013F194 /* CubicLineChartViewController.h */, 5BEAED2F1ABC18F00013F194 /* CubicLineChartViewController.m */, - 5BEAED301ABC18F00013F194 /* CubicLineChartViewController.xib */, 5BE6737D1D5B496500A87BA2 /* HalfPieChartViewController.h */, 5BE6737E1D5B496500A87BA2 /* HalfPieChartViewController.m */, - 5BE6737F1D5B496500A87BA2 /* HalfPieChartViewController.xib */, 5BDEDC3E1ABB7F73007D3A60 /* HorizontalBarChartViewController.h */, 5BDEDC3F1ABB7F73007D3A60 /* HorizontalBarChartViewController.m */, - 5BDEDC401ABB7F73007D3A60 /* HorizontalBarChartViewController.xib */, 5BD8F0711AB89CE500566E05 /* LineChart1ViewController.h */, 5BD8F0721AB89CE500566E05 /* LineChart1ViewController.m */, - 5BD8F0731AB89CE500566E05 /* LineChart1ViewController.xib */, 5BD47E5D1ABB3C91008FCEC6 /* LineChart2ViewController.h */, 5BD47E5E1ABB3C91008FCEC6 /* LineChart2ViewController.m */, - 5BD47E5F1ABB3C91008FCEC6 /* LineChart2ViewController.xib */, 5BE6738C1D5B4E0900A87BA2 /* LineChartFilledViewController.h */, 5BE6738D1D5B4E0900A87BA2 /* LineChartFilledViewController.m */, - 5BE6738E1D5B4E0900A87BA2 /* LineChartFilledViewController.xib */, 5BE6738F1D5B4E0900A87BA2 /* LineChartTimeViewController.h */, 5BE673901D5B4E0900A87BA2 /* LineChartTimeViewController.m */, - 5BE673911D5B4E0900A87BA2 /* LineChartTimeViewController.xib */, 5BEAED1F1ABC0BE20013F194 /* MultipleBarChartViewController.h */, 5BEAED201ABC0BE20013F194 /* MultipleBarChartViewController.m */, - 5BEAED211ABC0BE20013F194 /* MultipleBarChartViewController.xib */, 5BEAED221ABC0BE20013F194 /* MultipleLinesChartViewController.h */, 5BEAED231ABC0BE20013F194 /* MultipleLinesChartViewController.m */, - 5BEAED241ABC0BE20013F194 /* MultipleLinesChartViewController.xib */, 5B96243E1B38608C007763E2 /* NegativeStackedBarChartViewController.h */, 5B96243F1B38608C007763E2 /* NegativeStackedBarChartViewController.m */, - 5B9624401B38608C007763E2 /* NegativeStackedBarChartViewController.xib */, 5B0CC7821ABB875400665592 /* PieChartViewController.h */, 5B0CC7831ABB875400665592 /* PieChartViewController.m */, - 5B0CC7841ABB875400665592 /* PieChartViewController.xib */, 0439A3511C9FF95F00496F83 /* PiePolylineChartViewController.h */, 0439A3521C9FF95F00496F83 /* PiePolylineChartViewController.m */, - 0471CBFB1CA1090A00E52DBC /* PiePolylineChartViewController.xib */, 5BE7E75F1C693098000A0377 /* PositiveNegativeBarChartViewController.h */, 5BE7E7601C693098000A0377 /* PositiveNegativeBarChartViewController.m */, - 5BE7E7611C693098000A0377 /* PositiveNegativeBarChartViewController.xib */, 5BEAED331ABC192F0013F194 /* RadarChartViewController.h */, 5BEAED341ABC192F0013F194 /* RadarChartViewController.m */, - 5BEAED351ABC192F0013F194 /* RadarChartViewController.xib */, - 5B1B5DA71E911A15006D1375 /* RealmDemosViewController.h */, - 5B1B5DA81E911A15006D1375 /* RealmDemosViewController.m */, - 5B1B5DA91E911A15006D1375 /* RealmDemosViewController.xib */, 5BEAED151ABBFB340013F194 /* ScatterChartViewController.h */, 5BEAED161ABBFB340013F194 /* ScatterChartViewController.m */, - 5BEAED171ABBFB340013F194 /* ScatterChartViewController.xib */, 5BEAED3D1ABC1AC60013F194 /* SinusBarChartViewController.h */, 5BEAED3E1ABC1AC60013F194 /* SinusBarChartViewController.m */, - 5BEAED3F1ABC1AC60013F194 /* SinusBarChartViewController.xib */, 5BEAED181ABBFB340013F194 /* StackedBarChartViewController.h */, 5BEAED191ABBFB340013F194 /* StackedBarChartViewController.m */, - 5BEAED1A1ABBFB340013F194 /* StackedBarChartViewController.xib */, ); path = Demos; sourceTree = ""; @@ -590,7 +601,6 @@ buildActionMask = 2147483647; files = ( 5B613DF21D5A60DF000F1E98 /* LargeValueFormatter.swift in Sources */, - 5B1B5DAA1E911A15006D1375 /* RealmDemosViewController.m in Sources */, 5BEAED1B1ABBFB340013F194 /* ScatterChartViewController.m in Sources */, 5B0CC7851ABB875400665592 /* PieChartViewController.m in Sources */, 0439A3541C9FF95F00496F83 /* PiePolylineChartViewController.m in Sources */, diff --git a/ChartsDemo/Classes/RealmDemosViewController.h b/ChartsDemo/Classes/RealmDemosViewController.h deleted file mode 100644 index d73426e995..0000000000 --- a/ChartsDemo/Classes/RealmDemosViewController.h +++ /dev/null @@ -1,18 +0,0 @@ -// -// RealmDemosViewController.h -// ChartsDemo -// -// 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 -#import "DemoBaseViewController.h" -#import - -@interface RealmDemosViewController : DemoBaseViewController - -@end diff --git a/ChartsDemo/Classes/RealmDemosViewController.m b/ChartsDemo/Classes/RealmDemosViewController.m deleted file mode 100644 index 52b7811661..0000000000 --- a/ChartsDemo/Classes/RealmDemosViewController.m +++ /dev/null @@ -1,35 +0,0 @@ -// -// RealmDemosViewController.m -// ChartsDemo -// -// 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 "RealmDemosViewController.h" -#import "ChartsDemo-Swift.h" - -@interface RealmDemosViewController () - -@end - -@implementation RealmDemosViewController - -- (void)viewDidLoad -{ - [super viewDidLoad]; - - self.title = @"Realm demos"; - -} - -- (void)didReceiveMemoryWarning -{ - [super didReceiveMemoryWarning]; - // Dispose of any resources that can be recreated. -} - -@end diff --git a/ChartsDemo/Classes/AppDelegate.h b/ChartsDemo/Objective-C/AppDelegate.h similarity index 100% rename from ChartsDemo/Classes/AppDelegate.h rename to ChartsDemo/Objective-C/AppDelegate.h diff --git a/ChartsDemo/Classes/AppDelegate.m b/ChartsDemo/Objective-C/AppDelegate.m similarity index 100% rename from ChartsDemo/Classes/AppDelegate.m rename to ChartsDemo/Objective-C/AppDelegate.m diff --git a/ChartsDemo/Classes/Components/BalloonMarker.swift b/ChartsDemo/Objective-C/Components/BalloonMarker.swift similarity index 100% rename from ChartsDemo/Classes/Components/BalloonMarker.swift rename to ChartsDemo/Objective-C/Components/BalloonMarker.swift diff --git a/ChartsDemo/Classes/Components/RadarMarkerView.swift b/ChartsDemo/Objective-C/Components/RadarMarkerView.swift similarity index 100% rename from ChartsDemo/Classes/Components/RadarMarkerView.swift rename to ChartsDemo/Objective-C/Components/RadarMarkerView.swift diff --git a/ChartsDemo/Classes/Components/XYMarkerView.swift b/ChartsDemo/Objective-C/Components/XYMarkerView.swift similarity index 100% rename from ChartsDemo/Classes/Components/XYMarkerView.swift rename to ChartsDemo/Objective-C/Components/XYMarkerView.swift diff --git a/ChartsDemo/Classes/DemoBaseViewController.h b/ChartsDemo/Objective-C/DemoBaseViewController.h similarity index 100% rename from ChartsDemo/Classes/DemoBaseViewController.h rename to ChartsDemo/Objective-C/DemoBaseViewController.h diff --git a/ChartsDemo/Classes/DemoBaseViewController.m b/ChartsDemo/Objective-C/DemoBaseViewController.m similarity index 100% rename from ChartsDemo/Classes/DemoBaseViewController.m rename to ChartsDemo/Objective-C/DemoBaseViewController.m diff --git a/ChartsDemo/Classes/DemoListViewController.h b/ChartsDemo/Objective-C/DemoListViewController.h similarity index 100% rename from ChartsDemo/Classes/DemoListViewController.h rename to ChartsDemo/Objective-C/DemoListViewController.h diff --git a/ChartsDemo/Classes/DemoListViewController.m b/ChartsDemo/Objective-C/DemoListViewController.m similarity index 100% rename from ChartsDemo/Classes/DemoListViewController.m rename to ChartsDemo/Objective-C/DemoListViewController.m diff --git a/ChartsDemo/Classes/Demos/AnotherBarChartViewController.h b/ChartsDemo/Objective-C/Demos/AnotherBarChartViewController.h similarity index 100% rename from ChartsDemo/Classes/Demos/AnotherBarChartViewController.h rename to ChartsDemo/Objective-C/Demos/AnotherBarChartViewController.h diff --git a/ChartsDemo/Classes/Demos/AnotherBarChartViewController.m b/ChartsDemo/Objective-C/Demos/AnotherBarChartViewController.m similarity index 100% rename from ChartsDemo/Classes/Demos/AnotherBarChartViewController.m rename to ChartsDemo/Objective-C/Demos/AnotherBarChartViewController.m diff --git a/ChartsDemo/Classes/Demos/BarChartViewController.h b/ChartsDemo/Objective-C/Demos/BarChartViewController.h similarity index 100% rename from ChartsDemo/Classes/Demos/BarChartViewController.h rename to ChartsDemo/Objective-C/Demos/BarChartViewController.h diff --git a/ChartsDemo/Classes/Demos/BarChartViewController.m b/ChartsDemo/Objective-C/Demos/BarChartViewController.m similarity index 100% rename from ChartsDemo/Classes/Demos/BarChartViewController.m rename to ChartsDemo/Objective-C/Demos/BarChartViewController.m diff --git a/ChartsDemo/Classes/Demos/BubbleChartViewController.h b/ChartsDemo/Objective-C/Demos/BubbleChartViewController.h similarity index 100% rename from ChartsDemo/Classes/Demos/BubbleChartViewController.h rename to ChartsDemo/Objective-C/Demos/BubbleChartViewController.h diff --git a/ChartsDemo/Classes/Demos/BubbleChartViewController.m b/ChartsDemo/Objective-C/Demos/BubbleChartViewController.m similarity index 100% rename from ChartsDemo/Classes/Demos/BubbleChartViewController.m rename to ChartsDemo/Objective-C/Demos/BubbleChartViewController.m diff --git a/ChartsDemo/Classes/Demos/CandleStickChartViewController.h b/ChartsDemo/Objective-C/Demos/CandleStickChartViewController.h similarity index 100% rename from ChartsDemo/Classes/Demos/CandleStickChartViewController.h rename to ChartsDemo/Objective-C/Demos/CandleStickChartViewController.h diff --git a/ChartsDemo/Classes/Demos/CandleStickChartViewController.m b/ChartsDemo/Objective-C/Demos/CandleStickChartViewController.m similarity index 100% rename from ChartsDemo/Classes/Demos/CandleStickChartViewController.m rename to ChartsDemo/Objective-C/Demos/CandleStickChartViewController.m diff --git a/ChartsDemo/Classes/Demos/ColoredLineChartViewController.h b/ChartsDemo/Objective-C/Demos/ColoredLineChartViewController.h similarity index 100% rename from ChartsDemo/Classes/Demos/ColoredLineChartViewController.h rename to ChartsDemo/Objective-C/Demos/ColoredLineChartViewController.h diff --git a/ChartsDemo/Classes/Demos/ColoredLineChartViewController.m b/ChartsDemo/Objective-C/Demos/ColoredLineChartViewController.m similarity index 100% rename from ChartsDemo/Classes/Demos/ColoredLineChartViewController.m rename to ChartsDemo/Objective-C/Demos/ColoredLineChartViewController.m diff --git a/ChartsDemo/Classes/Demos/CombinedChartViewController.h b/ChartsDemo/Objective-C/Demos/CombinedChartViewController.h similarity index 100% rename from ChartsDemo/Classes/Demos/CombinedChartViewController.h rename to ChartsDemo/Objective-C/Demos/CombinedChartViewController.h diff --git a/ChartsDemo/Classes/Demos/CombinedChartViewController.m b/ChartsDemo/Objective-C/Demos/CombinedChartViewController.m similarity index 100% rename from ChartsDemo/Classes/Demos/CombinedChartViewController.m rename to ChartsDemo/Objective-C/Demos/CombinedChartViewController.m diff --git a/ChartsDemo/Classes/Demos/CubicLineChartViewController.h b/ChartsDemo/Objective-C/Demos/CubicLineChartViewController.h similarity index 100% rename from ChartsDemo/Classes/Demos/CubicLineChartViewController.h rename to ChartsDemo/Objective-C/Demos/CubicLineChartViewController.h diff --git a/ChartsDemo/Classes/Demos/CubicLineChartViewController.m b/ChartsDemo/Objective-C/Demos/CubicLineChartViewController.m similarity index 100% rename from ChartsDemo/Classes/Demos/CubicLineChartViewController.m rename to ChartsDemo/Objective-C/Demos/CubicLineChartViewController.m diff --git a/ChartsDemo/Classes/Demos/HalfPieChartViewController.h b/ChartsDemo/Objective-C/Demos/HalfPieChartViewController.h similarity index 100% rename from ChartsDemo/Classes/Demos/HalfPieChartViewController.h rename to ChartsDemo/Objective-C/Demos/HalfPieChartViewController.h diff --git a/ChartsDemo/Classes/Demos/HalfPieChartViewController.m b/ChartsDemo/Objective-C/Demos/HalfPieChartViewController.m similarity index 100% rename from ChartsDemo/Classes/Demos/HalfPieChartViewController.m rename to ChartsDemo/Objective-C/Demos/HalfPieChartViewController.m diff --git a/ChartsDemo/Classes/Demos/HorizontalBarChartViewController.h b/ChartsDemo/Objective-C/Demos/HorizontalBarChartViewController.h similarity index 100% rename from ChartsDemo/Classes/Demos/HorizontalBarChartViewController.h rename to ChartsDemo/Objective-C/Demos/HorizontalBarChartViewController.h diff --git a/ChartsDemo/Classes/Demos/HorizontalBarChartViewController.m b/ChartsDemo/Objective-C/Demos/HorizontalBarChartViewController.m similarity index 100% rename from ChartsDemo/Classes/Demos/HorizontalBarChartViewController.m rename to ChartsDemo/Objective-C/Demos/HorizontalBarChartViewController.m diff --git a/ChartsDemo/Classes/Demos/LineChart1ViewController.h b/ChartsDemo/Objective-C/Demos/LineChart1ViewController.h similarity index 100% rename from ChartsDemo/Classes/Demos/LineChart1ViewController.h rename to ChartsDemo/Objective-C/Demos/LineChart1ViewController.h diff --git a/ChartsDemo/Classes/Demos/LineChart1ViewController.m b/ChartsDemo/Objective-C/Demos/LineChart1ViewController.m similarity index 100% rename from ChartsDemo/Classes/Demos/LineChart1ViewController.m rename to ChartsDemo/Objective-C/Demos/LineChart1ViewController.m diff --git a/ChartsDemo/Classes/Demos/LineChart2ViewController.h b/ChartsDemo/Objective-C/Demos/LineChart2ViewController.h similarity index 100% rename from ChartsDemo/Classes/Demos/LineChart2ViewController.h rename to ChartsDemo/Objective-C/Demos/LineChart2ViewController.h diff --git a/ChartsDemo/Classes/Demos/LineChart2ViewController.m b/ChartsDemo/Objective-C/Demos/LineChart2ViewController.m similarity index 100% rename from ChartsDemo/Classes/Demos/LineChart2ViewController.m rename to ChartsDemo/Objective-C/Demos/LineChart2ViewController.m diff --git a/ChartsDemo/Classes/Demos/LineChartFilledViewController.h b/ChartsDemo/Objective-C/Demos/LineChartFilledViewController.h similarity index 100% rename from ChartsDemo/Classes/Demos/LineChartFilledViewController.h rename to ChartsDemo/Objective-C/Demos/LineChartFilledViewController.h diff --git a/ChartsDemo/Classes/Demos/LineChartFilledViewController.m b/ChartsDemo/Objective-C/Demos/LineChartFilledViewController.m similarity index 100% rename from ChartsDemo/Classes/Demos/LineChartFilledViewController.m rename to ChartsDemo/Objective-C/Demos/LineChartFilledViewController.m diff --git a/ChartsDemo/Classes/Demos/LineChartTimeViewController.h b/ChartsDemo/Objective-C/Demos/LineChartTimeViewController.h similarity index 100% rename from ChartsDemo/Classes/Demos/LineChartTimeViewController.h rename to ChartsDemo/Objective-C/Demos/LineChartTimeViewController.h diff --git a/ChartsDemo/Classes/Demos/LineChartTimeViewController.m b/ChartsDemo/Objective-C/Demos/LineChartTimeViewController.m similarity index 100% rename from ChartsDemo/Classes/Demos/LineChartTimeViewController.m rename to ChartsDemo/Objective-C/Demos/LineChartTimeViewController.m diff --git a/ChartsDemo/Classes/Demos/MultipleBarChartViewController.h b/ChartsDemo/Objective-C/Demos/MultipleBarChartViewController.h similarity index 100% rename from ChartsDemo/Classes/Demos/MultipleBarChartViewController.h rename to ChartsDemo/Objective-C/Demos/MultipleBarChartViewController.h diff --git a/ChartsDemo/Classes/Demos/MultipleBarChartViewController.m b/ChartsDemo/Objective-C/Demos/MultipleBarChartViewController.m similarity index 100% rename from ChartsDemo/Classes/Demos/MultipleBarChartViewController.m rename to ChartsDemo/Objective-C/Demos/MultipleBarChartViewController.m diff --git a/ChartsDemo/Classes/Demos/MultipleLinesChartViewController.h b/ChartsDemo/Objective-C/Demos/MultipleLinesChartViewController.h similarity index 100% rename from ChartsDemo/Classes/Demos/MultipleLinesChartViewController.h rename to ChartsDemo/Objective-C/Demos/MultipleLinesChartViewController.h diff --git a/ChartsDemo/Classes/Demos/MultipleLinesChartViewController.m b/ChartsDemo/Objective-C/Demos/MultipleLinesChartViewController.m similarity index 100% rename from ChartsDemo/Classes/Demos/MultipleLinesChartViewController.m rename to ChartsDemo/Objective-C/Demos/MultipleLinesChartViewController.m diff --git a/ChartsDemo/Classes/Demos/NegativeStackedBarChartViewController.h b/ChartsDemo/Objective-C/Demos/NegativeStackedBarChartViewController.h similarity index 100% rename from ChartsDemo/Classes/Demos/NegativeStackedBarChartViewController.h rename to ChartsDemo/Objective-C/Demos/NegativeStackedBarChartViewController.h diff --git a/ChartsDemo/Classes/Demos/NegativeStackedBarChartViewController.m b/ChartsDemo/Objective-C/Demos/NegativeStackedBarChartViewController.m similarity index 100% rename from ChartsDemo/Classes/Demos/NegativeStackedBarChartViewController.m rename to ChartsDemo/Objective-C/Demos/NegativeStackedBarChartViewController.m diff --git a/ChartsDemo/Classes/Demos/PieChartViewController.h b/ChartsDemo/Objective-C/Demos/PieChartViewController.h similarity index 100% rename from ChartsDemo/Classes/Demos/PieChartViewController.h rename to ChartsDemo/Objective-C/Demos/PieChartViewController.h diff --git a/ChartsDemo/Classes/Demos/PieChartViewController.m b/ChartsDemo/Objective-C/Demos/PieChartViewController.m similarity index 100% rename from ChartsDemo/Classes/Demos/PieChartViewController.m rename to ChartsDemo/Objective-C/Demos/PieChartViewController.m diff --git a/ChartsDemo/Classes/Demos/PiePolylineChartViewController.h b/ChartsDemo/Objective-C/Demos/PiePolylineChartViewController.h similarity index 100% rename from ChartsDemo/Classes/Demos/PiePolylineChartViewController.h rename to ChartsDemo/Objective-C/Demos/PiePolylineChartViewController.h diff --git a/ChartsDemo/Classes/Demos/PiePolylineChartViewController.m b/ChartsDemo/Objective-C/Demos/PiePolylineChartViewController.m similarity index 100% rename from ChartsDemo/Classes/Demos/PiePolylineChartViewController.m rename to ChartsDemo/Objective-C/Demos/PiePolylineChartViewController.m diff --git a/ChartsDemo/Classes/Demos/PositiveNegativeBarChartViewController.h b/ChartsDemo/Objective-C/Demos/PositiveNegativeBarChartViewController.h similarity index 100% rename from ChartsDemo/Classes/Demos/PositiveNegativeBarChartViewController.h rename to ChartsDemo/Objective-C/Demos/PositiveNegativeBarChartViewController.h diff --git a/ChartsDemo/Classes/Demos/PositiveNegativeBarChartViewController.m b/ChartsDemo/Objective-C/Demos/PositiveNegativeBarChartViewController.m similarity index 100% rename from ChartsDemo/Classes/Demos/PositiveNegativeBarChartViewController.m rename to ChartsDemo/Objective-C/Demos/PositiveNegativeBarChartViewController.m diff --git a/ChartsDemo/Classes/Demos/RadarChartViewController.h b/ChartsDemo/Objective-C/Demos/RadarChartViewController.h similarity index 100% rename from ChartsDemo/Classes/Demos/RadarChartViewController.h rename to ChartsDemo/Objective-C/Demos/RadarChartViewController.h diff --git a/ChartsDemo/Classes/Demos/RadarChartViewController.m b/ChartsDemo/Objective-C/Demos/RadarChartViewController.m similarity index 100% rename from ChartsDemo/Classes/Demos/RadarChartViewController.m rename to ChartsDemo/Objective-C/Demos/RadarChartViewController.m diff --git a/ChartsDemo/Classes/Demos/ScatterChartViewController.h b/ChartsDemo/Objective-C/Demos/ScatterChartViewController.h similarity index 100% rename from ChartsDemo/Classes/Demos/ScatterChartViewController.h rename to ChartsDemo/Objective-C/Demos/ScatterChartViewController.h diff --git a/ChartsDemo/Classes/Demos/ScatterChartViewController.m b/ChartsDemo/Objective-C/Demos/ScatterChartViewController.m similarity index 100% rename from ChartsDemo/Classes/Demos/ScatterChartViewController.m rename to ChartsDemo/Objective-C/Demos/ScatterChartViewController.m diff --git a/ChartsDemo/Classes/Demos/SinusBarChartViewController.h b/ChartsDemo/Objective-C/Demos/SinusBarChartViewController.h similarity index 100% rename from ChartsDemo/Classes/Demos/SinusBarChartViewController.h rename to ChartsDemo/Objective-C/Demos/SinusBarChartViewController.h diff --git a/ChartsDemo/Classes/Demos/SinusBarChartViewController.m b/ChartsDemo/Objective-C/Demos/SinusBarChartViewController.m similarity index 100% rename from ChartsDemo/Classes/Demos/SinusBarChartViewController.m rename to ChartsDemo/Objective-C/Demos/SinusBarChartViewController.m diff --git a/ChartsDemo/Classes/Demos/StackedBarChartViewController.h b/ChartsDemo/Objective-C/Demos/StackedBarChartViewController.h similarity index 100% rename from ChartsDemo/Classes/Demos/StackedBarChartViewController.h rename to ChartsDemo/Objective-C/Demos/StackedBarChartViewController.h diff --git a/ChartsDemo/Classes/Demos/StackedBarChartViewController.m b/ChartsDemo/Objective-C/Demos/StackedBarChartViewController.m similarity index 100% rename from ChartsDemo/Classes/Demos/StackedBarChartViewController.m rename to ChartsDemo/Objective-C/Demos/StackedBarChartViewController.m diff --git a/ChartsDemo/Classes/Formatters/DateValueFormatter.h b/ChartsDemo/Objective-C/Formatters/DateValueFormatter.h similarity index 100% rename from ChartsDemo/Classes/Formatters/DateValueFormatter.h rename to ChartsDemo/Objective-C/Formatters/DateValueFormatter.h diff --git a/ChartsDemo/Classes/Formatters/DateValueFormatter.m b/ChartsDemo/Objective-C/Formatters/DateValueFormatter.m similarity index 100% rename from ChartsDemo/Classes/Formatters/DateValueFormatter.m rename to ChartsDemo/Objective-C/Formatters/DateValueFormatter.m diff --git a/ChartsDemo/Classes/Formatters/DayAxisValueFormatter.h b/ChartsDemo/Objective-C/Formatters/DayAxisValueFormatter.h similarity index 100% rename from ChartsDemo/Classes/Formatters/DayAxisValueFormatter.h rename to ChartsDemo/Objective-C/Formatters/DayAxisValueFormatter.h diff --git a/ChartsDemo/Classes/Formatters/DayAxisValueFormatter.m b/ChartsDemo/Objective-C/Formatters/DayAxisValueFormatter.m similarity index 100% rename from ChartsDemo/Classes/Formatters/DayAxisValueFormatter.m rename to ChartsDemo/Objective-C/Formatters/DayAxisValueFormatter.m diff --git a/ChartsDemo/Classes/Formatters/IntAxisValueFormatter.h b/ChartsDemo/Objective-C/Formatters/IntAxisValueFormatter.h similarity index 100% rename from ChartsDemo/Classes/Formatters/IntAxisValueFormatter.h rename to ChartsDemo/Objective-C/Formatters/IntAxisValueFormatter.h diff --git a/ChartsDemo/Classes/Formatters/IntAxisValueFormatter.m b/ChartsDemo/Objective-C/Formatters/IntAxisValueFormatter.m similarity index 100% rename from ChartsDemo/Classes/Formatters/IntAxisValueFormatter.m rename to ChartsDemo/Objective-C/Formatters/IntAxisValueFormatter.m diff --git a/ChartsDemo/Classes/Formatters/LargeValueFormatter.swift b/ChartsDemo/Objective-C/Formatters/LargeValueFormatter.swift similarity index 100% rename from ChartsDemo/Classes/Formatters/LargeValueFormatter.swift rename to ChartsDemo/Objective-C/Formatters/LargeValueFormatter.swift diff --git a/ChartsDemo/Classes/DemoListViewController.xib b/ChartsDemo/XIBs/DemoListViewController.xib similarity index 100% rename from ChartsDemo/Classes/DemoListViewController.xib rename to ChartsDemo/XIBs/DemoListViewController.xib diff --git a/ChartsDemo/Classes/Demos/AnotherBarChartViewController.xib b/ChartsDemo/XIBs/Demos/AnotherBarChartViewController.xib similarity index 100% rename from ChartsDemo/Classes/Demos/AnotherBarChartViewController.xib rename to ChartsDemo/XIBs/Demos/AnotherBarChartViewController.xib diff --git a/ChartsDemo/Classes/Demos/BarChartViewController.xib b/ChartsDemo/XIBs/Demos/BarChartViewController.xib similarity index 100% rename from ChartsDemo/Classes/Demos/BarChartViewController.xib rename to ChartsDemo/XIBs/Demos/BarChartViewController.xib diff --git a/ChartsDemo/Classes/Demos/BubbleChartViewController.xib b/ChartsDemo/XIBs/Demos/BubbleChartViewController.xib similarity index 100% rename from ChartsDemo/Classes/Demos/BubbleChartViewController.xib rename to ChartsDemo/XIBs/Demos/BubbleChartViewController.xib diff --git a/ChartsDemo/Classes/Demos/CandleStickChartViewController.xib b/ChartsDemo/XIBs/Demos/CandleStickChartViewController.xib similarity index 100% rename from ChartsDemo/Classes/Demos/CandleStickChartViewController.xib rename to ChartsDemo/XIBs/Demos/CandleStickChartViewController.xib diff --git a/ChartsDemo/Classes/Demos/ColoredLineChartViewController.xib b/ChartsDemo/XIBs/Demos/ColoredLineChartViewController.xib similarity index 100% rename from ChartsDemo/Classes/Demos/ColoredLineChartViewController.xib rename to ChartsDemo/XIBs/Demos/ColoredLineChartViewController.xib diff --git a/ChartsDemo/Classes/Demos/CombinedChartViewController.xib b/ChartsDemo/XIBs/Demos/CombinedChartViewController.xib similarity index 100% rename from ChartsDemo/Classes/Demos/CombinedChartViewController.xib rename to ChartsDemo/XIBs/Demos/CombinedChartViewController.xib diff --git a/ChartsDemo/Classes/Demos/CubicLineChartViewController.xib b/ChartsDemo/XIBs/Demos/CubicLineChartViewController.xib similarity index 100% rename from ChartsDemo/Classes/Demos/CubicLineChartViewController.xib rename to ChartsDemo/XIBs/Demos/CubicLineChartViewController.xib diff --git a/ChartsDemo/Classes/Demos/HalfPieChartViewController.xib b/ChartsDemo/XIBs/Demos/HalfPieChartViewController.xib similarity index 100% rename from ChartsDemo/Classes/Demos/HalfPieChartViewController.xib rename to ChartsDemo/XIBs/Demos/HalfPieChartViewController.xib diff --git a/ChartsDemo/Classes/Demos/HorizontalBarChartViewController.xib b/ChartsDemo/XIBs/Demos/HorizontalBarChartViewController.xib similarity index 100% rename from ChartsDemo/Classes/Demos/HorizontalBarChartViewController.xib rename to ChartsDemo/XIBs/Demos/HorizontalBarChartViewController.xib diff --git a/ChartsDemo/Classes/Demos/LineChart1ViewController.xib b/ChartsDemo/XIBs/Demos/LineChart1ViewController.xib similarity index 100% rename from ChartsDemo/Classes/Demos/LineChart1ViewController.xib rename to ChartsDemo/XIBs/Demos/LineChart1ViewController.xib diff --git a/ChartsDemo/Classes/Demos/LineChart2ViewController.xib b/ChartsDemo/XIBs/Demos/LineChart2ViewController.xib similarity index 100% rename from ChartsDemo/Classes/Demos/LineChart2ViewController.xib rename to ChartsDemo/XIBs/Demos/LineChart2ViewController.xib diff --git a/ChartsDemo/Classes/Demos/LineChartFilledViewController.xib b/ChartsDemo/XIBs/Demos/LineChartFilledViewController.xib similarity index 100% rename from ChartsDemo/Classes/Demos/LineChartFilledViewController.xib rename to ChartsDemo/XIBs/Demos/LineChartFilledViewController.xib diff --git a/ChartsDemo/Classes/Demos/LineChartTimeViewController.xib b/ChartsDemo/XIBs/Demos/LineChartTimeViewController.xib similarity index 100% rename from ChartsDemo/Classes/Demos/LineChartTimeViewController.xib rename to ChartsDemo/XIBs/Demos/LineChartTimeViewController.xib diff --git a/ChartsDemo/Classes/Demos/MultipleBarChartViewController.xib b/ChartsDemo/XIBs/Demos/MultipleBarChartViewController.xib similarity index 100% rename from ChartsDemo/Classes/Demos/MultipleBarChartViewController.xib rename to ChartsDemo/XIBs/Demos/MultipleBarChartViewController.xib diff --git a/ChartsDemo/Classes/Demos/MultipleLinesChartViewController.xib b/ChartsDemo/XIBs/Demos/MultipleLinesChartViewController.xib similarity index 100% rename from ChartsDemo/Classes/Demos/MultipleLinesChartViewController.xib rename to ChartsDemo/XIBs/Demos/MultipleLinesChartViewController.xib diff --git a/ChartsDemo/Classes/Demos/NegativeStackedBarChartViewController.xib b/ChartsDemo/XIBs/Demos/NegativeStackedBarChartViewController.xib similarity index 100% rename from ChartsDemo/Classes/Demos/NegativeStackedBarChartViewController.xib rename to ChartsDemo/XIBs/Demos/NegativeStackedBarChartViewController.xib diff --git a/ChartsDemo/Classes/Demos/PieChartViewController.xib b/ChartsDemo/XIBs/Demos/PieChartViewController.xib similarity index 100% rename from ChartsDemo/Classes/Demos/PieChartViewController.xib rename to ChartsDemo/XIBs/Demos/PieChartViewController.xib diff --git a/ChartsDemo/Classes/Demos/PiePolylineChartViewController.xib b/ChartsDemo/XIBs/Demos/PiePolylineChartViewController.xib similarity index 100% rename from ChartsDemo/Classes/Demos/PiePolylineChartViewController.xib rename to ChartsDemo/XIBs/Demos/PiePolylineChartViewController.xib diff --git a/ChartsDemo/Classes/Demos/PositiveNegativeBarChartViewController.xib b/ChartsDemo/XIBs/Demos/PositiveNegativeBarChartViewController.xib similarity index 100% rename from ChartsDemo/Classes/Demos/PositiveNegativeBarChartViewController.xib rename to ChartsDemo/XIBs/Demos/PositiveNegativeBarChartViewController.xib diff --git a/ChartsDemo/Classes/Demos/RadarChartViewController.xib b/ChartsDemo/XIBs/Demos/RadarChartViewController.xib similarity index 100% rename from ChartsDemo/Classes/Demos/RadarChartViewController.xib rename to ChartsDemo/XIBs/Demos/RadarChartViewController.xib diff --git a/ChartsDemo/Classes/RealmDemosViewController.xib b/ChartsDemo/XIBs/Demos/RealmDemosViewController.xib similarity index 100% rename from ChartsDemo/Classes/RealmDemosViewController.xib rename to ChartsDemo/XIBs/Demos/RealmDemosViewController.xib diff --git a/ChartsDemo/Classes/Demos/ScatterChartViewController.xib b/ChartsDemo/XIBs/Demos/ScatterChartViewController.xib similarity index 100% rename from ChartsDemo/Classes/Demos/ScatterChartViewController.xib rename to ChartsDemo/XIBs/Demos/ScatterChartViewController.xib diff --git a/ChartsDemo/Classes/Demos/SinusBarChartViewController.xib b/ChartsDemo/XIBs/Demos/SinusBarChartViewController.xib similarity index 100% rename from ChartsDemo/Classes/Demos/SinusBarChartViewController.xib rename to ChartsDemo/XIBs/Demos/SinusBarChartViewController.xib diff --git a/ChartsDemo/Classes/Demos/StackedBarChartViewController.xib b/ChartsDemo/XIBs/Demos/StackedBarChartViewController.xib similarity index 88% rename from ChartsDemo/Classes/Demos/StackedBarChartViewController.xib rename to ChartsDemo/XIBs/Demos/StackedBarChartViewController.xib index c61b6170ca..7473b3ffa7 100644 --- a/ChartsDemo/Classes/Demos/StackedBarChartViewController.xib +++ b/ChartsDemo/XIBs/Demos/StackedBarChartViewController.xib @@ -1,10 +1,18 @@ - - + + + + + - + + + + HelveticaNeue-Light + + @@ -22,6 +30,7 @@ + + + + @@ -53,6 +66,7 @@ + diff --git a/ChartsDemo/Classes/Components/RadarMarkerView.xib b/ChartsDemo/XIBs/RadarMarkerView.xib similarity index 100% rename from ChartsDemo/Classes/Components/RadarMarkerView.xib rename to ChartsDemo/XIBs/RadarMarkerView.xib From 7fdad5e930202e87ac51269f93e7c26578007f54 Mon Sep 17 00:00:00 2001 From: jacobchristie Date: Sun, 17 Sep 2017 11:30:54 -0400 Subject: [PATCH 4/6] Merged all iOS demos to one project with 2 targets --- .../ChartsDemo.xcodeproj/project.pbxproj | 369 +++++++++++++++++- .../AppIcon.appiconset/Contents.json | 5 + ChartsDemo/Swift/AppDelegate.swift | 54 +++ .../Swift/Components/BalloonMarker.swift | 122 ++++++ .../Swift/Components/RadarMarkerView.swift | 27 ++ .../Swift/Components/XYMarkerView.swift | 32 ++ ChartsDemo/Swift/DemoBaseViewController.swift | 362 +++++++++++++++++ ChartsDemo/Swift/DemoListViewController.swift | 129 ++++++ .../Demos/AnotherBarChartViewController.swift | 98 +++++ .../Swift/Demos/BarChartViewController.swift | 152 ++++++++ .../Demos/BubbleChartViewController.swift | 127 ++++++ .../CandleStickChartViewController.swift | 122 ++++++ .../ColoredLineChartViewController.swift | 77 ++++ .../Demos/CombinedChartViewController.swift | 233 +++++++++++ .../Demos/CubicLineChartViewController.swift | 155 ++++++++ .../Demos/HalfPieChartViewController.swift | 142 +++++++ .../HorizontalBarChartViewController.swift | 124 ++++++ .../Demos/LineChart1ViewController.swift | 187 +++++++++ .../Demos/LineChart2ViewController.swift | 200 ++++++++++ .../Demos/LineChartFilledViewController.swift | 117 ++++++ .../Demos/LineChartTimeViewController.swift | 161 ++++++++ .../MultipleBarChartViewController.swift | 154 ++++++++ .../MultipleLinesChartViewController.swift | 138 +++++++ ...egativeStackedBarChartViewController.swift | 132 +++++++ .../Swift/Demos/PieChartViewController.swift | 153 ++++++++ .../PiePolylineChartViewController.swift | 145 +++++++ ...sitiveNegativeBarChartViewController.swift | 120 ++++++ .../Demos/RadarChartViewController.swift | 203 ++++++++++ .../Demos/ScatterChartViewController.swift | 124 ++++++ .../Demos/SinusBarChartViewController.swift | 108 +++++ .../Demos/StackedBarChartViewController.swift | 125 ++++++ .../Swift/Formatters/DateValueFormatter.swift | 23 ++ .../Formatters/DayAxisValueFormatter.swift | 109 ++++++ .../Formatters/IntAxisValueFormatter.swift | 16 + .../Formatters/LargeValueFormatter.swift | 58 +++ ChartsDemo/XIBs/DemoListViewController.xib | 12 +- .../Demos/AnotherBarChartViewController.xib | 22 +- .../XIBs/Demos/BarChartViewController.xib | 22 +- .../XIBs/Demos/BubbleChartViewController.xib | 22 +- .../Demos/CandleStickChartViewController.xib | 22 +- .../Demos/ColoredLineChartViewController.xib | 23 +- .../Demos/CombinedChartViewController.xib | 18 +- .../Demos/CubicLineChartViewController.xib | 22 +- .../XIBs/Demos/HalfPieChartViewController.xib | 18 +- .../HorizontalBarChartViewController.xib | 22 +- .../XIBs/Demos/LineChart1ViewController.xib | 22 +- .../XIBs/Demos/LineChart2ViewController.xib | 22 +- .../Demos/LineChartFilledViewController.xib | 21 +- .../Demos/LineChartTimeViewController.xib | 20 +- .../Demos/MultipleBarChartViewController.xib | 11 +- .../MultipleLinesChartViewController.xib | 22 +- .../NegativeStackedBarChartViewController.xib | 18 +- .../XIBs/Demos/PieChartViewController.xib | 22 +- .../Demos/PiePolylineChartViewController.xib | 22 +- ...PositiveNegativeBarChartViewController.xib | 18 +- .../XIBs/Demos/RadarChartViewController.xib | 19 +- .../XIBs/Demos/RealmDemosViewController.xib | 11 +- .../XIBs/Demos/ScatterChartViewController.xib | 22 +- .../Demos/SinusBarChartViewController.xib | 20 +- .../Demos/StackedBarChartViewController.xib | 2 +- ChartsDemo/XIBs/RadarMarkerView.xib | 19 +- 61 files changed, 4990 insertions(+), 107 deletions(-) create mode 100644 ChartsDemo/Swift/AppDelegate.swift create mode 100644 ChartsDemo/Swift/Components/BalloonMarker.swift create mode 100644 ChartsDemo/Swift/Components/RadarMarkerView.swift create mode 100644 ChartsDemo/Swift/Components/XYMarkerView.swift create mode 100644 ChartsDemo/Swift/DemoBaseViewController.swift create mode 100644 ChartsDemo/Swift/DemoListViewController.swift create mode 100644 ChartsDemo/Swift/Demos/AnotherBarChartViewController.swift create mode 100644 ChartsDemo/Swift/Demos/BarChartViewController.swift create mode 100644 ChartsDemo/Swift/Demos/BubbleChartViewController.swift create mode 100644 ChartsDemo/Swift/Demos/CandleStickChartViewController.swift create mode 100644 ChartsDemo/Swift/Demos/ColoredLineChartViewController.swift create mode 100644 ChartsDemo/Swift/Demos/CombinedChartViewController.swift create mode 100644 ChartsDemo/Swift/Demos/CubicLineChartViewController.swift create mode 100644 ChartsDemo/Swift/Demos/HalfPieChartViewController.swift create mode 100644 ChartsDemo/Swift/Demos/HorizontalBarChartViewController.swift create mode 100644 ChartsDemo/Swift/Demos/LineChart1ViewController.swift create mode 100644 ChartsDemo/Swift/Demos/LineChart2ViewController.swift create mode 100644 ChartsDemo/Swift/Demos/LineChartFilledViewController.swift create mode 100644 ChartsDemo/Swift/Demos/LineChartTimeViewController.swift create mode 100644 ChartsDemo/Swift/Demos/MultipleBarChartViewController.swift create mode 100644 ChartsDemo/Swift/Demos/MultipleLinesChartViewController.swift create mode 100644 ChartsDemo/Swift/Demos/NegativeStackedBarChartViewController.swift create mode 100644 ChartsDemo/Swift/Demos/PieChartViewController.swift create mode 100644 ChartsDemo/Swift/Demos/PiePolylineChartViewController.swift create mode 100644 ChartsDemo/Swift/Demos/PositiveNegativeBarChartViewController.swift create mode 100644 ChartsDemo/Swift/Demos/RadarChartViewController.swift create mode 100644 ChartsDemo/Swift/Demos/ScatterChartViewController.swift create mode 100644 ChartsDemo/Swift/Demos/SinusBarChartViewController.swift create mode 100644 ChartsDemo/Swift/Demos/StackedBarChartViewController.swift create mode 100644 ChartsDemo/Swift/Formatters/DateValueFormatter.swift create mode 100644 ChartsDemo/Swift/Formatters/DayAxisValueFormatter.swift create mode 100644 ChartsDemo/Swift/Formatters/IntAxisValueFormatter.swift create mode 100644 ChartsDemo/Swift/Formatters/LargeValueFormatter.swift diff --git a/ChartsDemo/ChartsDemo.xcodeproj/project.pbxproj b/ChartsDemo/ChartsDemo.xcodeproj/project.pbxproj index b4a36b455d..64b2388bf5 100644 --- a/ChartsDemo/ChartsDemo.xcodeproj/project.pbxproj +++ b/ChartsDemo/ChartsDemo.xcodeproj/project.pbxproj @@ -11,6 +11,67 @@ 0471CBFC1CA1090A00E52DBC /* PiePolylineChartViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0471CBFB1CA1090A00E52DBC /* PiePolylineChartViewController.xib */; }; 0630AE511D81271B008859B0 /* Charts.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0630AE411D8126C0008859B0 /* Charts.framework */; }; 0630AE521D81271B008859B0 /* Charts.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 0630AE411D8126C0008859B0 /* Charts.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 225B36201F6EB9A50005B3D5 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 225B361F1F6EB9A50005B3D5 /* AppDelegate.swift */; }; + 225B36311F6EB9EE0005B3D5 /* DemoBaseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 225B362F1F6EB9EE0005B3D5 /* DemoBaseViewController.swift */; }; + 225B36321F6EB9EE0005B3D5 /* DemoListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 225B36301F6EB9EE0005B3D5 /* DemoListViewController.swift */; }; + 225B36381F6EBA040005B3D5 /* IntAxisValueFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 225B36341F6EB9FE0005B3D5 /* IntAxisValueFormatter.swift */; }; + 225B36391F6EBA040005B3D5 /* DayAxisValueFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 225B36351F6EB9FE0005B3D5 /* DayAxisValueFormatter.swift */; }; + 225B363A1F6EBA040005B3D5 /* DateValueFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 225B36361F6EB9FE0005B3D5 /* DateValueFormatter.swift */; }; + 225B363B1F6EBA040005B3D5 /* LargeValueFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 225B36371F6EB9FE0005B3D5 /* LargeValueFormatter.swift */; }; + 225B36401F6EBA1D0005B3D5 /* XYMarkerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 225B363D1F6EBA180005B3D5 /* XYMarkerView.swift */; }; + 225B36411F6EBA1D0005B3D5 /* BalloonMarker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 225B363E1F6EBA180005B3D5 /* BalloonMarker.swift */; }; + 225B36421F6EBA1D0005B3D5 /* RadarMarkerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 225B363F1F6EBA180005B3D5 /* RadarMarkerView.swift */; }; + 225B365B1F6EBA470005B3D5 /* MultipleLinesChartViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 225B36441F6EBA410005B3D5 /* MultipleLinesChartViewController.swift */; }; + 225B365C1F6EBA470005B3D5 /* MultipleBarChartViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 225B36451F6EBA410005B3D5 /* MultipleBarChartViewController.swift */; }; + 225B365D1F6EBA470005B3D5 /* HalfPieChartViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 225B36461F6EBA410005B3D5 /* HalfPieChartViewController.swift */; }; + 225B365E1F6EBA470005B3D5 /* LineChartTimeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 225B36471F6EBA410005B3D5 /* LineChartTimeViewController.swift */; }; + 225B365F1F6EBA470005B3D5 /* ColoredLineChartViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 225B36481F6EBA410005B3D5 /* ColoredLineChartViewController.swift */; }; + 225B36601F6EBA470005B3D5 /* LineChart2ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 225B36491F6EBA410005B3D5 /* LineChart2ViewController.swift */; }; + 225B36611F6EBA470005B3D5 /* LineChart1ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 225B364A1F6EBA410005B3D5 /* LineChart1ViewController.swift */; }; + 225B36621F6EBA470005B3D5 /* NegativeStackedBarChartViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 225B364B1F6EBA410005B3D5 /* NegativeStackedBarChartViewController.swift */; }; + 225B36631F6EBA470005B3D5 /* ScatterChartViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 225B364C1F6EBA410005B3D5 /* ScatterChartViewController.swift */; }; + 225B36641F6EBA470005B3D5 /* StackedBarChartViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 225B364D1F6EBA410005B3D5 /* StackedBarChartViewController.swift */; }; + 225B36651F6EBA470005B3D5 /* BubbleChartViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 225B364E1F6EBA410005B3D5 /* BubbleChartViewController.swift */; }; + 225B36661F6EBA470005B3D5 /* LineChartFilledViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 225B364F1F6EBA410005B3D5 /* LineChartFilledViewController.swift */; }; + 225B36671F6EBA470005B3D5 /* PositiveNegativeBarChartViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 225B36501F6EBA410005B3D5 /* PositiveNegativeBarChartViewController.swift */; }; + 225B36681F6EBA470005B3D5 /* AnotherBarChartViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 225B36511F6EBA410005B3D5 /* AnotherBarChartViewController.swift */; }; + 225B36691F6EBA470005B3D5 /* PieChartViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 225B36521F6EBA410005B3D5 /* PieChartViewController.swift */; }; + 225B366A1F6EBA470005B3D5 /* CubicLineChartViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 225B36531F6EBA410005B3D5 /* CubicLineChartViewController.swift */; }; + 225B366B1F6EBA470005B3D5 /* RadarChartViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 225B36541F6EBA410005B3D5 /* RadarChartViewController.swift */; }; + 225B366C1F6EBA470005B3D5 /* HorizontalBarChartViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 225B36551F6EBA410005B3D5 /* HorizontalBarChartViewController.swift */; }; + 225B366D1F6EBA470005B3D5 /* PiePolylineChartViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 225B36561F6EBA410005B3D5 /* PiePolylineChartViewController.swift */; }; + 225B366E1F6EBA470005B3D5 /* CombinedChartViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 225B36571F6EBA410005B3D5 /* CombinedChartViewController.swift */; }; + 225B366F1F6EBA470005B3D5 /* BarChartViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 225B36581F6EBA410005B3D5 /* BarChartViewController.swift */; }; + 225B36701F6EBA470005B3D5 /* SinusBarChartViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 225B36591F6EBA410005B3D5 /* SinusBarChartViewController.swift */; }; + 225B36711F6EBA470005B3D5 /* CandleStickChartViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 225B365A1F6EBA410005B3D5 /* CandleStickChartViewController.swift */; }; + 225B36721F6EBA5E0005B3D5 /* DemoListViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5B8EAF231AB3271B009697AA /* DemoListViewController.xib */; }; + 225B36731F6EBA5E0005B3D5 /* RadarMarkerView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5B613DB41D526EA8000F1E98 /* RadarMarkerView.xib */; }; + 225B36741F6EBA640005B3D5 /* AnotherBarChartViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5BEAED111ABBFB2B0013F194 /* AnotherBarChartViewController.xib */; }; + 225B36751F6EBA640005B3D5 /* BarChartViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5BD47E641ABB424E008FCEC6 /* BarChartViewController.xib */; }; + 225B36761F6EBA640005B3D5 /* BubbleChartViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 55E3564D1ADC638F00A57971 /* BubbleChartViewController.xib */; }; + 225B36771F6EBA640005B3D5 /* CandleStickChartViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5BEAED2B1ABC160F0013F194 /* CandleStickChartViewController.xib */; }; + 225B36781F6EBA640005B3D5 /* ColoredLineChartViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5BEAED3A1ABC199F0013F194 /* ColoredLineChartViewController.xib */; }; + 225B36791F6EBA640005B3D5 /* CombinedChartViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5BDEDC461ABB871E007D3A60 /* CombinedChartViewController.xib */; }; + 225B367A1F6EBA640005B3D5 /* CubicLineChartViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5BEAED301ABC18F00013F194 /* CubicLineChartViewController.xib */; }; + 225B367B1F6EBA640005B3D5 /* HalfPieChartViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5BE6737F1D5B496500A87BA2 /* HalfPieChartViewController.xib */; }; + 225B367C1F6EBA640005B3D5 /* HorizontalBarChartViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5BDEDC401ABB7F73007D3A60 /* HorizontalBarChartViewController.xib */; }; + 225B367D1F6EBA640005B3D5 /* LineChart1ViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5BD8F0731AB89CE500566E05 /* LineChart1ViewController.xib */; }; + 225B367E1F6EBA640005B3D5 /* LineChart2ViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5BD47E5F1ABB3C91008FCEC6 /* LineChart2ViewController.xib */; }; + 225B367F1F6EBA640005B3D5 /* LineChartFilledViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5BE6738E1D5B4E0900A87BA2 /* LineChartFilledViewController.xib */; }; + 225B36801F6EBA640005B3D5 /* LineChartTimeViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5BE673911D5B4E0900A87BA2 /* LineChartTimeViewController.xib */; }; + 225B36811F6EBA640005B3D5 /* MultipleBarChartViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5BEAED211ABC0BE20013F194 /* MultipleBarChartViewController.xib */; }; + 225B36821F6EBA640005B3D5 /* MultipleLinesChartViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5BEAED241ABC0BE20013F194 /* MultipleLinesChartViewController.xib */; }; + 225B36831F6EBA640005B3D5 /* NegativeStackedBarChartViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5B9624401B38608C007763E2 /* NegativeStackedBarChartViewController.xib */; }; + 225B36841F6EBA640005B3D5 /* PieChartViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5B0CC7841ABB875400665592 /* PieChartViewController.xib */; }; + 225B36851F6EBA640005B3D5 /* PiePolylineChartViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0471CBFB1CA1090A00E52DBC /* PiePolylineChartViewController.xib */; }; + 225B36861F6EBA640005B3D5 /* PositiveNegativeBarChartViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5BE7E7611C693098000A0377 /* PositiveNegativeBarChartViewController.xib */; }; + 225B36871F6EBA640005B3D5 /* RadarChartViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5BEAED351ABC192F0013F194 /* RadarChartViewController.xib */; }; + 225B36881F6EBA640005B3D5 /* RealmDemosViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5B1B5DA91E911A15006D1375 /* RealmDemosViewController.xib */; }; + 225B36891F6EBA640005B3D5 /* ScatterChartViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5BEAED171ABBFB340013F194 /* ScatterChartViewController.xib */; }; + 225B368A1F6EBA640005B3D5 /* SinusBarChartViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5BEAED3F1ABC1AC60013F194 /* SinusBarChartViewController.xib */; }; + 225B368B1F6EBA640005B3D5 /* StackedBarChartViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5BEAED1A1ABBFB340013F194 /* StackedBarChartViewController.xib */; }; + 225B368C1F6EBBB00005B3D5 /* Charts.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0630AE411D8126C0008859B0 /* Charts.framework */; }; + 225B368D1F6EBBB00005B3D5 /* Charts.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 0630AE411D8126C0008859B0 /* Charts.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 55E356501ADC638F00A57971 /* BubbleChartViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 55E3564D1ADC638F00A57971 /* BubbleChartViewController.xib */; }; 55E356511ADC638F00A57971 /* BubbleChartViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 55E3564F1ADC638F00A57971 /* BubbleChartViewController.m */; }; 5B0CC7851ABB875400665592 /* PieChartViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B0CC7831ABB875400665592 /* PieChartViewController.m */; }; @@ -107,9 +168,27 @@ remoteGlobalIDString = 06165F231D8110E600722320; remoteInfo = Charts; }; + 225B368E1F6EBBB00005B3D5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 0630AE391D8126C0008859B0 /* Charts.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 06165F231D8110E600722320; + remoteInfo = Charts; + }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ + 225B36901F6EBBB10005B3D5 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 225B368D1F6EBBB00005B3D5 /* Charts.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; 5BB4B0751ACA710D00E2EF4D /* Embed Frameworks */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; @@ -129,6 +208,40 @@ 0471CBFB1CA1090A00E52DBC /* PiePolylineChartViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = PiePolylineChartViewController.xib; sourceTree = ""; }; 0630AE391D8126C0008859B0 /* Charts.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Charts.xcodeproj; path = ../Charts.xcodeproj; sourceTree = ""; }; 066750AC1E2DB68D00E22DC6 /* Carthage.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Carthage.xcconfig; path = ../Carthage.xcconfig; sourceTree = ""; }; + 225B361D1F6EB9A50005B3D5 /* ChartsDemo-Swift.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "ChartsDemo-Swift.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 225B361F1F6EB9A50005B3D5 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 225B362F1F6EB9EE0005B3D5 /* DemoBaseViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DemoBaseViewController.swift; sourceTree = ""; }; + 225B36301F6EB9EE0005B3D5 /* DemoListViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DemoListViewController.swift; sourceTree = ""; }; + 225B36341F6EB9FE0005B3D5 /* IntAxisValueFormatter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntAxisValueFormatter.swift; sourceTree = ""; }; + 225B36351F6EB9FE0005B3D5 /* DayAxisValueFormatter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DayAxisValueFormatter.swift; sourceTree = ""; }; + 225B36361F6EB9FE0005B3D5 /* DateValueFormatter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateValueFormatter.swift; sourceTree = ""; }; + 225B36371F6EB9FE0005B3D5 /* LargeValueFormatter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LargeValueFormatter.swift; sourceTree = ""; }; + 225B363D1F6EBA180005B3D5 /* XYMarkerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XYMarkerView.swift; sourceTree = ""; }; + 225B363E1F6EBA180005B3D5 /* BalloonMarker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BalloonMarker.swift; sourceTree = ""; }; + 225B363F1F6EBA180005B3D5 /* RadarMarkerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadarMarkerView.swift; sourceTree = ""; }; + 225B36441F6EBA410005B3D5 /* MultipleLinesChartViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultipleLinesChartViewController.swift; sourceTree = ""; }; + 225B36451F6EBA410005B3D5 /* MultipleBarChartViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultipleBarChartViewController.swift; sourceTree = ""; }; + 225B36461F6EBA410005B3D5 /* HalfPieChartViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HalfPieChartViewController.swift; sourceTree = ""; }; + 225B36471F6EBA410005B3D5 /* LineChartTimeViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LineChartTimeViewController.swift; sourceTree = ""; }; + 225B36481F6EBA410005B3D5 /* ColoredLineChartViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColoredLineChartViewController.swift; sourceTree = ""; }; + 225B36491F6EBA410005B3D5 /* LineChart2ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LineChart2ViewController.swift; sourceTree = ""; }; + 225B364A1F6EBA410005B3D5 /* LineChart1ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LineChart1ViewController.swift; sourceTree = ""; }; + 225B364B1F6EBA410005B3D5 /* NegativeStackedBarChartViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NegativeStackedBarChartViewController.swift; sourceTree = ""; }; + 225B364C1F6EBA410005B3D5 /* ScatterChartViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScatterChartViewController.swift; sourceTree = ""; }; + 225B364D1F6EBA410005B3D5 /* StackedBarChartViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StackedBarChartViewController.swift; sourceTree = ""; }; + 225B364E1F6EBA410005B3D5 /* BubbleChartViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BubbleChartViewController.swift; sourceTree = ""; }; + 225B364F1F6EBA410005B3D5 /* LineChartFilledViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LineChartFilledViewController.swift; sourceTree = ""; }; + 225B36501F6EBA410005B3D5 /* PositiveNegativeBarChartViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PositiveNegativeBarChartViewController.swift; sourceTree = ""; }; + 225B36511F6EBA410005B3D5 /* AnotherBarChartViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnotherBarChartViewController.swift; sourceTree = ""; }; + 225B36521F6EBA410005B3D5 /* PieChartViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PieChartViewController.swift; sourceTree = ""; }; + 225B36531F6EBA410005B3D5 /* CubicLineChartViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CubicLineChartViewController.swift; sourceTree = ""; }; + 225B36541F6EBA410005B3D5 /* RadarChartViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadarChartViewController.swift; sourceTree = ""; }; + 225B36551F6EBA410005B3D5 /* HorizontalBarChartViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HorizontalBarChartViewController.swift; sourceTree = ""; }; + 225B36561F6EBA410005B3D5 /* PiePolylineChartViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PiePolylineChartViewController.swift; sourceTree = ""; }; + 225B36571F6EBA410005B3D5 /* CombinedChartViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CombinedChartViewController.swift; sourceTree = ""; }; + 225B36581F6EBA410005B3D5 /* BarChartViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BarChartViewController.swift; sourceTree = ""; }; + 225B36591F6EBA410005B3D5 /* SinusBarChartViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SinusBarChartViewController.swift; sourceTree = ""; }; + 225B365A1F6EBA410005B3D5 /* CandleStickChartViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CandleStickChartViewController.swift; sourceTree = ""; }; 55E3564D1ADC638F00A57971 /* BubbleChartViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = BubbleChartViewController.xib; sourceTree = ""; }; 55E3564E1ADC638F00A57971 /* BubbleChartViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BubbleChartViewController.h; sourceTree = ""; }; 55E3564F1ADC638F00A57971 /* BubbleChartViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BubbleChartViewController.m; sourceTree = ""; }; @@ -235,6 +348,14 @@ /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ + 225B361A1F6EB9A50005B3D5 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 225B368C1F6EBBB00005B3D5 /* Charts.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 5B57BBAC1A9B26AA0036A6CC /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -255,6 +376,70 @@ name = Products; sourceTree = ""; }; + 225B361E1F6EB9A50005B3D5 /* Swift */ = { + isa = PBXGroup; + children = ( + 225B361F1F6EB9A50005B3D5 /* AppDelegate.swift */, + 225B362F1F6EB9EE0005B3D5 /* DemoBaseViewController.swift */, + 225B36301F6EB9EE0005B3D5 /* DemoListViewController.swift */, + 225B363C1F6EBA180005B3D5 /* Components */, + 225B36331F6EB9FE0005B3D5 /* Formatters */, + 225B36431F6EBA410005B3D5 /* Demos */, + ); + path = Swift; + sourceTree = ""; + }; + 225B36331F6EB9FE0005B3D5 /* Formatters */ = { + isa = PBXGroup; + children = ( + 225B36351F6EB9FE0005B3D5 /* DayAxisValueFormatter.swift */, + 225B36361F6EB9FE0005B3D5 /* DateValueFormatter.swift */, + 225B36341F6EB9FE0005B3D5 /* IntAxisValueFormatter.swift */, + 225B36371F6EB9FE0005B3D5 /* LargeValueFormatter.swift */, + ); + path = Formatters; + sourceTree = ""; + }; + 225B363C1F6EBA180005B3D5 /* Components */ = { + isa = PBXGroup; + children = ( + 225B363E1F6EBA180005B3D5 /* BalloonMarker.swift */, + 225B363F1F6EBA180005B3D5 /* RadarMarkerView.swift */, + 225B363D1F6EBA180005B3D5 /* XYMarkerView.swift */, + ); + path = Components; + sourceTree = ""; + }; + 225B36431F6EBA410005B3D5 /* Demos */ = { + isa = PBXGroup; + children = ( + 225B36511F6EBA410005B3D5 /* AnotherBarChartViewController.swift */, + 225B36581F6EBA410005B3D5 /* BarChartViewController.swift */, + 225B364E1F6EBA410005B3D5 /* BubbleChartViewController.swift */, + 225B365A1F6EBA410005B3D5 /* CandleStickChartViewController.swift */, + 225B36481F6EBA410005B3D5 /* ColoredLineChartViewController.swift */, + 225B36571F6EBA410005B3D5 /* CombinedChartViewController.swift */, + 225B36531F6EBA410005B3D5 /* CubicLineChartViewController.swift */, + 225B36461F6EBA410005B3D5 /* HalfPieChartViewController.swift */, + 225B36551F6EBA410005B3D5 /* HorizontalBarChartViewController.swift */, + 225B364A1F6EBA410005B3D5 /* LineChart1ViewController.swift */, + 225B36491F6EBA410005B3D5 /* LineChart2ViewController.swift */, + 225B364F1F6EBA410005B3D5 /* LineChartFilledViewController.swift */, + 225B36471F6EBA410005B3D5 /* LineChartTimeViewController.swift */, + 225B36441F6EBA410005B3D5 /* MultipleLinesChartViewController.swift */, + 225B36451F6EBA410005B3D5 /* MultipleBarChartViewController.swift */, + 225B364B1F6EBA410005B3D5 /* NegativeStackedBarChartViewController.swift */, + 225B36521F6EBA410005B3D5 /* PieChartViewController.swift */, + 225B36561F6EBA410005B3D5 /* PiePolylineChartViewController.swift */, + 225B36501F6EBA410005B3D5 /* PositiveNegativeBarChartViewController.swift */, + 225B36541F6EBA410005B3D5 /* RadarChartViewController.swift */, + 225B364C1F6EBA410005B3D5 /* ScatterChartViewController.swift */, + 225B36591F6EBA410005B3D5 /* SinusBarChartViewController.swift */, + 225B364D1F6EBA410005B3D5 /* StackedBarChartViewController.swift */, + ); + path = Demos; + sourceTree = ""; + }; 227136F41F6EB665006D2A11 /* XIBs */ = { isa = PBXGroup; children = ( @@ -327,6 +512,7 @@ children = ( 066750AC1E2DB68D00E22DC6 /* Carthage.xcconfig */, 5B57BBB11A9B26AA0036A6CC /* Objective-C */, + 225B361E1F6EB9A50005B3D5 /* Swift */, 227136F41F6EB665006D2A11 /* XIBs */, 5B8EAF2E1AB32E15009697AA /* Resources */, 5B57BBB21A9B26AA0036A6CC /* Supporting Files */, @@ -339,6 +525,7 @@ isa = PBXGroup; children = ( 5B57BBAF1A9B26AA0036A6CC /* ChartsDemo.app */, + 225B361D1F6EB9A50005B3D5 /* ChartsDemo-Swift.app */, ); name = Products; sourceTree = ""; @@ -468,6 +655,25 @@ /* End PBXGroup section */ /* Begin PBXNativeTarget section */ + 225B361C1F6EB9A50005B3D5 /* ChartsDemo-Swift */ = { + isa = PBXNativeTarget; + buildConfigurationList = 225B362C1F6EB9A50005B3D5 /* Build configuration list for PBXNativeTarget "ChartsDemo-Swift" */; + buildPhases = ( + 225B36191F6EB9A50005B3D5 /* Sources */, + 225B361A1F6EB9A50005B3D5 /* Frameworks */, + 225B361B1F6EB9A50005B3D5 /* Resources */, + 225B36901F6EBBB10005B3D5 /* Embed Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 225B368F1F6EBBB00005B3D5 /* PBXTargetDependency */, + ); + name = "ChartsDemo-Swift"; + productName = "ChartsDemo-Swift"; + productReference = 225B361D1F6EB9A50005B3D5 /* ChartsDemo-Swift.app */; + productType = "com.apple.product-type.application"; + }; 5B57BBAE1A9B26AA0036A6CC /* ChartsDemo */ = { isa = PBXNativeTarget; buildConfigurationList = 5B57BBD21A9B26AA0036A6CC /* Build configuration list for PBXNativeTarget "ChartsDemo" */; @@ -494,10 +700,14 @@ isa = PBXProject; attributes = { LastSwiftMigration = 0700; - LastSwiftUpdateCheck = 0700; + LastSwiftUpdateCheck = 0900; LastUpgradeCheck = 0820; ORGANIZATIONNAME = dcg; TargetAttributes = { + 225B361C1F6EB9A50005B3D5 = { + CreatedOnToolsVersion = 9.0; + ProvisioningStyle = Automatic; + }; 5B57BBAE1A9B26AA0036A6CC = { CreatedOnToolsVersion = 6.1.1; LastSwiftMigration = 0800; @@ -524,6 +734,7 @@ projectRoot = ""; targets = ( 5B57BBAE1A9B26AA0036A6CC /* ChartsDemo */, + 225B361C1F6EB9A50005B3D5 /* ChartsDemo-Swift */, ); }; /* End PBXProject section */ @@ -546,6 +757,39 @@ /* End PBXReferenceProxy section */ /* Begin PBXResourcesBuildPhase section */ + 225B361B1F6EB9A50005B3D5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 225B367C1F6EBA640005B3D5 /* HorizontalBarChartViewController.xib in Resources */, + 225B36841F6EBA640005B3D5 /* PieChartViewController.xib in Resources */, + 225B36741F6EBA640005B3D5 /* AnotherBarChartViewController.xib in Resources */, + 225B36781F6EBA640005B3D5 /* ColoredLineChartViewController.xib in Resources */, + 225B36791F6EBA640005B3D5 /* CombinedChartViewController.xib in Resources */, + 225B367B1F6EBA640005B3D5 /* HalfPieChartViewController.xib in Resources */, + 225B367A1F6EBA640005B3D5 /* CubicLineChartViewController.xib in Resources */, + 225B368B1F6EBA640005B3D5 /* StackedBarChartViewController.xib in Resources */, + 225B36821F6EBA640005B3D5 /* MultipleLinesChartViewController.xib in Resources */, + 225B36751F6EBA640005B3D5 /* BarChartViewController.xib in Resources */, + 225B367F1F6EBA640005B3D5 /* LineChartFilledViewController.xib in Resources */, + 225B36801F6EBA640005B3D5 /* LineChartTimeViewController.xib in Resources */, + 225B36811F6EBA640005B3D5 /* MultipleBarChartViewController.xib in Resources */, + 225B367D1F6EBA640005B3D5 /* LineChart1ViewController.xib in Resources */, + 225B36721F6EBA5E0005B3D5 /* DemoListViewController.xib in Resources */, + 225B36891F6EBA640005B3D5 /* ScatterChartViewController.xib in Resources */, + 225B36851F6EBA640005B3D5 /* PiePolylineChartViewController.xib in Resources */, + 225B36771F6EBA640005B3D5 /* CandleStickChartViewController.xib in Resources */, + 225B36871F6EBA640005B3D5 /* RadarChartViewController.xib in Resources */, + 225B368A1F6EBA640005B3D5 /* SinusBarChartViewController.xib in Resources */, + 225B36731F6EBA5E0005B3D5 /* RadarMarkerView.xib in Resources */, + 225B367E1F6EBA640005B3D5 /* LineChart2ViewController.xib in Resources */, + 225B36881F6EBA640005B3D5 /* RealmDemosViewController.xib in Resources */, + 225B36861F6EBA640005B3D5 /* PositiveNegativeBarChartViewController.xib in Resources */, + 225B36831F6EBA640005B3D5 /* NegativeStackedBarChartViewController.xib in Resources */, + 225B36761F6EBA640005B3D5 /* BubbleChartViewController.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 5B57BBAD1A9B26AA0036A6CC /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -596,6 +840,46 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ + 225B36191F6EB9A50005B3D5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 225B365E1F6EBA470005B3D5 /* LineChartTimeViewController.swift in Sources */, + 225B36311F6EB9EE0005B3D5 /* DemoBaseViewController.swift in Sources */, + 225B36391F6EBA040005B3D5 /* DayAxisValueFormatter.swift in Sources */, + 225B36661F6EBA470005B3D5 /* LineChartFilledViewController.swift in Sources */, + 225B366A1F6EBA470005B3D5 /* CubicLineChartViewController.swift in Sources */, + 225B36671F6EBA470005B3D5 /* PositiveNegativeBarChartViewController.swift in Sources */, + 225B363A1F6EBA040005B3D5 /* DateValueFormatter.swift in Sources */, + 225B366D1F6EBA470005B3D5 /* PiePolylineChartViewController.swift in Sources */, + 225B366F1F6EBA470005B3D5 /* BarChartViewController.swift in Sources */, + 225B36601F6EBA470005B3D5 /* LineChart2ViewController.swift in Sources */, + 225B36411F6EBA1D0005B3D5 /* BalloonMarker.swift in Sources */, + 225B366C1F6EBA470005B3D5 /* HorizontalBarChartViewController.swift in Sources */, + 225B36401F6EBA1D0005B3D5 /* XYMarkerView.swift in Sources */, + 225B36421F6EBA1D0005B3D5 /* RadarMarkerView.swift in Sources */, + 225B366B1F6EBA470005B3D5 /* RadarChartViewController.swift in Sources */, + 225B36611F6EBA470005B3D5 /* LineChart1ViewController.swift in Sources */, + 225B36691F6EBA470005B3D5 /* PieChartViewController.swift in Sources */, + 225B365B1F6EBA470005B3D5 /* MultipleLinesChartViewController.swift in Sources */, + 225B365F1F6EBA470005B3D5 /* ColoredLineChartViewController.swift in Sources */, + 225B36201F6EB9A50005B3D5 /* AppDelegate.swift in Sources */, + 225B36321F6EB9EE0005B3D5 /* DemoListViewController.swift in Sources */, + 225B36711F6EBA470005B3D5 /* CandleStickChartViewController.swift in Sources */, + 225B36631F6EBA470005B3D5 /* ScatterChartViewController.swift in Sources */, + 225B365C1F6EBA470005B3D5 /* MultipleBarChartViewController.swift in Sources */, + 225B366E1F6EBA470005B3D5 /* CombinedChartViewController.swift in Sources */, + 225B36641F6EBA470005B3D5 /* StackedBarChartViewController.swift in Sources */, + 225B36651F6EBA470005B3D5 /* BubbleChartViewController.swift in Sources */, + 225B36381F6EBA040005B3D5 /* IntAxisValueFormatter.swift in Sources */, + 225B365D1F6EBA470005B3D5 /* HalfPieChartViewController.swift in Sources */, + 225B36701F6EBA470005B3D5 /* SinusBarChartViewController.swift in Sources */, + 225B36681F6EBA470005B3D5 /* AnotherBarChartViewController.swift in Sources */, + 225B36621F6EBA470005B3D5 /* NegativeStackedBarChartViewController.swift in Sources */, + 225B363B1F6EBA040005B3D5 /* LargeValueFormatter.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 5B57BBAB1A9B26AA0036A6CC /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -645,9 +929,79 @@ name = Charts; targetProxy = 0630AE531D81271B008859B0 /* PBXContainerItemProxy */; }; + 225B368F1F6EBBB00005B3D5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Charts; + targetProxy = 225B368E1F6EBBB00005B3D5 /* PBXContainerItemProxy */; + }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ + 225B362D1F6EB9A50005B3D5 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = ""; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = "$(SRCROOT)/Supporting Files/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 8.2; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.dcg.ChartsDemo-Swift"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = 1; + }; + name = Debug; + }; + 225B362E1F6EB9A50005B3D5 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = ""; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = "$(SRCROOT)/Supporting Files/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 8.2; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.dcg.ChartsDemo-Swift"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = 1; + }; + name = Release; + }; 5B57BBD01A9B26AA0036A6CC /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 066750AC1E2DB68D00E22DC6 /* Carthage.xcconfig */; @@ -687,7 +1041,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.1; + IPHONEOS_DEPLOYMENT_TARGET = 8.2; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -726,7 +1080,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.1; + IPHONEOS_DEPLOYMENT_TARGET = 8.2; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; @@ -776,6 +1130,15 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ + 225B362C1F6EB9A50005B3D5 /* Build configuration list for PBXNativeTarget "ChartsDemo-Swift" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 225B362D1F6EB9A50005B3D5 /* Debug */, + 225B362E1F6EB9A50005B3D5 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; 5B57BBAA1A9B26AA0036A6CC /* Build configuration list for PBXProject "ChartsDemo" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/ChartsDemo/Resources/Images.xcassets/AppIcon.appiconset/Contents.json b/ChartsDemo/Resources/Images.xcassets/AppIcon.appiconset/Contents.json index fe9ab4226e..32d8413dd0 100644 --- a/ChartsDemo/Resources/Images.xcassets/AppIcon.appiconset/Contents.json +++ b/ChartsDemo/Resources/Images.xcassets/AppIcon.appiconset/Contents.json @@ -45,6 +45,11 @@ "idiom" : "iphone", "filename" : "Icon-60@3x.png", "scale" : "3x" + }, + { + "idiom" : "ios-marketing", + "size" : "1024x1024", + "scale" : "1x" } ], "info" : { diff --git a/ChartsDemo/Swift/AppDelegate.swift b/ChartsDemo/Swift/AppDelegate.swift new file mode 100644 index 0000000000..7f13108e70 --- /dev/null +++ b/ChartsDemo/Swift/AppDelegate.swift @@ -0,0 +1,54 @@ +// +// AppDelegate.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-03. +// Copyright © 2017 jc. All rights reserved. +// + +import UIKit + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + + var window: UIWindow? + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { + // Override point for customization after application launch. + self.window = UIWindow(frame: UIScreen.main.bounds) + + + let vc = DemoListViewController() + let nav = UINavigationController(rootViewController: vc) + + window?.rootViewController = nav + window?.makeKeyAndVisible() + + return true + } + + func applicationWillResignActive(_ application: UIApplication) { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. + } + + func applicationDidEnterBackground(_ application: UIApplication) { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. + } + + func applicationWillEnterForeground(_ application: UIApplication) { + // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. + } + + func applicationDidBecomeActive(_ application: UIApplication) { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. + } + + func applicationWillTerminate(_ application: UIApplication) { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. + } + + +} + diff --git a/ChartsDemo/Swift/Components/BalloonMarker.swift b/ChartsDemo/Swift/Components/BalloonMarker.swift new file mode 100644 index 0000000000..d18b3d2823 --- /dev/null +++ b/ChartsDemo/Swift/Components/BalloonMarker.swift @@ -0,0 +1,122 @@ +// +// BalloonMarker.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-09. +// Copyright © 2017 jc. All rights reserved. +// + +import Foundation +import Charts + +public class BalloonMarker: MarkerImage { + public var color: UIColor + public var arrowSize = CGSize(width: 15, height: 11) + public var font: UIFont + public var textColor: UIColor + public var insets: UIEdgeInsets + public var minimumSize = CGSize() + + fileprivate var label: String? + fileprivate var _labelSize: CGSize = CGSize() + fileprivate var _paragraphStyle: NSMutableParagraphStyle? + fileprivate var _drawAttributes = [NSAttributedStringKey : AnyObject]() + + public init(color: UIColor, font: UIFont, textColor: UIColor, insets: UIEdgeInsets) { + self.color = color + self.font = font + self.textColor = textColor + self.insets = insets + + _paragraphStyle = NSParagraphStyle.default.mutableCopy() as? NSMutableParagraphStyle + _paragraphStyle?.alignment = .center + super.init() + } + + public override func offsetForDrawing(atPoint point: CGPoint) -> CGPoint { + let size = self.size + var point = point + point.x -= size.width / 2.0 + point.y -= size.height + return super.offsetForDrawing(atPoint: point) + } + + public override func draw(context: CGContext, point: CGPoint) { + guard let label = label else { return } + + let offset = self.offsetForDrawing(atPoint: point) + let size = self.size + + var rect = CGRect( + origin: CGPoint( + x: point.x + offset.x, + y: point.y + offset.y), + size: size) + rect.origin.x -= size.width / 2.0 + rect.origin.y -= size.height + + context.saveGState() + + context.setFillColor(color.cgColor) + context.beginPath() + context.move(to: CGPoint( + x: rect.origin.x, + y: rect.origin.y)) + context.addLine(to: CGPoint( + x: rect.origin.x + rect.size.width, + y: rect.origin.y)) + context.addLine(to: CGPoint( + x: rect.origin.x + rect.size.width, + y: rect.origin.y + rect.size.height - arrowSize.height)) + context.addLine(to: CGPoint( + x: rect.origin.x + (rect.size.width + arrowSize.width) / 2.0, + y: rect.origin.y + rect.size.height - arrowSize.height)) + context.addLine(to: CGPoint( + x: rect.origin.x + rect.size.width / 2.0, + y: rect.origin.y + rect.size.height)) + context.addLine(to: CGPoint( + x: rect.origin.x + (rect.size.width - arrowSize.width) / 2.0, + y: rect.origin.y + rect.size.height - arrowSize.height)) + context.addLine(to: CGPoint( + x: rect.origin.x, + y: rect.origin.y + rect.size.height - arrowSize.height)) + context.addLine(to: CGPoint( + x: rect.origin.x, + y: rect.origin.y)) + context.fillPath() + + rect.origin.y += self.insets.top + rect.size.height -= self.insets.top + self.insets.bottom + + UIGraphicsPushContext(context) + + label.draw(in: rect, withAttributes: _drawAttributes) + + UIGraphicsPopContext() + + context.restoreGState() + } + + public override func refreshContent(entry: ChartDataEntry, highlight: Highlight) { + setLabel(String(entry.y)) + } + + public func setLabel(_ newLabel: String) { + label = newLabel + + _drawAttributes.removeAll() + _drawAttributes[.font] = self.font + _drawAttributes[.paragraphStyle] = _paragraphStyle + _drawAttributes[.foregroundColor] = self.textColor + + _labelSize = label?.size(withAttributes: _drawAttributes) ?? CGSize.zero + + var size = CGSize() + size.width = _labelSize.width + self.insets.left + self.insets.right + size.height = _labelSize.height + self.insets.top + self.insets.bottom + size.width = max(minimumSize.width, size.width) + size.height = max(minimumSize.height, size.height) + self.size = size + } + +} diff --git a/ChartsDemo/Swift/Components/RadarMarkerView.swift b/ChartsDemo/Swift/Components/RadarMarkerView.swift new file mode 100644 index 0000000000..019196d5e8 --- /dev/null +++ b/ChartsDemo/Swift/Components/RadarMarkerView.swift @@ -0,0 +1,27 @@ +// +// RadarMarkerView.swift +// ChartsDemo +// +// 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 Charts + +public class RadarMarkerView: MarkerView { + @IBOutlet var label: UILabel! + + public override func awakeFromNib() { + self.offset.x = -self.frame.size.width / 2.0 + self.offset.y = -self.frame.size.height - 7.0 + } + + public override func refreshContent(entry: ChartDataEntry, highlight: Highlight) { + label.text = String.init(format: "%d %%", Int(round(entry.y))) + layoutIfNeeded() + } +} diff --git a/ChartsDemo/Swift/Components/XYMarkerView.swift b/ChartsDemo/Swift/Components/XYMarkerView.swift new file mode 100644 index 0000000000..23bb965487 --- /dev/null +++ b/ChartsDemo/Swift/Components/XYMarkerView.swift @@ -0,0 +1,32 @@ +// +// XYMarkerView.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-09. +// Copyright © 2017 jc. All rights reserved. +// + +import Foundation +import Charts + +public class XYMarkerView: BalloonMarker { + public var xAxisValueFormatter: IAxisValueFormatter + fileprivate var yFormatter = NumberFormatter() + + public init(color: UIColor, font: UIFont, textColor: UIColor, insets: UIEdgeInsets, + xAxisValueFormatter: IAxisValueFormatter) { + self.xAxisValueFormatter = xAxisValueFormatter + yFormatter.minimumFractionDigits = 1 + yFormatter.maximumFractionDigits = 1 + super.init(color: color, font: font, textColor: textColor, insets: insets) + } + + public override func refreshContent(entry: ChartDataEntry, highlight: Highlight) { + let string = "x: " + + xAxisValueFormatter.stringForValue(entry.x, axis: XAxis()) + + ", y: " + + yFormatter.string(from: NSNumber(floatLiteral: entry.y))! + setLabel(string) + } + +} diff --git a/ChartsDemo/Swift/DemoBaseViewController.swift b/ChartsDemo/Swift/DemoBaseViewController.swift new file mode 100644 index 0000000000..c19c174ee9 --- /dev/null +++ b/ChartsDemo/Swift/DemoBaseViewController.swift @@ -0,0 +1,362 @@ +// +// DemoBaseViewController.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-03. +// Copyright © 2017 jc. All rights reserved. +// + +import UIKit +import Charts + +enum Option { + case toggleValues + case toggleIcons + case toggleHighlight + case animateX + case animateY + case animateXY + case saveToGallery + case togglePinchZoom + case toggleAutoScaleMinMax + case toggleData + case toggleBarBorders + // CandleChart + case toggleShadowColorSameAsCandle + // CombinedChart + case toggleLineValues + case toggleBarValues + case removeDataSet + // CubicLineSampleFillFormatter + case toggleFilled + case toggleCircles + case toggleCubic + case toggleHorizontalCubic + case toggleStepped + // HalfPieChartController + case toggleXValues + case togglePercent + case toggleHole + case spin + case drawCenter + // RadarChart + case toggleXLabels + case toggleYLabels + case toggleRotate + case toggleHighlightCircle + + var label: String { + switch self { + case .toggleValues: return "Toggle Y-Values" + case .toggleIcons: return "Toggle Icons" + case .toggleHighlight: return "Toggle Highlight" + case .animateX: return "Animate X" + case .animateY: return "Animate Y" + case .animateXY: return "Animate XY" + case .saveToGallery: return "Save to Camera Roll" + case .togglePinchZoom: return "Toggle PinchZoom" + case .toggleAutoScaleMinMax: return "Toggle auto scale min/max" + case .toggleData: return "Toggle Data" + case .toggleBarBorders: return "Toggle Bar Borders" + // CandleChart + case .toggleShadowColorSameAsCandle: return "Toggle shadow same color" + // CombinedChart + case .toggleLineValues: return "Toggle Line Values" + case .toggleBarValues: return "Toggle Bar Values" + case .removeDataSet: return "Remove Random Set" + // CubicLineSampleFillFormatter + case .toggleFilled: return "Toggle Filled" + case .toggleCircles: return "Toggle Circles" + case .toggleCubic: return "Toggle Cubic" + case .toggleHorizontalCubic: return "Toggle Horizontal Cubic" + case .toggleStepped: return "Toggle Stepped" + // HalfPieChartController + case .toggleXValues: return "Toggle X-Values" + case .togglePercent: return "Toggle Percent" + case .toggleHole: return "Toggle Hole" + case .spin: return "Spin" + case .drawCenter: return "Draw CenterText" + // RadarChart + case .toggleXLabels: return "Toggle X-Labels" + case .toggleYLabels: return "Toggle Y-Labels" + case .toggleRotate: return "Toggle Rotate" + case .toggleHighlightCircle: return "Toggle highlight circle" + } + } +} + +class DemoBaseViewController: UIViewController, ChartViewDelegate { + private var optionsTableView: UITableView? = nil + let parties = ["Party A", "Party B", "Party C", "Party D", "Party E", "Party F", + "Party G", "Party H", "Party I", "Party J", "Party K", "Party L", + "Party M", "Party N", "Party O", "Party P", "Party Q", "Party R", + "Party S", "Party T", "Party U", "Party V", "Party W", "Party X", + "Party Y", "Party Z"] + + @IBOutlet weak var optionsButton: UIButton! + var options: [Option]! + + var shouldHideData: Bool = false + + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + self.initialize() + } + + override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { + super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) + self.initialize() + } + + private func initialize() { + self.edgesForExtendedLayout = [] + } + + func optionTapped(_ option: Option) {} + + func handleOption(_ option: Option, forChartView chartView: ChartViewBase) { + switch option { + case .toggleValues: + for set in chartView.data!.dataSets { + set.drawValuesEnabled = !set.drawValuesEnabled + } + chartView.setNeedsDisplay() + + case .toggleIcons: + for set in chartView.data!.dataSets { + set.drawIconsEnabled = !set.drawIconsEnabled + } + chartView.setNeedsDisplay() + + case .toggleHighlight: + chartView.data!.highlightEnabled = !chartView.data!.isHighlightEnabled + chartView.setNeedsDisplay() + + case .animateX: + chartView.animate(xAxisDuration: 3) + + case .animateY: + chartView.animate(yAxisDuration: 3) + + case .animateXY: + chartView.animate(xAxisDuration: 3, yAxisDuration: 3) + + case .saveToGallery: + UIImageWriteToSavedPhotosAlbum(chartView.getChartImage(transparent: false)!, nil, nil, nil) + + case .togglePinchZoom: + let barLineChart = chartView as! BarLineChartViewBase + barLineChart.pinchZoomEnabled = !barLineChart.pinchZoomEnabled + chartView.setNeedsDisplay() + + case .toggleAutoScaleMinMax: + let barLineChart = chartView as! BarLineChartViewBase + barLineChart.autoScaleMinMaxEnabled = !barLineChart.isAutoScaleMinMaxEnabled + chartView.notifyDataSetChanged() + + case .toggleData: + shouldHideData = !shouldHideData + updateChartData() + + case .toggleBarBorders: + for set in chartView.data!.dataSets { + if let set = set as? BarChartDataSet { + set.barBorderWidth = set.barBorderWidth == 1.0 ? 0.0 : 1.0 + } + } + chartView.setNeedsDisplay() + default: + break + } + } + + @IBAction func optionsButtonTapped(_ sender: Any) { + if let optionsTableView = self.optionsTableView { + optionsTableView.removeFromSuperview() + self.optionsTableView = nil + return + } + + let optionsTableView = UITableView() + optionsTableView.backgroundColor = UIColor(white: 0, alpha: 0.9) + optionsTableView.delegate = self + optionsTableView.dataSource = self + + optionsTableView.translatesAutoresizingMaskIntoConstraints = false + + self.optionsTableView = optionsTableView + + var constraints = [NSLayoutConstraint]() + + constraints.append(NSLayoutConstraint(item: optionsTableView, + attribute: .leading, + relatedBy: .equal, + toItem: self.view, + attribute: .leading, + multiplier: 1, + constant: 40)) + + constraints.append(NSLayoutConstraint(item: optionsTableView, + attribute: .trailing, + relatedBy: .equal, + toItem: sender as! UIView, + attribute: .trailing, + multiplier: 1, + constant: 0)) + + constraints.append(NSLayoutConstraint(item: optionsTableView, + attribute: .top, + relatedBy: .equal, + toItem: sender, + attribute: .bottom, + multiplier: 1, + constant: 5)) + + self.view.addSubview(optionsTableView) + constraints.forEach { $0.isActive = true } + + let constraint = NSLayoutConstraint(item: optionsTableView, + attribute: .height, + relatedBy: .equal, + toItem: nil, + attribute: .height, + multiplier: 1, + constant: 220) + constraint.isActive = true + } + + func updateChartData() { + fatalError("updateChartData not overridden") + } + + func setup(pieChartView chartView: PieChartView) { + chartView.usePercentValuesEnabled = true + chartView.drawSlicesUnderHoleEnabled = false + chartView.holeRadiusPercent = 0.58 + chartView.transparentCircleRadiusPercent = 0.61 + chartView.chartDescription?.enabled = false + chartView.setExtraOffsets(left: 5, top: 10, right: 5, bottom: 5) + + chartView.drawCenterTextEnabled = true + + let paragraphStyle = NSParagraphStyle.default.mutableCopy() as! NSMutableParagraphStyle + paragraphStyle.lineBreakMode = .byTruncatingTail + paragraphStyle.alignment = .center + + let centerText = NSMutableAttributedString(string: "Charts\nby Daniel Cohen Gindi") + centerText.setAttributes([.font : UIFont(name: "HelveticaNeue-Light", size: 13)!, + .paragraphStyle : paragraphStyle], range: NSRange(location: 0, length: centerText.length)) + centerText.addAttributes([.font : UIFont(name: "HelveticaNeue-Light", size: 11)!, + .foregroundColor : UIColor.gray], range: NSRange(location: 10, length: centerText.length - 10)) + centerText.addAttributes([.font : UIFont(name: "HelveticaNeue-Light", size: 11)!, + .foregroundColor : UIColor(red: 51/255, green: 181/255, blue: 229/255, alpha: 1)], range: NSRange(location: centerText.length - 19, length: 19)) + chartView.centerAttributedText = centerText; + + chartView.drawHoleEnabled = true + chartView.rotationAngle = 0 + chartView.rotationEnabled = true + chartView.highlightPerTapEnabled = true + + let l = chartView.legend + l.horizontalAlignment = .right + l.verticalAlignment = .top + l.orientation = .vertical + l.drawInside = false + l.xEntrySpace = 7 + l.yEntrySpace = 0 + l.yOffset = 0 +// chartView.legend = l + } + + func setup(radarChartView chartView: RadarChartView) { + chartView.chartDescription?.enabled = false + } + + func setup(barLineChartView chartView: BarLineChartViewBase) { + chartView.chartDescription?.enabled = false + + chartView.dragEnabled = true + chartView.setScaleEnabled(true) + chartView.pinchZoomEnabled = false + + // ChartYAxis *leftAxis = chartView.leftAxis; + + let xAxis = chartView.xAxis + xAxis.labelPosition = .bottom + + chartView.rightAxis.enabled = false + } + // TODO: Cannot override from extensions + //extension DemoBaseViewController: ChartViewDelegate { + func chartValueSelected(_ chartView: ChartViewBase, entry: ChartDataEntry, highlight: Highlight) { + NSLog("chartValueSelected"); + } + + func chartValueNothingSelected(_ chartView: ChartViewBase) { + NSLog("chartValueNothingSelected"); + } + + func chartScaled(_ chartView: ChartViewBase, scaleX: CGFloat, scaleY: CGFloat) { + + } + + func chartTranslated(_ chartView: ChartViewBase, dX: CGFloat, dY: CGFloat) { + + } +} + +extension DemoBaseViewController: UITableViewDelegate, UITableViewDataSource { + func numberOfSections(in tableView: UITableView) -> Int { + if optionsTableView != nil { + return 1 + } + + return 0 + } + + @available(iOS 2.0, *) + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + if optionsTableView != nil { + return options.count + } + + return 0 + + } + + func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { + if optionsTableView != nil { + return 40.0; + } + + return 44.0; + } + + @available(iOS 2.0, *) + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + var cell = tableView.dequeueReusableCell(withIdentifier: "Cell") + + if cell == nil { + cell = UITableViewCell(style: .default, reuseIdentifier: "Cell") + cell?.backgroundView = nil + cell?.backgroundColor = .clear + cell?.textLabel?.textColor = .white + } + cell?.textLabel?.text = self.options[indexPath.row].label + + return cell! + } + + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + if optionsTableView != nil { + tableView.deselectRow(at: indexPath, animated: true) + + optionsTableView?.removeFromSuperview() + self.optionsTableView = nil + + self.optionTapped(self.options[indexPath.row]) + } + + } +} + diff --git a/ChartsDemo/Swift/DemoListViewController.swift b/ChartsDemo/Swift/DemoListViewController.swift new file mode 100644 index 0000000000..1322e488cb --- /dev/null +++ b/ChartsDemo/Swift/DemoListViewController.swift @@ -0,0 +1,129 @@ +// +// DemoListViewController.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-09. +// Copyright © 2017 jc. All rights reserved. +// + +import UIKit + +private struct ItemDef { + let title: String + let subtitle: String + let `class`: AnyClass +} + +class DemoListViewController: UIViewController { + + @IBOutlet var tableView: UITableView! + private var itemDefs = [ItemDef(title: "Line Chart", + subtitle: "A simple demonstration of the linechart.", + class: LineChart1ViewController.self), + ItemDef(title: "Line Chart (Dual YAxis)", + subtitle: "Demonstration of the linechart with dual y-axis.", + class: LineChart2ViewController.self), + ItemDef(title: "Bar Chart", + subtitle: "A simple demonstration of the bar chart.", + class: BarChartViewController.self), + ItemDef(title: "Horizontal Bar Chart", + subtitle: "A simple demonstration of the horizontal bar chart.", + class: HorizontalBarChartViewController.self), + ItemDef(title: "Combined Chart", + subtitle: "Demonstrates how to create a combined chart (bar and line in this case).", + class: CombinedChartViewController.self), + ItemDef(title: "Pie Chart", + subtitle: "A simple demonstration of the pie chart.", + class: PieChartViewController.self), + ItemDef(title: "Pie Chart with value lines", + subtitle: "A simple demonstration of the pie chart with polyline notes.", + class: PiePolylineChartViewController.self), + ItemDef(title: "Scatter Chart", + subtitle: "A simple demonstration of the scatter chart.", + class: ScatterChartViewController.self), + ItemDef(title: "Bubble Chart", + subtitle: "A simple demonstration of the bubble chart.", + class: BubbleChartViewController.self), + ItemDef(title: "Stacked Bar Chart", + subtitle: "A simple demonstration of a bar chart with stacked bars.", + class: StackedBarChartViewController.self), + ItemDef(title: "Stacked Bar Chart Negative", + subtitle: "A simple demonstration of stacked bars with negative and positive values.", + class: NegativeStackedBarChartViewController.self), + ItemDef(title: "Another Bar Chart", + subtitle: "Implementation of a BarChart that only shows values at the bottom.", + class: AnotherBarChartViewController.self), + ItemDef(title: "Multiple Lines Chart", + subtitle: "A line chart with multiple DataSet objects. One color per DataSet.", + class: MultipleLinesChartViewController.self), + ItemDef(title: "Multiple Bars Chart", + subtitle: "A bar chart with multiple DataSet objects. One multiple colors per DataSet.", + class: MultipleBarChartViewController.self), + ItemDef(title: "Candle Stick Chart", + subtitle: "Demonstrates usage of the CandleStickChart.", + class: CandleStickChartViewController.self), + ItemDef(title: "Cubic Line Chart", + subtitle: "Demonstrates cubic lines in a LineChart.", + class: CubicLineChartViewController.self), + ItemDef(title: "Radar Chart", + subtitle: "Demonstrates the use of a spider-web like (net) chart.", + class: RadarChartViewController.self), + ItemDef(title: "Colored Line Chart", + subtitle: "Shows a LineChart with different background and line color.", + class: ColoredLineChartViewController.self), + ItemDef(title: "Sinus Bar Chart", + subtitle: "A Bar Chart plotting the sinus function with 8.000 values.", + class: SinusBarChartViewController.self), + ItemDef(title: "BarChart positive / negative", + subtitle: "This demonstrates how to create a BarChart with positive and negative values in different colors.", + class: PositiveNegativeBarChartViewController.self), + ItemDef(title: "Time Line Chart", + subtitle: "Simple demonstration of a time-chart. This chart draws one line entry per hour originating from the current time in milliseconds.", + class: LineChartTimeViewController.self), + ItemDef(title: "Filled Line Chart", + subtitle: "This demonstrates how to fill an area between two LineDataSets.", + class: LineChartFilledViewController.self), + ItemDef(title: "Half Pie Chart", + subtitle: "This demonstrates how to create a 180 degree PieChart.", + class: HalfPieChartViewController.self) + ] + + override func viewDidLoad() { + super.viewDidLoad() + + self.title = "Charts Demonstration" + self.tableView.rowHeight = 70 + //FIXME: Add TimeLineChart + + } +} + +extension DemoListViewController: UITableViewDelegate, UITableViewDataSource { + func numberOfSections(in tableView: UITableView) -> Int { + return 1 + } + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return self.itemDefs.count + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let def = self.itemDefs[indexPath.row] + let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") ?? UITableViewCell(style: .subtitle, reuseIdentifier: "Cell") + cell.textLabel?.text = def.title + cell.detailTextLabel?.text = def.subtitle + cell.detailTextLabel?.numberOfLines = 0 + + return cell + } + + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + let def = self.itemDefs[indexPath.row] + + let vcClass = def.class as! UIViewController.Type + let vc = vcClass.init() + + self.navigationController?.pushViewController(vc, animated: true) + tableView.deselectRow(at: indexPath, animated: true) + } +} diff --git a/ChartsDemo/Swift/Demos/AnotherBarChartViewController.swift b/ChartsDemo/Swift/Demos/AnotherBarChartViewController.swift new file mode 100644 index 0000000000..abe86cd94a --- /dev/null +++ b/ChartsDemo/Swift/Demos/AnotherBarChartViewController.swift @@ -0,0 +1,98 @@ +// +// AnotherBarChartViewController.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-09. +// Copyright © 2017 jc. All rights reserved. +// + +import UIKit +import Charts + +class AnotherBarChartViewController: DemoBaseViewController { + + @IBOutlet var chartView: BarChartView! + @IBOutlet var sliderX: UISlider! + @IBOutlet var sliderY: UISlider! + @IBOutlet var sliderTextX: UITextField! + @IBOutlet var sliderTextY: UITextField! + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + self.options = [.toggleValues, + .toggleHighlight, + .animateX, + .animateY, + .animateXY, + .saveToGallery, + .togglePinchZoom, + .toggleData, + .toggleBarBorders] + + chartView.delegate = self + + chartView.chartDescription?.enabled = false + chartView.maxVisibleCount = 60 + chartView.pinchZoomEnabled = false + chartView.drawBarShadowEnabled = false + + let xAxis = chartView.xAxis + xAxis.labelPosition = .bottom + + chartView.legend.enabled = false + + sliderX.value = 10 + sliderY.value = 100 + self.slidersValueChanged(nil) + } + + + override func updateChartData() { + if self.shouldHideData { + chartView.data = nil + return + } + + self.setDataCount(Int(sliderX.value) + 1, range: Double(sliderY.value)) + } + + func setDataCount(_ count: Int, range: Double) { + let yVals = (0.. BarChartDataEntry in + let mult = range + 1 + let val = Double(arc4random_uniform(UInt32(mult))) + mult/3 + return BarChartDataEntry(x: Double(i), y: val) + } + + var set1: BarChartDataSet! = nil + if let set = chartView.data?.dataSets.first as? BarChartDataSet { + set1 = set + set1?.values = yVals + chartView.data?.notifyDataChanged() + chartView.notifyDataSetChanged() + } else { + set1 = BarChartDataSet(values: yVals, label: "Data Set") + set1.colors = ChartColorTemplates.vordiplom() + set1.drawValuesEnabled = false + + let data = BarChartData(dataSet: set1) + chartView.data = data + chartView.fitBars = true + } + + chartView.setNeedsDisplay() + } + + override func optionTapped(_ option: Option) { + super.handleOption(option, forChartView: chartView) + } + + // MARK: - Actions + @IBAction func slidersValueChanged(_ sender: Any?) { + sliderTextX.text = "\(Int(sliderX.value))" + sliderTextY.text = "\(Int(sliderY.value))" + + self.updateChartData() + } +} diff --git a/ChartsDemo/Swift/Demos/BarChartViewController.swift b/ChartsDemo/Swift/Demos/BarChartViewController.swift new file mode 100644 index 0000000000..a9a629120a --- /dev/null +++ b/ChartsDemo/Swift/Demos/BarChartViewController.swift @@ -0,0 +1,152 @@ +// +// BarChartViewController.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-09. +// Copyright © 2017 jc. All rights reserved. +// + +import UIKit +import Charts + +class BarChartViewController: DemoBaseViewController { + + @IBOutlet var chartView: BarChartView! + @IBOutlet var sliderX: UISlider! + @IBOutlet var sliderY: UISlider! + @IBOutlet var sliderTextX: UITextField! + @IBOutlet var sliderTextY: UITextField! + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + self.title = "Bar Chart" + + self.options = [.toggleValues, + .toggleHighlight, + .animateX, + .animateY, + .animateXY, + .saveToGallery, + .togglePinchZoom, + .toggleData, + .toggleBarBorders] + + self.setup(barLineChartView: chartView) + + chartView.delegate = self + + chartView.drawBarShadowEnabled = false + chartView.drawValueAboveBarEnabled = false + + chartView.maxVisibleCount = 60 + + let xAxis = chartView.xAxis + xAxis.labelPosition = .bottom + xAxis.labelFont = .systemFont(ofSize: 10) + xAxis.granularity = 1 + xAxis.labelCount = 7 + xAxis.valueFormatter = DayAxisValueFormatter(chart: chartView) + + let leftAxisFormatter = NumberFormatter() + leftAxisFormatter.minimumFractionDigits = 0 + leftAxisFormatter.maximumFractionDigits = 1 + leftAxisFormatter.negativeSuffix = " $" + leftAxisFormatter.positiveSuffix = " $" + + let leftAxis = chartView.leftAxis + leftAxis.labelFont = .systemFont(ofSize: 10) + leftAxis.labelCount = 8 + leftAxis.valueFormatter = DefaultAxisValueFormatter(formatter: leftAxisFormatter) + leftAxis.labelPosition = .outsideChart + leftAxis.spaceTop = 0.15 + leftAxis.axisMinimum = 0 // FIXME: HUH?? this replaces startAtZero = YES + + let rightAxis = chartView.rightAxis + rightAxis.enabled = true + rightAxis.labelFont = .systemFont(ofSize: 10) + rightAxis.labelCount = 8 + rightAxis.valueFormatter = leftAxis.valueFormatter + rightAxis.spaceTop = 0.15 + rightAxis.axisMinimum = 0 + + let l = chartView.legend + l.horizontalAlignment = .left + l.verticalAlignment = .bottom + l.orientation = .horizontal + l.drawInside = false + l.form = .circle + l.formSize = 9 + l.font = UIFont(name: "HelveticaNeue-Light", size: 11)! + l.xEntrySpace = 4 +// chartView.legend = l + + let marker = XYMarkerView(color: UIColor(white: 180/250, alpha: 1), + font: .systemFont(ofSize: 12), + textColor: .white, + insets: UIEdgeInsets(top: 8, left: 8, bottom: 20, right: 8), + xAxisValueFormatter: chartView.xAxis.valueFormatter!) + marker.chartView = chartView + marker.minimumSize = CGSize(width: 80, height: 40) + chartView.marker = marker + + sliderX.value = 12 + sliderY.value = 50 + slidersValueChanged(nil) + } + + override func updateChartData() { + if self.shouldHideData { + chartView.data = nil + return + } + + self.setDataCount(Int(sliderX.value) + 1, range: UInt32(sliderY.value)) + } + + func setDataCount(_ count: Int, range: UInt32) { + let start = 1 + + let yVals = (start.. BarChartDataEntry in + let mult = range + 1 + let val = Double(arc4random_uniform(mult)) + if arc4random_uniform(100) < 25 { + return BarChartDataEntry(x: Double(i), y: val, icon: UIImage(named: "icon")) + } else { + return BarChartDataEntry(x: Double(i), y: val) + } + } + + var set1: BarChartDataSet! = nil + if let set = chartView.data?.dataSets.first as? BarChartDataSet { + set1 = set + set1.values = yVals + chartView.data?.notifyDataChanged() + chartView.notifyDataSetChanged() + } else { + set1 = BarChartDataSet(values: yVals, label: "The year 2017") + set1.colors = ChartColorTemplates.material() + set1.drawValuesEnabled = false + + let data = BarChartData(dataSet: set1) + data.setValueFont(UIFont(name: "HelveticaNeue-Light", size: 10)!) + data.barWidth = 0.9 + chartView.data = data + } + +// chartView.setNeedsDisplay() + } + + override func optionTapped(_ option: Option) { + super.handleOption(option, forChartView: chartView) + } + + // MARK: - Actions + @IBAction func slidersValueChanged(_ sender: Any?) { + sliderTextX.text = "\(Int(sliderX.value + 2))" + sliderTextY.text = "\(Int(sliderY.value))" + + self.updateChartData() + } +} diff --git a/ChartsDemo/Swift/Demos/BubbleChartViewController.swift b/ChartsDemo/Swift/Demos/BubbleChartViewController.swift new file mode 100644 index 0000000000..61d944b735 --- /dev/null +++ b/ChartsDemo/Swift/Demos/BubbleChartViewController.swift @@ -0,0 +1,127 @@ +// +// BubbleChartViewController.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-09. +// Copyright © 2017 jc. All rights reserved. +// + +import UIKit +import Charts + +class BubbleChartViewController: DemoBaseViewController { + + @IBOutlet var chartView: BubbleChartView! + @IBOutlet var sliderX: UISlider! + @IBOutlet var sliderY: UISlider! + @IBOutlet var sliderTextX: UITextField! + @IBOutlet var sliderTextY: UITextField! + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + self.title = "Bubble Chart" + self.options = [.toggleValues, + .toggleIcons, + .toggleHighlight, + .animateX, + .animateY, + .animateXY, + .saveToGallery, + .togglePinchZoom, + .toggleAutoScaleMinMax, + .toggleData] + + chartView.delegate = self + + chartView.chartDescription?.enabled = false + + chartView.dragEnabled = false + chartView.setScaleEnabled(true) + chartView.maxVisibleCount = 200 + chartView.pinchZoomEnabled = true + + chartView.legend.horizontalAlignment = .right + chartView.legend.verticalAlignment = .top + chartView.legend.orientation = .vertical + chartView.legend.drawInside = false + chartView.legend.font = UIFont(name: "HelveticaNeue-Light", size: 10)! + + chartView.leftAxis.labelFont = UIFont(name: "HelveticaNeue-Light", size: 10)! + chartView.leftAxis.spaceTop = 0.3 + chartView.leftAxis.spaceBottom = 0.3 + chartView.leftAxis.axisMinimum = 0 + + chartView.rightAxis.enabled = false + + chartView.xAxis.labelPosition = .bottom + chartView.xAxis.labelFont = UIFont(name: "HelveticaNeue-Light", size: 10)! + + sliderX.value = 10 + sliderY.value = 50 + slidersValueChanged(nil) + } + + override func updateChartData() { + if self.shouldHideData { + chartView.data = nil + return + } + + self.setDataCount(Int(sliderX.value), range: UInt32(sliderY.value)) + } + + func setDataCount(_ count: Int, range: UInt32) { + let yVals1 = (0.. BubbleChartDataEntry in + let val = Double(arc4random_uniform(range)) + let size = CGFloat(arc4random_uniform(range)) + return BubbleChartDataEntry(x: Double(i), y: val, size: size, icon: UIImage(named: "icon")) + } + let yVals2 = (0.. BubbleChartDataEntry in + let val = Double(arc4random_uniform(range)) + let size = CGFloat(arc4random_uniform(range)) + return BubbleChartDataEntry(x: Double(i), y: val, size: size, icon: UIImage(named: "icon")) + } + let yVals3 = (0.. BubbleChartDataEntry in + let val = Double(arc4random_uniform(range)) + let size = CGFloat(arc4random_uniform(range)) + return BubbleChartDataEntry(x: Double(i), y: val, size: size) + } + + let set1 = BubbleChartDataSet(values: yVals1, label: "DS 1") + set1.drawIconsEnabled = false + set1.setColor(ChartColorTemplates.colorful()[0], alpha: 0.5) + set1.drawValuesEnabled = true + + let set2 = BubbleChartDataSet(values: yVals2, label: "DS 2") + set2.drawIconsEnabled = false + set2.iconsOffset = CGPoint(x: 0, y: 15) + set2.setColor(ChartColorTemplates.colorful()[1], alpha: 0.5) + set2.drawValuesEnabled = true + + let set3 = BubbleChartDataSet(values: yVals3, label: "DS 3") + set3.setColor(ChartColorTemplates.colorful()[2], alpha: 0.5) + set3.drawValuesEnabled = true + + let data = BubbleChartData(dataSets: [set1, set2, set3]) + data.setDrawValues(false) + data.setValueFont(UIFont(name: "HelveticaNeue-Light", size: 7)!) + data.setHighlightCircleWidth(1.5) + data.setValueTextColor(.white) + + chartView.data = data + } + + override func optionTapped(_ option: Option) { + super.handleOption(option, forChartView: chartView) + } + + // MARK: - Actions + @IBAction func slidersValueChanged(_ sender: Any?) { + sliderTextX.text = "\(Int(sliderX.value))" + sliderTextY.text = "\(Int(sliderY.value))" + + self.updateChartData() + } +} diff --git a/ChartsDemo/Swift/Demos/CandleStickChartViewController.swift b/ChartsDemo/Swift/Demos/CandleStickChartViewController.swift new file mode 100644 index 0000000000..082ba9d269 --- /dev/null +++ b/ChartsDemo/Swift/Demos/CandleStickChartViewController.swift @@ -0,0 +1,122 @@ +// +// CandleStickChartViewController.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-09. +// Copyright © 2017 jc. All rights reserved. +// + +import UIKit +import Charts + +class CandleStickChartViewController: DemoBaseViewController { + + @IBOutlet var chartView: CandleStickChartView! + @IBOutlet var sliderX: UISlider! + @IBOutlet var sliderY: UISlider! + @IBOutlet var sliderTextX: UITextField! + @IBOutlet var sliderTextY: UITextField! + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + self.title = "Bubble Chart" + self.options = [.toggleValues, + .toggleIcons, + .toggleHighlight, + .animateX, + .animateY, + .animateXY, + .saveToGallery, + .togglePinchZoom, + .toggleAutoScaleMinMax, + .toggleShadowColorSameAsCandle, + .toggleData] + + chartView.delegate = self + + chartView.chartDescription?.enabled = false + + chartView.dragEnabled = false + chartView.setScaleEnabled(true) + chartView.maxVisibleCount = 200 + chartView.pinchZoomEnabled = true + + chartView.legend.horizontalAlignment = .right + chartView.legend.verticalAlignment = .top + chartView.legend.orientation = .vertical + chartView.legend.drawInside = false + chartView.legend.font = UIFont(name: "HelveticaNeue-Light", size: 10)! + + chartView.leftAxis.labelFont = UIFont(name: "HelveticaNeue-Light", size: 10)! + chartView.leftAxis.spaceTop = 0.3 + chartView.leftAxis.spaceBottom = 0.3 + chartView.leftAxis.axisMinimum = 0 + + chartView.rightAxis.enabled = false + + chartView.xAxis.labelPosition = .bottom + chartView.xAxis.labelFont = UIFont(name: "HelveticaNeue-Light", size: 10)! + + sliderX.value = 10 + sliderY.value = 50 + slidersValueChanged(nil) + } + + override func updateChartData() { + if self.shouldHideData { + chartView.data = nil + return + } + + self.setDataCount(Int(sliderX.value), range: UInt32(sliderY.value)) + } + + func setDataCount(_ count: Int, range: UInt32) { + let yVals1 = (0.. CandleChartDataEntry in + let mult = range + 1 + let val = Double(arc4random_uniform(40) + mult) + let high = Double(arc4random_uniform(9) + 8) + let low = Double(arc4random_uniform(9) + 8) + let open = Double(arc4random_uniform(6) + 1) + let close = Double(arc4random_uniform(6) + 1) + let even = i % 2 == 0 + + return CandleChartDataEntry(x: Double(i), shadowH: val + high, shadowL: val - low, open: even ? val + open : val - open, close: even ? val - close : val + close, icon: UIImage(named: "icon")!) + } + + let set1 = CandleChartDataSet(values: yVals1, label: "Data Set") + set1.axisDependency = .left + set1.setColor(UIColor(white: 80/255, alpha: 1)) + set1.drawIconsEnabled = false + set1.shadowColor = .darkGray + set1.shadowWidth = 0.7 + set1.decreasingColor = .red + set1.decreasingFilled = true + set1.increasingColor = UIColor(red: 122/255, green: 242/255, blue: 84/255, alpha: 1) + set1.increasingFilled = false + set1.neutralColor = .blue + + let data = CandleChartData(dataSet: set1) + chartView.data = data + } + + override func optionTapped(_ option: Option) { + if .toggleShadowColorSameAsCandle ~= option { + for set in chartView.data!.dataSets as! [CandleChartDataSet] { + set.shadowColorSameAsCandle = !set.shadowColorSameAsCandle + } + chartView.notifyDataSetChanged() + } else { + super.handleOption(option, forChartView: chartView) + } + } + + // MARK: - Actions + @IBAction func slidersValueChanged(_ sender: Any?) { + sliderTextX.text = "\(Int(sliderX.value))" + sliderTextY.text = "\(Int(sliderY.value))" + + self.updateChartData() + }} diff --git a/ChartsDemo/Swift/Demos/ColoredLineChartViewController.swift b/ChartsDemo/Swift/Demos/ColoredLineChartViewController.swift new file mode 100644 index 0000000000..a5309ea707 --- /dev/null +++ b/ChartsDemo/Swift/Demos/ColoredLineChartViewController.swift @@ -0,0 +1,77 @@ +// +// ColoredLineChartViewController.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-04. +// Copyright © 2017 jc. All rights reserved. +// + +import UIKit +import Charts + +class ColoredLineChartViewController: DemoBaseViewController { + @IBOutlet var chartViews: [LineChartView]! + + override func viewDidLoad() { + super.viewDidLoad() + + self.title = "Colored Line Chart" + + let colors = [UIColor(red: 137/255, green: 230/255, blue: 81/255, alpha: 1), + UIColor(red: 240/255, green: 240/255, blue: 30/255, alpha: 1), + UIColor(red: 89/255, green: 199/255, blue: 250/255, alpha: 1), + UIColor(red: 250/255, green: 104/255, blue: 104/255, alpha: 1)] + + for (i, chartView) in chartViews.enumerated() { + let data = dataWithCount(36, range: 100) + data.setValueFont(UIFont(name: "HelveticaNeue", size: 7)!) + + setupChart(chartView, data: data, color: colors[i % colors.count]) + } + } + + func setupChart(_ chart: LineChartView, data: LineChartData, color: UIColor) { + (data.getDataSetByIndex(0) as! LineChartDataSet).circleHoleColor = color + + chart.delegate = self + chart.backgroundColor = color + + chart.chartDescription?.enabled = false + + chart.dragEnabled = true + chart.setScaleEnabled(true) + chart.pinchZoomEnabled = false + chart.setViewPortOffsets(left: 10, top: 0, right: 10, bottom: 0) + + chart.legend.enabled = false + + chart.leftAxis.enabled = false + chart.leftAxis.spaceTop = 0.4 + chart.leftAxis.spaceBottom = 0.4 + chart.rightAxis.enabled = false + chart.xAxis.enabled = false + + chart.data = data + + chart.animate(xAxisDuration: 2.5) + } + + func dataWithCount(_ count: Int, range: UInt32) -> LineChartData { + let yVals = (0.. ChartDataEntry in + let val = Double(arc4random_uniform(range)) + 3 + return ChartDataEntry(x: Double(i), y: val) + } + + let set1 = LineChartDataSet(values: yVals, label: "DataSet 1") + + set1.lineWidth = 1.75 + set1.circleRadius = 5.0 + set1.circleHoleRadius = 2.5 + set1.setColor(.white) + set1.setCircleColor(.white) + set1.highlightColor = .white + set1.drawValuesEnabled = false + + return LineChartData(dataSet: set1) + } +} diff --git a/ChartsDemo/Swift/Demos/CombinedChartViewController.swift b/ChartsDemo/Swift/Demos/CombinedChartViewController.swift new file mode 100644 index 0000000000..d3162293a7 --- /dev/null +++ b/ChartsDemo/Swift/Demos/CombinedChartViewController.swift @@ -0,0 +1,233 @@ +// +// CombinedChartViewController.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-09. +// Copyright © 2017 jc. All rights reserved. +// + +import UIKit +import Charts + +private let ITEM_COUNT = 12 + +class CombinedChartViewController: DemoBaseViewController { + @IBOutlet var chartView: CombinedChartView! + + let months = ["Jan", "Feb", "Mar", + "Apr", "May", "Jun", + "Jul", "Aug", "Sep", + "Oct", "Nov", "Dec"] + + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + self.title = "Combined Chart" + self.options = [.toggleLineValues, + .toggleBarValues, + .saveToGallery, + .toggleData, + .toggleBarBorders, + .removeDataSet] + + chartView.delegate = self + + chartView.chartDescription?.enabled = false + + chartView.drawBarShadowEnabled = false + chartView.highlightFullBarEnabled = false + + + chartView.drawOrder = [DrawOrder.bar.rawValue, + DrawOrder.bubble.rawValue, + DrawOrder.candle.rawValue, + DrawOrder.line.rawValue, + DrawOrder.scatter.rawValue] + + let l = chartView.legend + l.wordWrapEnabled = true + l.horizontalAlignment = .center + l.verticalAlignment = .bottom + l.orientation = .horizontal + l.drawInside = false +// chartView.legend = l + + let rightAxis = chartView.rightAxis + rightAxis.axisMinimum = 0 + + let leftAxis = chartView.leftAxis + leftAxis.axisMinimum = 0 + + let xAxis = chartView.xAxis + xAxis.labelPosition = .bothSided + xAxis.axisMinimum = 0 + xAxis.granularity = 1 + xAxis.valueFormatter = self + + self.updateChartData() + } + + override func updateChartData() { + if self.shouldHideData { + chartView.data = nil + return + } + + self.setChartData() + } + + func setChartData() { + let data = CombinedChartData() + data.lineData = generateLineData() + data.barData = generateBarData() + data.bubbleData = generateBubbleData() + data.scatterData = generateScatterData() + data.candleData = generateCandleData() + + chartView.xAxis.axisMaximum = data.xMax + 0.25 + + chartView.data = data + } + + override func optionTapped(_ option: Option) { + switch option { + case .toggleLineValues: + for set in chartView.data!.dataSets { + if let set = set as? LineChartDataSet { + set.drawValuesEnabled = !set .drawValuesEnabled + + } + } + chartView.setNeedsDisplay() + + case .toggleBarValues: + for set in chartView.data!.dataSets { + if let set = set as? BarChartDataSet { + set.drawValuesEnabled = !set .drawValuesEnabled + } + } + chartView.setNeedsDisplay() + + case .removeDataSet: + let rnd = Int(arc4random_uniform(UInt32(chartView.data!.dataSetCount))) + chartView.data?.removeDataSet(chartView.data!.getDataSetByIndex(rnd)) + chartView.data?.notifyDataChanged() + chartView.notifyDataSetChanged() + + default: + super.handleOption(option, forChartView: chartView) + } + } + + func generateLineData() -> LineChartData { + let entries = (0.. ChartDataEntry in + return ChartDataEntry(x: Double(i) + 0.5, y: Double(arc4random_uniform(15) + 5)) + } + + let set = LineChartDataSet(values: entries, label: "Line DataSet") + set.setColor(UIColor(red: 240/255, green: 238/255, blue: 70/255, alpha: 1)) + set.lineWidth = 2.5 + set.setCircleColor(UIColor(red: 240/255, green: 238/255, blue: 70/255, alpha: 1)) + set.circleRadius = 5 + set.circleHoleRadius = 2.5 + set.fillColor = UIColor(red: 240/255, green: 238/255, blue: 70/255, alpha: 1) + set.mode = .cubicBezier + set.drawValuesEnabled = true + set.valueFont = .systemFont(ofSize: 10) + set.valueTextColor = UIColor(red: 240/255, green: 238/255, blue: 70/255, alpha: 1) + + set.axisDependency = .left + + return LineChartData(dataSet: set) + } + + func generateBarData() -> BarChartData { + let entries1 = (0.. BarChartDataEntry in + return BarChartDataEntry(x: 0, y: Double(arc4random_uniform(25) + 25)) + } + let entries2 = (0.. BarChartDataEntry in + return BarChartDataEntry(x: 0, yValues: [Double(arc4random_uniform(13) + 12), Double(arc4random_uniform(13) + 12)]) + } + + let set1 = BarChartDataSet(values: entries1, label: "Bar 1") + set1.setColor(UIColor(red: 60/255, green: 220/255, blue: 78/255, alpha: 1)) + set1.valueTextColor = UIColor(red: 60/255, green: 220/255, blue: 78/255, alpha: 1) + set1.valueFont = .systemFont(ofSize: 10) + set1.axisDependency = .left + + let set2 = BarChartDataSet(values: entries2, label: "") + set2.stackLabels = ["Stack 1", "Stack 2"] + set2.colors = [UIColor(red: 61/255, green: 165/255, blue: 255/255, alpha: 1), + UIColor(red: 23/255, green: 197/255, blue: 255/255, alpha: 1) + ] + set2.valueTextColor = UIColor(red: 61/255, green: 165/255, blue: 255/255, alpha: 1) + set2.valueFont = .systemFont(ofSize: 10) + set2.axisDependency = .left + + let groupSpace = 0.06 + let barSpace = 0.02 // x2 dataset + let barWidth = 0.45 // x2 dataset + // (0.45 + 0.02) * 2 + 0.06 = 1.00 -> interval per "group" + + let data = BarChartData(dataSets: [set1, set2]) + data.barWidth = barWidth + + // make this BarData object grouped + data.groupBars(fromX: 0, groupSpace: groupSpace, barSpace: barSpace) + + return data + } + + func generateScatterData() -> ScatterChartData { + let entries = stride(from: 0.0, to: Double(ITEM_COUNT), by: 0.5).map { (i) -> ChartDataEntry in + return ChartDataEntry(x: i+0.25, y: Double(arc4random_uniform(10) + 55)) + } + + let set = ScatterChartDataSet(values: entries, label: "Scatter DataSet") + set.colors = ChartColorTemplates.material() + set.scatterShapeSize = 4.5 + set.drawValuesEnabled = false + set.valueFont = .systemFont(ofSize: 10) + + return ScatterChartData(dataSet: set) + } + + func generateCandleData() -> CandleChartData { + let entries = stride(from: 0, to: ITEM_COUNT, by: 2).map { (i) -> CandleChartDataEntry in + return CandleChartDataEntry(x: Double(i+1), shadowH: 90, shadowL: 70, open: 85, close: 75) + } + + let set = CandleChartDataSet(values: entries, label: "Candle DataSet") + set.setColor(UIColor(red: 80/255, green: 80/255, blue: 80/255, alpha: 1)) + set.decreasingColor = UIColor(red: 142/255, green: 150/255, blue: 175/255, alpha: 1) + set.shadowColor = .darkGray + set.valueFont = .systemFont(ofSize: 10) + set.drawValuesEnabled = false + + return CandleChartData(dataSet: set) + } + + func generateBubbleData() -> BubbleChartData { + let entries = (0.. BubbleChartDataEntry in + return BubbleChartDataEntry(x: Double(i) + 0.5, + y: Double(arc4random_uniform(10) + 105), + size: CGFloat(arc4random_uniform(50) + 105)) + } + + let set = BubbleChartDataSet(values: entries, label: "Bubble DataSet") + set.setColors(ChartColorTemplates.vordiplom(), alpha: 1) + set.valueTextColor = .white + set.valueFont = .systemFont(ofSize: 10) + set.drawValuesEnabled = true + + return BubbleChartData(dataSet: set) + } +} + +extension CombinedChartViewController: IAxisValueFormatter { + func stringForValue(_ value: Double, axis: AxisBase?) -> String { + return months[Int(value) % months.count] + } +} diff --git a/ChartsDemo/Swift/Demos/CubicLineChartViewController.swift b/ChartsDemo/Swift/Demos/CubicLineChartViewController.swift new file mode 100644 index 0000000000..627d13d08d --- /dev/null +++ b/ChartsDemo/Swift/Demos/CubicLineChartViewController.swift @@ -0,0 +1,155 @@ +// +// CubicLineChartViewController.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-09. +// Copyright © 2017 jc. All rights reserved. +// + +import UIKit +import Charts + +private class CubicLineSampleFillFormatter: IFillFormatter { + func getFillLinePosition(dataSet: ILineChartDataSet, dataProvider: LineChartDataProvider) -> CGFloat { + return -10 + } +} + +class CubicLineChartViewController: DemoBaseViewController { + + @IBOutlet var chartView: LineChartView! + @IBOutlet var sliderX: UISlider! + @IBOutlet var sliderY: UISlider! + @IBOutlet var sliderTextX: UITextField! + @IBOutlet var sliderTextY: UITextField! + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + self.title = "Cubic Line Chart" + + self.options = [.toggleValues, + .toggleFilled, + .toggleCircles, + .toggleCubic, + .toggleHorizontalCubic, + .toggleStepped, + .toggleHighlight, + .animateX, + .animateY, + .animateXY, + .saveToGallery, + .togglePinchZoom, + .toggleAutoScaleMinMax, + .toggleData] + + chartView.delegate = self + + chartView.setViewPortOffsets(left: 0, top: 20, right: 0, bottom: 0) + chartView.backgroundColor = UIColor(red: 104/255, green: 241/255, blue: 175/255, alpha: 1) + + chartView.dragEnabled = true + chartView.setScaleEnabled(true) + chartView.pinchZoomEnabled = false + chartView.maxHighlightDistance = 300 + + chartView.xAxis.enabled = false + + let yAxis = chartView.leftAxis + yAxis.labelFont = UIFont(name: "HelveticaNeue-Light", size:12)! + yAxis.setLabelCount(6, force: false) + yAxis.labelTextColor = .white + yAxis.labelPosition = .insideChart + yAxis.axisLineColor = .white + + chartView.rightAxis.enabled = false + chartView.legend.enabled = false + + sliderX.value = 45 + sliderY.value = 100 + self.slidersValueChanged(nil) + + chartView.animate(xAxisDuration: 2, yAxisDuration: 2) + } + + override func updateChartData() { + if self.shouldHideData { + chartView.data = nil + return + } + + self.setDataCount(Int(sliderX.value + 1), range: UInt32(sliderY.value)) + } + + func setDataCount(_ count: Int, range: UInt32) { + let yVals1 = (0.. ChartDataEntry in + let mult = range + 1 + let val = Double(arc4random_uniform(mult) + 20) + return ChartDataEntry(x: Double(i), y: val) + } + + let set1 = LineChartDataSet(values: yVals1, label: "DataSet 1") + set1.mode = .cubicBezier + set1.drawCirclesEnabled = false + set1.lineWidth = 1.8 + set1.circleRadius = 4 + set1.setCircleColor(.white) + set1.highlightColor = UIColor(red: 244/255, green: 117/255, blue: 117/255, alpha: 1) + set1.fillColor = .white + set1.fillAlpha = 1 + set1.drawHorizontalHighlightIndicatorEnabled = false + set1.fillFormatter = CubicLineSampleFillFormatter() + + let data = LineChartData(dataSet: set1) + data.setValueFont(UIFont(name: "HelveticaNeue-Light", size: 9)!) + data.setDrawValues(false) + + chartView.data = data + } + + override func optionTapped(_ option: Option) { + switch option { + case .toggleFilled: + for set in chartView.data!.dataSets as! [LineChartDataSet] { + set.drawFilledEnabled = !set.drawFilledEnabled + } + chartView.setNeedsDisplay() + + case .toggleCircles: + for set in chartView.data!.dataSets as! [LineChartDataSet] { + set.drawCirclesEnabled = !set.drawCirclesEnabled + } + chartView.setNeedsDisplay() + + case .toggleCubic: + for set in chartView.data!.dataSets as! [LineChartDataSet] { + set.mode = (set.mode == .cubicBezier) ? .linear : .cubicBezier + } + chartView.setNeedsDisplay() + + case .toggleStepped: + for set in chartView.data!.dataSets as! [LineChartDataSet] { + set.mode = (set.mode == .stepped) ? .linear : .stepped + } + chartView.setNeedsDisplay() + + case .toggleHorizontalCubic: + for set in chartView.data!.dataSets as! [LineChartDataSet] { + set.mode = (set.mode == .cubicBezier) ? .horizontalBezier : .cubicBezier + } + chartView.setNeedsDisplay() + + default: + super.handleOption(option, forChartView: chartView) + } + } + + // MARK: - Actions + @IBAction func slidersValueChanged(_ sender: Any?) { + sliderTextX.text = "\(Int(sliderX.value))" + sliderTextY.text = "\(Int(sliderY.value))" + + self.updateChartData() + } +} diff --git a/ChartsDemo/Swift/Demos/HalfPieChartViewController.swift b/ChartsDemo/Swift/Demos/HalfPieChartViewController.swift new file mode 100644 index 0000000000..7c4ed80ba7 --- /dev/null +++ b/ChartsDemo/Swift/Demos/HalfPieChartViewController.swift @@ -0,0 +1,142 @@ +// +// HalfPieChartViewController.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-09. +// Copyright © 2017 jc. All rights reserved. +// + +import UIKit +import Charts + +class HalfPieChartViewController: DemoBaseViewController { + + @IBOutlet var chartView: PieChartView! + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + self.title = "Half Pie Bar Chart" + + self.options = [.toggleValues, + .toggleXValues, + .togglePercent, + .toggleHole, + .animateX, + .animateY, + .animateXY, + .spin, + .drawCenter, + .saveToGallery, + .toggleData] + + self.setup(pieChartView: chartView) + + chartView.delegate = self + + chartView.holeColor = .white + chartView.transparentCircleColor = NSUIColor.white.withAlphaComponent(0.43) + chartView.holeRadiusPercent = 0.58 + chartView.rotationEnabled = false + chartView.highlightPerTapEnabled = true + + chartView.maxAngle = 180 // Half chart + chartView.rotationAngle = 180 // Rotate to make the half on the upper side + chartView.centerTextOffset = CGPoint(x: 0, y: -20) + + let l = chartView.legend + l.horizontalAlignment = .center + l.verticalAlignment = .top + l.orientation = .horizontal + l.drawInside = false + l.xEntrySpace = 7 + l.yEntrySpace = 0 + l.yOffset = 0 +// chartView.legend = l + + // entry label styling + chartView.entryLabelColor = .white + chartView.entryLabelFont = UIFont(name:"HelveticaNeue-Light", size:12)! + + self.updateChartData() + + chartView.animate(xAxisDuration: 1.4, easingOption: .easeOutBack) + } + + override func updateChartData() { + if self.shouldHideData { + chartView.data = nil + return + } + + self.setDataCount(4, range: 100) + } + + func setDataCount(_ count: Int, range: UInt32) { + let entries = (0.. PieChartDataEntry in + // IMPORTANT: In a PieChart, no values (Entry) should have the same xIndex (even if from different DataSets), since no values can be drawn above each other. + return PieChartDataEntry(value: Double(arc4random_uniform(range) + range / 5), + label: parties[i % parties.count]) + } + + let set = PieChartDataSet(values: entries, label: "Election Results") + set.sliceSpace = 3 + set.selectionShift = 5 + set.colors = ChartColorTemplates.material() + + let data = PieChartData(dataSet: set) + + let pFormatter = NumberFormatter() + pFormatter.numberStyle = .percent + pFormatter.maximumFractionDigits = 1 + pFormatter.multiplier = 1 + pFormatter.percentSymbol = " %" + data.setValueFormatter(DefaultValueFormatter(formatter: pFormatter)) + + data.setValueFont(UIFont(name: "HelveticaNeue-Light", size: 11)!) + data.setValueTextColor(.white) + + chartView.data = data + + chartView.setNeedsDisplay() + } + + override func optionTapped(_ option: Option) { + switch option { + case .toggleXValues: + chartView.drawEntryLabelsEnabled = !chartView.drawEntryLabelsEnabled + chartView.setNeedsDisplay() + + case .togglePercent: + chartView.usePercentValuesEnabled = !chartView.usePercentValuesEnabled + chartView.setNeedsDisplay() + + case .toggleHole: + chartView.drawHoleEnabled = !chartView.drawHoleEnabled + chartView.setNeedsDisplay() + + case .drawCenter: + chartView.drawCenterTextEnabled = !chartView.drawCenterTextEnabled + chartView.setNeedsDisplay() + + case .animateX: + chartView.animate(xAxisDuration: 1.4) + + case .animateY: + chartView.animate(yAxisDuration: 1.4) + + case .animateXY: + chartView.animate(xAxisDuration: 1.4, yAxisDuration: 1.4) + + case .spin: + chartView.spin(duration: 2, + fromAngle: chartView.rotationAngle, + toAngle: chartView.rotationAngle + 360, + easingOption: .easeInCubic) + + default: + handleOption(option, forChartView: chartView) + } + } +} diff --git a/ChartsDemo/Swift/Demos/HorizontalBarChartViewController.swift b/ChartsDemo/Swift/Demos/HorizontalBarChartViewController.swift new file mode 100644 index 0000000000..2dbcab9491 --- /dev/null +++ b/ChartsDemo/Swift/Demos/HorizontalBarChartViewController.swift @@ -0,0 +1,124 @@ +// +// HorizontalBarChartViewController.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-09. +// Copyright © 2017 jc. All rights reserved. +// + +import UIKit +import Charts + +class HorizontalBarChartViewController: DemoBaseViewController { + + @IBOutlet var chartView: HorizontalBarChartView! + @IBOutlet var sliderX: UISlider! + @IBOutlet var sliderY: UISlider! + @IBOutlet var sliderTextX: UITextField! + @IBOutlet var sliderTextY: UITextField! + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + self.title = "Horizontal Bar Char" + self.options = [.toggleValues, + .toggleIcons, + .toggleHighlight, + .animateX, + .animateY, + .animateXY, + .saveToGallery, + .togglePinchZoom, + .toggleAutoScaleMinMax, + .toggleData, + .toggleBarBorders] + + self.setup(barLineChartView: chartView) + + chartView.delegate = self + + chartView.drawBarShadowEnabled = false + chartView.drawValueAboveBarEnabled = true + + chartView.maxVisibleCount = 60 + + let xAxis = chartView.xAxis + xAxis.labelPosition = .bottom + xAxis.labelFont = .systemFont(ofSize: 10) + xAxis.drawAxisLineEnabled = true + xAxis.granularity = 10 + + let leftAxis = chartView.leftAxis + leftAxis.labelFont = .systemFont(ofSize: 10) + leftAxis.drawAxisLineEnabled = true + leftAxis.drawGridLinesEnabled = true + leftAxis.axisMinimum = 0 + + let rightAxis = chartView.rightAxis + rightAxis.enabled = true + rightAxis.labelFont = .systemFont(ofSize: 10) + rightAxis.drawAxisLineEnabled = true + rightAxis.axisMinimum = 0 + + let l = chartView.legend + l.horizontalAlignment = .left + l.verticalAlignment = .bottom + l.orientation = .horizontal + l.drawInside = false + l.form = .square + l.formSize = 8 + l.font = UIFont(name: "HelveticaNeue-Light", size: 11)! + l.xEntrySpace = 4 +// chartView.legend = l + + chartView.fitBars = true + + sliderX.value = 12 + sliderY.value = 50 + slidersValueChanged(nil) + + chartView.animate(yAxisDuration: 2.5) + } + + override func updateChartData() { + if self.shouldHideData { + chartView.data = nil + return + } + + self.setDataCount(Int(sliderX.value) + 1, range: UInt32(sliderY.value)) + } + + func setDataCount(_ count: Int, range: UInt32) { + let barWidth = 9.0 + let spaceForBar = 10.0 + + let yVals = (0.. BarChartDataEntry in + let mult = range + 1 + let val = Double(arc4random_uniform(mult)) + return BarChartDataEntry(x: Double(i)*spaceForBar, y: val, icon: #imageLiteral(resourceName: "icon")) + } + + let set1 = BarChartDataSet(values: yVals, label: "DataSet") + set1.drawIconsEnabled = false + + let data = BarChartData(dataSet: set1) + data.setValueFont(UIFont(name:"HelveticaNeue-Light", size:10)!) + data.barWidth = barWidth + + chartView.data = data + } + + override func optionTapped(_ option: Option) { + super.handleOption(option, forChartView: chartView) + } + + // MARK: - Actions + @IBAction func slidersValueChanged(_ sender: Any?) { + sliderTextX.text = "\(Int(sliderX.value))" + sliderTextY.text = "\(Int(sliderY.value))" + + self.updateChartData() + } +} diff --git a/ChartsDemo/Swift/Demos/LineChart1ViewController.swift b/ChartsDemo/Swift/Demos/LineChart1ViewController.swift new file mode 100644 index 0000000000..bf5eb7f67d --- /dev/null +++ b/ChartsDemo/Swift/Demos/LineChart1ViewController.swift @@ -0,0 +1,187 @@ +// +// LineChart1ViewController.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-09. +// Copyright © 2017 jc. All rights reserved. +// + +import UIKit +import Charts + +class LineChart1ViewController: DemoBaseViewController { + + @IBOutlet var chartView: LineChartView! + @IBOutlet var sliderX: UISlider! + @IBOutlet var sliderY: UISlider! + @IBOutlet var sliderTextX: UITextField! + @IBOutlet var sliderTextY: UITextField! + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + self.title = "Line Chart 1" + self.options = [.toggleValues, + .toggleFilled, + .toggleCircles, + .toggleCubic, + .toggleHorizontalCubic, + .toggleIcons, + .toggleStepped, + .toggleHighlight, + .animateX, + .animateY, + .animateXY, + .saveToGallery, + .togglePinchZoom, + .toggleAutoScaleMinMax, + .toggleData] + + chartView.delegate = self + + chartView.chartDescription?.enabled = false + chartView.dragEnabled = true + chartView.setScaleEnabled(true) + chartView.pinchZoomEnabled = true + + // x-axis limit line + let llXAxis = ChartLimitLine(limit: 10, label: "Index 10") + llXAxis.lineWidth = 4 + llXAxis.lineDashLengths = [10, 10, 0] + llXAxis.labelPosition = .rightBottom + llXAxis.valueFont = .systemFont(ofSize: 10) + + chartView.xAxis.gridLineDashLengths = [10, 10] + chartView.xAxis.gridLineDashPhase = 0 + + let ll1 = ChartLimitLine(limit: 150, label: "Upper Limit") + ll1.lineWidth = 4 + ll1.lineDashLengths = [5, 5] + ll1.labelPosition = .rightTop + ll1.valueFont = .systemFont(ofSize: 10) + + let ll2 = ChartLimitLine(limit: -30, label: "Lower Limit") + ll2.lineWidth = 4 + ll2.lineDashLengths = [5,5] + ll2.labelPosition = .rightBottom + ll2.valueFont = .systemFont(ofSize: 10) + + let leftAxis = chartView.leftAxis + leftAxis.removeAllLimitLines() + leftAxis.addLimitLine(ll1) + leftAxis.addLimitLine(ll2) + leftAxis.axisMaximum = 200 + leftAxis.axisMinimum = -50 + leftAxis.gridLineDashLengths = [5, 5] + leftAxis.drawLimitLinesBehindDataEnabled = true + + chartView.rightAxis.enabled = false + + //[_chartView.viewPortHandler setMaximumScaleY: 2.f]; + //[_chartView.viewPortHandler setMaximumScaleX: 2.f]; + + let marker = BalloonMarker(color: UIColor(white: 180/255, alpha: 1), + font: .systemFont(ofSize: 12), + textColor: .white, + insets: UIEdgeInsets(top: 8, left: 8, bottom: 20, right: 8)) + marker.chartView = chartView + marker.minimumSize = CGSize(width: 80, height: 40) + chartView.marker = marker + + chartView.legend.form = .line + + sliderX.value = 45 + sliderY.value = 100 + slidersValueChanged(nil) + + chartView.animate(xAxisDuration: 2.5) + } + + override func updateChartData() { + if self.shouldHideData { + chartView.data = nil + return + } + + self.setDataCount(Int(sliderX.value), range: UInt32(sliderY.value)) + } + + func setDataCount(_ count: Int, range: UInt32) { + let values = (0.. ChartDataEntry in + let val = Double(arc4random_uniform(range) + 3) + return ChartDataEntry(x: Double(i), y: val, icon: #imageLiteral(resourceName: "icon")) + } + + let set1 = LineChartDataSet(values: values, label: "DataSet 1") + set1.drawIconsEnabled = false + + set1.lineDashLengths = [5, 2.5] + set1.highlightLineDashLengths = [5, 2.5] + set1.setColor(.black) + set1.setCircleColor(.black) + set1.lineWidth = 1 + set1.circleRadius = 3 + set1.drawCircleHoleEnabled = false + set1.valueFont = .systemFont(ofSize: 9) + set1.formLineDashLengths = [5, 2.5] + set1.formLineWidth = 1 + set1.formLineWidth = 15 + + let gradientColors = [ChartColorTemplates.colorFromString("#00ff0000").cgColor, + ChartColorTemplates.colorFromString("#ffff0000").cgColor] + let gradient = CGGradient(colorsSpace: nil, colors: gradientColors as CFArray, locations: nil)! + + set1.fillAlpha = 1 + set1.fill = Fill(linearGradient: gradient, angle: 90) //.linearGradient(gradient, angle: 90) + set1.drawFilledEnabled = true + + let data = LineChartData(dataSet: set1) + + chartView.data = data + } + + override func optionTapped(_ option: Option) { + switch option { + case .toggleFilled: + for set in chartView.data!.dataSets as! [LineChartDataSet] { + set.drawFilledEnabled = !set.drawFilledEnabled + } + chartView.setNeedsDisplay() + + case .toggleCircles: + for set in chartView.data!.dataSets as! [LineChartDataSet] { + set.drawCirclesEnabled = !set.drawCirclesEnabled + } + chartView.setNeedsDisplay() + + case .toggleCubic: + for set in chartView.data!.dataSets as! [LineChartDataSet] { + set.mode = (set.mode == .cubicBezier) ? .linear : .cubicBezier + } + chartView.setNeedsDisplay() + + case .toggleStepped: + for set in chartView.data!.dataSets as! [LineChartDataSet] { + set.mode = (set.mode == .stepped) ? .linear : .stepped + } + chartView.setNeedsDisplay() + + case .toggleHorizontalCubic: + for set in chartView.data!.dataSets as! [LineChartDataSet] { + set.mode = (set.mode == .cubicBezier) ? .horizontalBezier : .cubicBezier + } + chartView.setNeedsDisplay() + + default: + super.handleOption(option, forChartView: chartView) + } + } + + @IBAction func slidersValueChanged(_ sender: Any?) { + sliderTextX.text = "\(Int(sliderX.value))" + sliderTextY.text = "\(Int(sliderY.value))" + + self.updateChartData() + } +} diff --git a/ChartsDemo/Swift/Demos/LineChart2ViewController.swift b/ChartsDemo/Swift/Demos/LineChart2ViewController.swift new file mode 100644 index 0000000000..564d50f66d --- /dev/null +++ b/ChartsDemo/Swift/Demos/LineChart2ViewController.swift @@ -0,0 +1,200 @@ +// +// LineChart2ViewController.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-09. +// Copyright © 2017 jc. All rights reserved. +// + +import UIKit +import Charts + +class LineChart2ViewController: DemoBaseViewController { + + @IBOutlet var chartView: LineChartView! + @IBOutlet var sliderX: UISlider! + @IBOutlet var sliderY: UISlider! + @IBOutlet var sliderTextX: UITextField! + @IBOutlet var sliderTextY: UITextField! + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + self.title = "Line Chart 2" + self.options = [.toggleValues, + .toggleFilled, + .toggleCircles, + .toggleCubic, + .toggleHorizontalCubic, + .toggleStepped, + .toggleHighlight, + .animateX, + .animateY, + .animateXY, + .saveToGallery, + .togglePinchZoom, + .toggleAutoScaleMinMax, + .toggleData] + + chartView.delegate = self + + chartView.chartDescription?.enabled = false + chartView.dragEnabled = true + chartView.setScaleEnabled(true) + chartView.pinchZoomEnabled = true + + let l = chartView.legend + l.form = .line + l.font = UIFont(name: "HelveticaNeue-Light", size: 11)! + l.textColor = .white + l.horizontalAlignment = .left + l.verticalAlignment = .bottom + l.orientation = .horizontal + l.drawInside = false + + let xAxis = chartView.xAxis + xAxis.labelFont = .systemFont(ofSize: 11) + xAxis.labelTextColor = .white + xAxis.drawAxisLineEnabled = false + + let leftAxis = chartView.leftAxis + leftAxis.labelTextColor = UIColor(red: 51/255, green: 181/255, blue: 229/255, alpha: 1) + leftAxis.axisMaximum = 200 + leftAxis.axisMinimum = 0 + leftAxis.drawGridLinesEnabled = true + leftAxis.granularityEnabled = true + + let rightAxis = chartView.rightAxis + rightAxis.labelTextColor = .red + rightAxis.axisMaximum = 900 + rightAxis.axisMinimum = -200 + rightAxis.granularityEnabled = false + + sliderX.value = 20 + sliderY.value = 30 + slidersValueChanged(nil) + + chartView.animate(xAxisDuration: 2.5) + } + + override func updateChartData() { + if self.shouldHideData { + chartView.data = nil + return + } + + self.setDataCount(Int(sliderX.value + 1), range: UInt32(sliderY.value)) + } + + func setDataCount(_ count: Int, range: UInt32) { + let yVals1 = (0.. ChartDataEntry in + let mult = range / 2 + let val = Double(arc4random_uniform(mult) + 50) + return ChartDataEntry(x: Double(i), y: val) + } + let yVals2 = (0.. ChartDataEntry in + let val = Double(arc4random_uniform(range) + 450) + return ChartDataEntry(x: Double(i), y: val) + } + let yVals3 = (0.. ChartDataEntry in + let val = Double(arc4random_uniform(range) + 500) + return ChartDataEntry(x: Double(i), y: val) + } + + let set1 = LineChartDataSet(values: yVals1, label: "DataSet 1") + set1.axisDependency = .left + set1.setColor(UIColor(red: 51/255, green: 181/255, blue: 229/255, alpha: 1)) + set1.setCircleColor(.white) + set1.lineWidth = 2 + set1.circleRadius = 3 + set1.fillAlpha = 65/255 + set1.fillColor = UIColor(red: 51/255, green: 181/255, blue: 229/255, alpha: 1) + set1.highlightColor = UIColor(red: 244/255, green: 117/255, blue: 117/255, alpha: 1) + set1.drawCircleHoleEnabled = false + + let set2 = LineChartDataSet(values: yVals2, label: "DataSet 2") + set2.axisDependency = .right + set2.setColor(.red) + set2.setCircleColor(.white) + set2.lineWidth = 2 + set2.circleRadius = 3 + set2.fillAlpha = 65/255 + set2.fillColor = .red + set2.highlightColor = UIColor(red: 244/255, green: 117/255, blue: 117/255, alpha: 1) + set2.drawCircleHoleEnabled = false + + let set3 = LineChartDataSet(values: yVals3, label: "DataSet 3") + set3.axisDependency = .right + set3.setColor(.yellow) + set3.setCircleColor(.white) + set3.lineWidth = 2 + set3.circleRadius = 3 + set3.fillAlpha = 65/255 + set3.fillColor = UIColor.yellow.withAlphaComponent(200/255) + set3.highlightColor = UIColor(red: 244/255, green: 117/255, blue: 117/255, alpha: 1) + set3.drawCircleHoleEnabled = false + + let data = LineChartData(dataSets: [set1, set2, set3]) + data.setValueTextColor(.white) + data.setValueFont(.systemFont(ofSize: 9)) + + chartView.data = data + } + + override func optionTapped(_ option: Option) { + switch option { + case .toggleFilled: + for set in chartView.data!.dataSets as! [LineChartDataSet] { + set.drawFilledEnabled = !set.drawFilledEnabled + } + chartView.setNeedsDisplay() + + case .toggleCircles: + for set in chartView.data!.dataSets as! [LineChartDataSet] { + set.drawCirclesEnabled = !set.drawCirclesEnabled + } + chartView.setNeedsDisplay() + + case .toggleCubic: + for set in chartView.data!.dataSets as! [LineChartDataSet] { + set.mode = (set.mode == .cubicBezier) ? .linear : .cubicBezier + } + chartView.setNeedsDisplay() + + case .toggleStepped: + for set in chartView.data!.dataSets as! [LineChartDataSet] { + set.mode = (set.mode == .stepped) ? .linear : .stepped + } + chartView.setNeedsDisplay() + + case .toggleHorizontalCubic: + for set in chartView.data!.dataSets as! [LineChartDataSet] { + set.mode = (set.mode == .cubicBezier) ? .horizontalBezier : .cubicBezier + } + chartView.setNeedsDisplay() + + default: + super.handleOption(option, forChartView: chartView) + } + } + + @IBAction func slidersValueChanged(_ sender: Any?) { + sliderTextX.text = "\(Int(sliderX.value))" + sliderTextY.text = "\(Int(sliderY.value))" + + self.updateChartData() + } +//} + // TODO: Declarations in extensions cannot override yet. +//extension LineChart2ViewController { + override func chartValueSelected(_ chartView: ChartViewBase, entry: ChartDataEntry, highlight: Highlight) { + super.chartValueSelected(chartView, entry: entry, highlight: highlight) + + self.chartView.centerViewToAnimated(xValue: entry.x, yValue: entry.y, + axis: self.chartView.data!.getDataSetByIndex(highlight.dataSetIndex).axisDependency, + duration: 1) + //[_chartView moveViewToAnimatedWithXValue:entry.x yValue:entry.y axis:[_chartView.data getDataSetByIndex:dataSetIndex].axisDependency duration:1.0]; + //[_chartView zoomAndCenterViewAnimatedWithScaleX:1.8 scaleY:1.8 xValue:entry.x yValue:entry.y axis:[_chartView.data getDataSetByIndex:dataSetIndex].axisDependency duration:1.0]; + } +} diff --git a/ChartsDemo/Swift/Demos/LineChartFilledViewController.swift b/ChartsDemo/Swift/Demos/LineChartFilledViewController.swift new file mode 100644 index 0000000000..11726e4e4f --- /dev/null +++ b/ChartsDemo/Swift/Demos/LineChartFilledViewController.swift @@ -0,0 +1,117 @@ +// +// LineChartFilledViewController.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-09. +// Copyright © 2017 jc. All rights reserved. +// + +import UIKit +import Charts + +class LineChartFilledViewController: DemoBaseViewController { + + @IBOutlet var chartView: LineChartView! + @IBOutlet var sliderX: UISlider! + @IBOutlet var sliderY: UISlider! + @IBOutlet var sliderTextX: UITextField! + @IBOutlet var sliderTextY: UITextField! + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + self.title = "Filled Line Chart" + + chartView.delegate = self + + chartView.backgroundColor = .white + chartView.gridBackgroundColor = UIColor(red: 51/255, green: 181/255, blue: 229/255, alpha: 150/255) + chartView.drawGridBackgroundEnabled = true + + chartView.drawBordersEnabled = true + + chartView.chartDescription?.enabled = false + + chartView.pinchZoomEnabled = false + chartView.dragEnabled = true + chartView.setScaleEnabled(true) + + chartView.legend.enabled = false + + chartView.xAxis.enabled = false + + let leftAxis = chartView.leftAxis + leftAxis.axisMaximum = 900 + leftAxis.axisMinimum = -250 + leftAxis.drawAxisLineEnabled = false + + chartView.rightAxis.enabled = false + + sliderX.value = 100 + sliderY.value = 60 + slidersValueChanged(nil) + } + + override func updateChartData() { + if self.shouldHideData { + chartView.data = nil + return + } + + self.setDataCount(Int(sliderX.value), range: UInt32(sliderY.value)) + } + + func setDataCount(_ count: Int, range: UInt32) { + let yVals1 = (0.. ChartDataEntry in + let val = Double(arc4random_uniform(range) + 50) + return ChartDataEntry(x: Double(i), y: val) + } + let yVals2 = (0.. ChartDataEntry in + let val = Double(arc4random_uniform(range) + 450) + return ChartDataEntry(x: Double(i), y: val) + } + + let set1 = LineChartDataSet(values: yVals1, label: "DataSet 1") + set1.axisDependency = .left + set1.setColor(UIColor(red: 255/255, green: 241/255, blue: 46/255, alpha: 1)) + set1.drawCirclesEnabled = false + set1.lineWidth = 2 + set1.circleRadius = 3 + set1.fillAlpha = 1 + set1.drawFilledEnabled = true + set1.fillColor = .white + set1.highlightColor = UIColor(red: 244/255, green: 117/255, blue: 117/255, alpha: 1) + set1.drawCircleHoleEnabled = false + set1.fillFormatter = DefaultFillFormatter { _,_ -> CGFloat in + return CGFloat(self.chartView.leftAxis.axisMinimum) + } + + let set2 = LineChartDataSet(values: yVals2, label: "DataSet 2") + set2.axisDependency = .left + set2.setColor(UIColor(red: 255/255, green: 241/255, blue: 46/255, alpha: 1)) + set2.drawCirclesEnabled = false + set2.lineWidth = 2 + set2.circleRadius = 3 + set2.fillAlpha = 1 + set2.drawFilledEnabled = true + set2.fillColor = .white + set2.highlightColor = UIColor(red: 244/255, green: 117/255, blue: 117/255, alpha: 1) + set2.drawCircleHoleEnabled = false + set2.fillFormatter = DefaultFillFormatter { _,_ -> CGFloat in + return CGFloat(self.chartView.leftAxis.axisMaximum) + } + + let data = LineChartData(dataSets: [set1, set2]) + data.setDrawValues(false) + + chartView.data = data + } + + @IBAction func slidersValueChanged(_ sender: Any?) { + sliderTextX.text = "\(Int(sliderX.value))" + sliderTextY.text = "\(Int(sliderY.value))" + + self.updateChartData() + } +} diff --git a/ChartsDemo/Swift/Demos/LineChartTimeViewController.swift b/ChartsDemo/Swift/Demos/LineChartTimeViewController.swift new file mode 100644 index 0000000000..1b4c425ba6 --- /dev/null +++ b/ChartsDemo/Swift/Demos/LineChartTimeViewController.swift @@ -0,0 +1,161 @@ +// +// LineChartTimeViewController.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-09. +// Copyright © 2017 jc. All rights reserved. +// + +import UIKit +import Charts + +class LineChartTimeViewController: DemoBaseViewController { + @IBOutlet var chartView: LineChartView! + @IBOutlet var sliderX: UISlider! + @IBOutlet var sliderTextX: UITextField! + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + self.title = "Line Chart 2" + self.options = [.toggleValues, + .toggleFilled, + .toggleCircles, + .toggleCubic, + .toggleHorizontalCubic, + .toggleStepped, + .toggleHighlight, + .animateX, + .animateY, + .animateXY, + .saveToGallery, + .togglePinchZoom, + .toggleAutoScaleMinMax, + .toggleData] + + chartView.delegate = self + + chartView.chartDescription?.enabled = false + + chartView.dragEnabled = true + chartView.setScaleEnabled(true) + chartView.pinchZoomEnabled = false + chartView.highlightPerDragEnabled = true + + chartView.backgroundColor = .white + + chartView.legend.enabled = false + + let xAxis = chartView.xAxis + xAxis.labelPosition = .topInside + xAxis.labelFont = .systemFont(ofSize: 10, weight: .light) + xAxis.labelTextColor = UIColor(red: 255/255, green: 192/255, blue: 56/255, alpha: 1) + xAxis.drawAxisLineEnabled = false + xAxis.drawGridLinesEnabled = true + xAxis.centerAxisLabelsEnabled = true + xAxis.granularity = 3600 + xAxis.valueFormatter = DateValueFormatter() + + let leftAxis = chartView.leftAxis + leftAxis.labelPosition = .insideChart + leftAxis.labelFont = .systemFont(ofSize: 12, weight: .light) + leftAxis.drawGridLinesEnabled = true + leftAxis.granularityEnabled = true + leftAxis.axisMinimum = 0 + leftAxis.axisMaximum = 170 + leftAxis.yOffset = -9 + leftAxis.labelTextColor = UIColor(red: 255/255, green: 192/255, blue: 56/255, alpha: 1) + + + chartView.rightAxis.enabled = false + + chartView.legend.form = .line + + sliderX.value = 100 + slidersValueChanged(nil) + + chartView.animate(xAxisDuration: 2.5) + } + + override func updateChartData() { + if self.shouldHideData { + chartView.data = nil + return + } + + self.setDataCount(Int(sliderX.value), range: 30) + } + + func setDataCount(_ count: Int, range: UInt32) { + let now = Date().timeIntervalSince1970 + let hourSeconds: TimeInterval = 3600 + + let from = now - (Double(count) / 2) * hourSeconds + let to = now + (Double(count) / 2) * hourSeconds + + let values = stride(from: from, to: to, by: hourSeconds).map { (x) -> ChartDataEntry in + let y = arc4random_uniform(range) + 50 + return ChartDataEntry(x: x, y: Double(y)) + } + + let set1 = LineChartDataSet(values: values, label: "DataSet 1") + set1.axisDependency = .left + set1.setColor(UIColor(red: 51/255, green: 181/255, blue: 229/255, alpha: 1)) + set1.lineWidth = 1.5 + set1.drawCirclesEnabled = false + set1.drawValuesEnabled = false + set1.fillAlpha = 0.26 + set1.fillColor = UIColor(red: 51/255, green: 181/255, blue: 229/255, alpha: 1) + set1.highlightColor = UIColor(red: 244/255, green: 117/255, blue: 117/255, alpha: 1) + set1.drawCircleHoleEnabled = false + + let data = LineChartData(dataSet: set1) + data.setValueTextColor(.white) + data.setValueFont(.systemFont(ofSize: 9, weight: .light)) + + chartView.data = data + } + + override func optionTapped(_ option: Option) { + switch option { + case .toggleFilled: + for set in chartView.data!.dataSets as! [LineChartDataSet] { + set.drawFilledEnabled = !set.drawFilledEnabled + } + chartView.setNeedsDisplay() + + case .toggleCircles: + for set in chartView.data!.dataSets as! [LineChartDataSet] { + set.drawCirclesEnabled = !set.drawCirclesEnabled + } + chartView.setNeedsDisplay() + + case .toggleCubic: + for set in chartView.data!.dataSets as! [LineChartDataSet] { + set.mode = (set.mode == .cubicBezier) ? .linear : .cubicBezier + } + chartView.setNeedsDisplay() + + case .toggleStepped: + for set in chartView.data!.dataSets as! [LineChartDataSet] { + set.mode = (set.mode == .stepped) ? .linear : .stepped + } + chartView.setNeedsDisplay() + + case .toggleHorizontalCubic: + for set in chartView.data!.dataSets as! [LineChartDataSet] { + set.mode = (set.mode == .cubicBezier) ? .horizontalBezier : .cubicBezier + } + chartView.setNeedsDisplay() + + default: + super.handleOption(option, forChartView: chartView) + } + } + + @IBAction func slidersValueChanged(_ sender: Any?) { + sliderTextX.text = "\(Int(sliderX.value))" + self.updateChartData() + } +} diff --git a/ChartsDemo/Swift/Demos/MultipleBarChartViewController.swift b/ChartsDemo/Swift/Demos/MultipleBarChartViewController.swift new file mode 100644 index 0000000000..93c9f4654b --- /dev/null +++ b/ChartsDemo/Swift/Demos/MultipleBarChartViewController.swift @@ -0,0 +1,154 @@ +// +// MultipleBarChartViewController.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-09. +// Copyright © 2017 jc. All rights reserved. +// + +import UIKit +import Charts + +class MultipleBarChartViewController: DemoBaseViewController { + + @IBOutlet var chartView: BarChartView! + @IBOutlet var sliderX: UISlider! + @IBOutlet var sliderY: UISlider! + @IBOutlet var sliderTextX: UITextField! + @IBOutlet var sliderTextY: UITextField! + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + self.title = "Multiple Bar Chart" + + self.options = [.toggleValues, + .toggleHighlight, + .animateX, + .animateY, + .animateXY, + .saveToGallery, + .togglePinchZoom, + .toggleAutoScaleMinMax, + .toggleData, + .toggleBarBorders] + + chartView.delegate = self + + chartView.chartDescription?.enabled = false + + chartView.pinchZoomEnabled = false + chartView.drawBarShadowEnabled = false + + let marker = BalloonMarker(color: UIColor(white: 180/255, alpha: 1), font: .systemFont(ofSize: 12), textColor: .white, insets: UIEdgeInsets(top: 8, left: 8, bottom: 20, right: 8)) + marker.chartView = chartView + marker.minimumSize = CGSize(width: 80, height: 40) + chartView.marker = marker + + let l = chartView.legend + l.horizontalAlignment = .right + l.verticalAlignment = .top + l.orientation = .vertical + l.drawInside = true + l.font = .systemFont(ofSize: 8, weight: .light) + l.yOffset = 10 + l.xOffset = 10 + l.yEntrySpace = 0 +// chartView.legend = l + + let xAxis = chartView.xAxis + xAxis.labelFont = .systemFont(ofSize: 10, weight: .light) + xAxis.granularity = 1 + xAxis.centerAxisLabelsEnabled = true + xAxis.valueFormatter = IntAxisValueFormatter() + + let leftAxisFormatter = NumberFormatter() + leftAxisFormatter.maximumFractionDigits = 1 + + let leftAxis = chartView.leftAxis + leftAxis.labelFont = .systemFont(ofSize: 10, weight: .light) + leftAxis.valueFormatter = LargeValueFormatter() + leftAxis.spaceTop = 0.35 + leftAxis.axisMinimum = 0 + + chartView.rightAxis.enabled = false + + sliderX.value = 10 + sliderY.value = 100 + slidersValueChanged(nil) + } + + override func updateChartData() { + if self.shouldHideData { + chartView.data = nil + return + } + + self.setDataCount(Int(sliderX.value), range: UInt32(sliderY.value)) + } + + func setDataCount(_ count: Int, range: UInt32) { + let groupSpace = 0.08 + let barSpace = 0.03 + let barWidth = 0.2 + // (0.2 + 0.03) * 4 + 0.08 = 1.00 -> interval per "group" + + let randomMultiplier = range * 100000 + let groupCount = count + 1 + let startYear = 1980 + let endYear = startYear + groupCount + + let block: (Int) -> BarChartDataEntry = { (i) -> BarChartDataEntry in + return BarChartDataEntry(x: Double(i), y: Double(arc4random_uniform(randomMultiplier))) + } + let yVals1 = (startYear ..< endYear).map(block) + let yVals2 = (startYear ..< endYear).map(block) + let yVals3 = (startYear ..< endYear).map(block) + let yVals4 = (startYear ..< endYear).map(block) + + let set1 = BarChartDataSet(values: yVals1, label: "Company A") + set1.setColor(UIColor(red: 104/255, green: 241/255, blue: 175/255, alpha: 1)) + + let set2 = BarChartDataSet(values: yVals2, label: "Company B") + set2.setColor(UIColor(red: 164/255, green: 228/255, blue: 251/255, alpha: 1)) + + let set3 = BarChartDataSet(values: yVals3, label: "Company C") + set3.setColor(UIColor(red: 242/255, green: 247/255, blue: 158/255, alpha: 1)) + + let set4 = BarChartDataSet(values: yVals4, label: "Company D") + set4.setColor(UIColor(red: 255/255, green: 102/255, blue: 0/255, alpha: 1)) + + let data = BarChartData(dataSets: [set1, set2, set3, set4]) + data.setValueFont(.systemFont(ofSize: 10, weight: .light)) + data.setValueFormatter(LargeValueFormatter()) + + // specify the width each bar should have + data.barWidth = barWidth + + // restrict the x-axis range + chartView.xAxis.axisMinimum = Double(startYear) + + // groupWidthWithGroupSpace(...) is a helper that calculates the width each group needs based on the provided parameters + chartView.xAxis.axisMaximum = Double(startYear) + data.groupWidth(groupSpace: groupSpace, barSpace: barSpace) * Double(groupCount) + + data.groupBars(fromX: Double(startYear), groupSpace: groupSpace, barSpace: barSpace) + + chartView.data = data + } + + override func optionTapped(_ option: Option) { + super.handleOption(option, forChartView: chartView) + } + + // MARK: - Actions + @IBAction func slidersValueChanged(_ sender: Any?) { + let startYear = 1980 + let endYear = startYear + Int(sliderX.value) + + sliderTextX.text = "\(startYear)-\(endYear)" + sliderTextY.text = "\(Int(sliderY.value))" + + self.updateChartData() + } +} diff --git a/ChartsDemo/Swift/Demos/MultipleLinesChartViewController.swift b/ChartsDemo/Swift/Demos/MultipleLinesChartViewController.swift new file mode 100644 index 0000000000..4b11f73d28 --- /dev/null +++ b/ChartsDemo/Swift/Demos/MultipleLinesChartViewController.swift @@ -0,0 +1,138 @@ +// +// MultipleLinesChartViewController.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-09. +// Copyright © 2017 jc. All rights reserved. +// + +import UIKit +import Charts + +class MultipleLinesChartViewController: DemoBaseViewController { + + @IBOutlet var chartView: LineChartView! + @IBOutlet var sliderX: UISlider! + @IBOutlet var sliderY: UISlider! + @IBOutlet var sliderTextX: UITextField! + @IBOutlet var sliderTextY: UITextField! + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + self.title = "Multiple Lines Chart" + self.options = [.toggleValues, + .toggleFilled, + .toggleCircles, + .toggleCubic, + .toggleStepped, + .toggleHighlight, + .animateX, + .animateY, + .animateXY, + .saveToGallery, + .togglePinchZoom, + .toggleAutoScaleMinMax, + .toggleData] + + chartView.delegate = self + + chartView.chartDescription?.enabled = false + + chartView.leftAxis.enabled = false + chartView.rightAxis.drawAxisLineEnabled = false + chartView.xAxis.drawAxisLineEnabled = false + + chartView.drawBordersEnabled = false + chartView.setScaleEnabled(true) + + let l = chartView.legend + l.horizontalAlignment = .right + l.verticalAlignment = .top + l.orientation = .vertical + l.drawInside = false +// chartView.legend = l + + sliderX.value = 20 + sliderY.value = 100 + slidersValueChanged(nil) + } + + override func updateChartData() { + if self.shouldHideData { + chartView.data = nil + return + } + + self.setDataCount(Int(sliderX.value), range: UInt32(sliderY.value)) + } + + // TODO: Refine data creation + func setDataCount(_ count: Int, range: UInt32) { + let colors = ChartColorTemplates.vordiplom()[0...2] + + let block: (Int) -> ChartDataEntry = { (i) -> ChartDataEntry in + let val = Double(arc4random_uniform(range) + 3) + return ChartDataEntry(x: Double(i), y: val) + } + let dataSets = (0..<3).map { i -> LineChartDataSet in + let yVals = (0.. String { + return String(format: "%03.0f-%03.0f", value, value + 10) + } +} diff --git a/ChartsDemo/Swift/Demos/PieChartViewController.swift b/ChartsDemo/Swift/Demos/PieChartViewController.swift new file mode 100644 index 0000000000..5b0acf4b64 --- /dev/null +++ b/ChartsDemo/Swift/Demos/PieChartViewController.swift @@ -0,0 +1,153 @@ +// +// PieChartViewController.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-09. +// Copyright © 2017 jc. All rights reserved. +// + +import UIKit +import Charts + +class PieChartViewController: DemoBaseViewController { + + @IBOutlet var chartView: PieChartView! + @IBOutlet var sliderX: UISlider! + @IBOutlet var sliderY: UISlider! + @IBOutlet var sliderTextX: UITextField! + @IBOutlet var sliderTextY: UITextField! + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + self.title = "Half Pie Bar Chart" + + self.options = [.toggleValues, + .toggleXValues, + .togglePercent, + .toggleHole, + .toggleIcons, + .animateX, + .animateY, + .animateXY, + .spin, + .drawCenter, + .saveToGallery, + .toggleData] + + self.setup(pieChartView: chartView) + + chartView.delegate = self + + let l = chartView.legend + l.horizontalAlignment = .right + l.verticalAlignment = .top + l.orientation = .vertical + l.xEntrySpace = 7 + l.yEntrySpace = 0 + l.yOffset = 0 +// chartView.legend = l + + // entry label styling + chartView.entryLabelColor = .white + chartView.entryLabelFont = .systemFont(ofSize: 12, weight: .light) + + sliderX.value = 4 + sliderY.value = 100 + self.slidersValueChanged(nil) + + chartView.animate(xAxisDuration: 1.4, easingOption: .easeOutBack) + } + + override func updateChartData() { + if self.shouldHideData { + chartView.data = nil + return + } + + self.setDataCount(Int(sliderX.value), range: UInt32(sliderY.value)) + } + + func setDataCount(_ count: Int, range: UInt32) { + let entries = (0.. PieChartDataEntry in + // IMPORTANT: In a PieChart, no values (Entry) should have the same xIndex (even if from different DataSets), since no values can be drawn above each other. + return PieChartDataEntry(value: Double(arc4random_uniform(range) + range / 5), + label: parties[i % parties.count], + icon: #imageLiteral(resourceName: "icon")) + } + + let set = PieChartDataSet(values: entries, label: "Election Results") + set.drawIconsEnabled = false + set.sliceSpace = 2 + + + set.colors = ChartColorTemplates.vordiplom() + + ChartColorTemplates.joyful() + + ChartColorTemplates.colorful() + + ChartColorTemplates.liberty() + + ChartColorTemplates.pastel() + + [UIColor(red: 51/255, green: 181/255, blue: 229/255, alpha: 1)] + + let data = PieChartData(dataSet: set) + + let pFormatter = NumberFormatter() + pFormatter.numberStyle = .percent + pFormatter.maximumFractionDigits = 1 + pFormatter.multiplier = 1 + pFormatter.percentSymbol = " %" + data.setValueFormatter(DefaultValueFormatter(formatter: pFormatter)) + + data.setValueFont(.systemFont(ofSize: 11, weight: .light)) + data.setValueTextColor(.white) + + chartView.data = data + chartView.highlightValues(nil) + } + + override func optionTapped(_ option: Option) { + switch option { + case .toggleXValues: + chartView.drawEntryLabelsEnabled = !chartView.drawEntryLabelsEnabled + chartView.setNeedsDisplay() + + case .togglePercent: + chartView.usePercentValuesEnabled = !chartView.usePercentValuesEnabled + chartView.setNeedsDisplay() + + case .toggleHole: + chartView.drawHoleEnabled = !chartView.drawHoleEnabled + chartView.setNeedsDisplay() + + case .drawCenter: + chartView.drawCenterTextEnabled = !chartView.drawCenterTextEnabled + chartView.setNeedsDisplay() + + case .animateX: + chartView.animate(xAxisDuration: 1.4) + + case .animateY: + chartView.animate(yAxisDuration: 1.4) + + case .animateXY: + chartView.animate(xAxisDuration: 1.4, yAxisDuration: 1.4) + + case .spin: + chartView.spin(duration: 2, + fromAngle: chartView.rotationAngle, + toAngle: chartView.rotationAngle + 360, + easingOption: .easeInCubic) + + default: + handleOption(option, forChartView: chartView) + } + } + + // MARK: - Actions + @IBAction func slidersValueChanged(_ sender: Any?) { + sliderTextX.text = "\(Int(sliderX.value))" + sliderTextY.text = "\(Int(sliderY.value))" + + self.updateChartData() + } +} diff --git a/ChartsDemo/Swift/Demos/PiePolylineChartViewController.swift b/ChartsDemo/Swift/Demos/PiePolylineChartViewController.swift new file mode 100644 index 0000000000..5b48713b2f --- /dev/null +++ b/ChartsDemo/Swift/Demos/PiePolylineChartViewController.swift @@ -0,0 +1,145 @@ +// +// PiePolylineChartViewController.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-09. +// Copyright © 2017 jc. All rights reserved. +// + +import UIKit +import Charts + +class PiePolylineChartViewController: DemoBaseViewController { + + @IBOutlet var chartView: PieChartView! + @IBOutlet var sliderX: UISlider! + @IBOutlet var sliderY: UISlider! + @IBOutlet var sliderTextX: UITextField! + @IBOutlet var sliderTextY: UITextField! + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + self.title = "Pie Bar Chart" + + self.options = [.toggleValues, + .toggleXValues, + .togglePercent, + .toggleHole, + .animateX, + .animateY, + .animateXY, + .spin, + .drawCenter, + .saveToGallery, + .toggleData] + + self.setup(pieChartView: chartView) + + chartView.delegate = self + + chartView.legend.enabled = false + chartView.setExtraOffsets(left: 20, top: 0, right: 20, bottom: 0) + + sliderX.value = 40 + sliderY.value = 100 + self.slidersValueChanged(nil) + + chartView.animate(xAxisDuration: 1.4, easingOption: .easeOutBack) + } + + override func updateChartData() { + if self.shouldHideData { + chartView.data = nil + return + } + + self.setDataCount(Int(sliderX.value), range: UInt32(sliderY.value)) + } + + func setDataCount(_ count: Int, range: UInt32) { + let entries = (0.. PieChartDataEntry in + // IMPORTANT: In a PieChart, no values (Entry) should have the same xIndex (even if from different DataSets), since no values can be drawn above each other. + return PieChartDataEntry(value: Double(arc4random_uniform(range) + range / 5), + label: parties[i % parties.count]) + } + + let set = PieChartDataSet(values: entries, label: "Election Results") + set.sliceSpace = 2 + + + set.colors = ChartColorTemplates.vordiplom() + + ChartColorTemplates.joyful() + + ChartColorTemplates.colorful() + + ChartColorTemplates.liberty() + + ChartColorTemplates.pastel() + + [UIColor(red: 51/255, green: 181/255, blue: 229/255, alpha: 1)] + + set.valueLinePart1OffsetPercentage = 0.8 + set.valueLinePart1Length = 0.2 + set.valueLinePart2Length = 0.4 + //set.xValuePosition = .outsideSlice + set.yValuePosition = .outsideSlice + + let data = PieChartData(dataSet: set) + + let pFormatter = NumberFormatter() + pFormatter.numberStyle = .percent + pFormatter.maximumFractionDigits = 1 + pFormatter.multiplier = 1 + pFormatter.percentSymbol = " %" + data.setValueFormatter(DefaultValueFormatter(formatter: pFormatter)) + data.setValueFont(.systemFont(ofSize: 11, weight: .light)) + data.setValueTextColor(.black) + + chartView.data = data + chartView.highlightValues(nil) + } + + override func optionTapped(_ option: Option) { + switch option { + case .toggleXValues: + chartView.drawEntryLabelsEnabled = !chartView.drawEntryLabelsEnabled + chartView.setNeedsDisplay() + + case .togglePercent: + chartView.usePercentValuesEnabled = !chartView.usePercentValuesEnabled + chartView.setNeedsDisplay() + + case .toggleHole: + chartView.drawHoleEnabled = !chartView.drawHoleEnabled + chartView.setNeedsDisplay() + + case .drawCenter: + chartView.drawCenterTextEnabled = !chartView.drawCenterTextEnabled + chartView.setNeedsDisplay() + + case .animateX: + chartView.animate(xAxisDuration: 1.4) + + case .animateY: + chartView.animate(yAxisDuration: 1.4) + + case .animateXY: + chartView.animate(xAxisDuration: 1.4, yAxisDuration: 1.4) + + case .spin: + chartView.spin(duration: 2, + fromAngle: chartView.rotationAngle, + toAngle: chartView.rotationAngle + 360, + easingOption: .easeInCubic) + + default: + handleOption(option, forChartView: chartView) + } + } + + // MARK: - Actions + @IBAction func slidersValueChanged(_ sender: Any?) { + sliderTextX.text = "\(Int(sliderX.value))" + sliderTextY.text = "\(Int(sliderY.value))" + + self.updateChartData() + } +} diff --git a/ChartsDemo/Swift/Demos/PositiveNegativeBarChartViewController.swift b/ChartsDemo/Swift/Demos/PositiveNegativeBarChartViewController.swift new file mode 100644 index 0000000000..6d363dec0c --- /dev/null +++ b/ChartsDemo/Swift/Demos/PositiveNegativeBarChartViewController.swift @@ -0,0 +1,120 @@ +// +// PositiveNegativeBarChartViewController.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-09. +// Copyright © 2017 jc. All rights reserved. +// + +import UIKit +import Charts + +class PositiveNegativeBarChartViewController: DemoBaseViewController { + + @IBOutlet var chartView: BarChartView! + + let dataLabels = ["12-19", + "12-30", + "12-31", + "01-01", + "01-02"] + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + self.title = "Bar Chart" + self.options = [.toggleValues, + .toggleHighlight, + .animateX, + .animateY, + .animateXY, + .saveToGallery, + .togglePinchZoom, + .toggleAutoScaleMinMax, + .toggleData, + .toggleBarBorders] + + self.setup(barLineChartView: chartView) + + chartView.delegate = self + + chartView.setExtraOffsets(left: 70, top: -30, right: 70, bottom: 10) + + chartView.drawBarShadowEnabled = false + chartView.drawValueAboveBarEnabled = true + + chartView.chartDescription?.enabled = false + + chartView.rightAxis.enabled = false + + let xAxis = chartView.xAxis + xAxis.labelPosition = .bottom + xAxis.labelFont = .systemFont(ofSize: 13) + xAxis.drawAxisLineEnabled = false + xAxis.labelTextColor = .lightGray + xAxis.labelCount = 5 + xAxis.centerAxisLabelsEnabled = true + xAxis.granularity = 1 + xAxis.valueFormatter = self + + let leftAxis = chartView.leftAxis + leftAxis.drawLabelsEnabled = false + leftAxis.spaceTop = 0.25 + leftAxis.spaceBottom = 0.25 + leftAxis.drawAxisLineEnabled = false + leftAxis.drawZeroLineEnabled = true + leftAxis.zeroLineColor = .gray + leftAxis.zeroLineWidth = 0.7 + + self.updateChartData() + } + + override func updateChartData() { + if self.shouldHideData { + chartView.data = nil + return + } + + self.setChartData() + } + + func setChartData() { + let yVals = [BarChartDataEntry(x: 0, y: -224.1), + BarChartDataEntry(x: 1, y: 238.5), + BarChartDataEntry(x: 2, y: 1280.1), + BarChartDataEntry(x: 3, y: -442.3), + BarChartDataEntry(x: 4, y: -2280.1) + ] + + let red = UIColor(red: 211/255, green: 74/255, blue: 88/255, alpha: 1) + let green = UIColor(red: 110/255, green: 190/255, blue: 102/255, alpha: 1) + let colors = yVals.map { (entry) -> NSUIColor in + return entry.y > 0 ? red : green + } + + let set = BarChartDataSet(values: yVals, label: "Values") + set.colors = colors + set.valueColors = colors + + let data = BarChartData(dataSet: set) + data.setValueFont(.systemFont(ofSize: 13)) + + let formatter = NumberFormatter() + formatter.maximumFractionDigits = 1 + data.setValueFormatter(DefaultValueFormatter(formatter: formatter)) + data.barWidth = 0.8 + + chartView.data = data + } + + override func optionTapped(_ option: Option) { + super.handleOption(option, forChartView: chartView) + } +} + +extension PositiveNegativeBarChartViewController: IAxisValueFormatter { + func stringForValue(_ value: Double, axis: AxisBase?) -> String { + return dataLabels[min(max(Int(value), 0), dataLabels.count - 1)] + } +} diff --git a/ChartsDemo/Swift/Demos/RadarChartViewController.swift b/ChartsDemo/Swift/Demos/RadarChartViewController.swift new file mode 100644 index 0000000000..f90bb74c6c --- /dev/null +++ b/ChartsDemo/Swift/Demos/RadarChartViewController.swift @@ -0,0 +1,203 @@ +// +// RadarChartViewController.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-09. +// Copyright © 2017 jc. All rights reserved. +// + +import UIKit +import Charts + +class RadarChartViewController: DemoBaseViewController { + + @IBOutlet var chartView: RadarChartView! + + let activities = ["Burger", "Steak", "Salad", "Pasta", "Pizza"] + var originalBarBgColor: UIColor! + var originalBarTintColor: UIColor! + var originalBarStyle: UIBarStyle! + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + self.title = "Radar Bar Chart" + self.options = [.toggleValues, + .toggleHighlight, + .toggleHighlightCircle, + .toggleXLabels, + .toggleYLabels, + .toggleRotate, + .toggleFilled, + .animateX, + .animateY, + .animateXY, + .spin, + .saveToGallery, + .toggleData] + + chartView.delegate = self + + chartView.chartDescription?.enabled = false + chartView.webLineWidth = 1 + chartView.innerWebLineWidth = 1 + chartView.webColor = .lightGray + chartView.innerWebColor = .lightGray + chartView.webAlpha = 1 + + let marker = RadarMarkerView.viewFromXib()! + marker.chartView = chartView + chartView.marker = marker + + let xAxis = chartView.xAxis + xAxis.labelFont = .systemFont(ofSize: 9, weight: .light) + xAxis.xOffset = 0 + xAxis.yOffset = 0 + xAxis.valueFormatter = self + xAxis.labelTextColor = .white + + let yAxis = chartView.yAxis + yAxis.labelFont = .systemFont(ofSize: 9, weight: .light) + yAxis.labelCount = 5 + yAxis.axisMinimum = 0 + yAxis.axisMaximum = 80 + yAxis.drawLabelsEnabled = false + + let l = chartView.legend + l.horizontalAlignment = .center + l.verticalAlignment = .top + l.orientation = .horizontal + l.drawInside = false + l.font = .systemFont(ofSize: 10, weight: .light) + l.xEntrySpace = 7 + l.yEntrySpace = 5 + l.textColor = .white +// chartView.legend = l + + self.updateChartData() + + chartView.animate(xAxisDuration: 1.4, yAxisDuration: 1.4, easingOption: .easeOutBack) + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + UIView.animate(withDuration: 0.15) { + let navBar = self.navigationController!.navigationBar + self.originalBarBgColor = navBar.barTintColor + self.originalBarTintColor = navBar.tintColor + self.originalBarStyle = navBar.barStyle + + navBar.barTintColor = self.view.backgroundColor + navBar.tintColor = .white + navBar.barStyle = .black + } + } + + override func viewWillDisappear(_ animated: Bool) { + super.viewWillDisappear(animated) + + UIView.animate(withDuration: 0.15) { + let navBar = self.navigationController!.navigationBar + navBar.barTintColor = self.originalBarBgColor + navBar.tintColor = self.originalBarTintColor + navBar.barStyle = self.originalBarStyle + } + } + + override func updateChartData() { + if self.shouldHideData { + chartView.data = nil + return + } + + self.setChartData() + } + + func setChartData() { + let mult: UInt32 = 80 + let min: UInt32 = 20 + let cnt = 5 + + let block: (Int) -> RadarChartDataEntry = { _ in return RadarChartDataEntry(value: Double(arc4random_uniform(mult) + min))} + let entries1 = (0.. String { + return activities[Int(value) % activities.count] + } +} diff --git a/ChartsDemo/Swift/Demos/ScatterChartViewController.swift b/ChartsDemo/Swift/Demos/ScatterChartViewController.swift new file mode 100644 index 0000000000..2dea8e3627 --- /dev/null +++ b/ChartsDemo/Swift/Demos/ScatterChartViewController.swift @@ -0,0 +1,124 @@ +// +// ScatterChartViewController.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-09. +// Copyright © 2017 jc. All rights reserved. +// + +import UIKit +import Charts + +class ScatterChartViewController: DemoBaseViewController { + + @IBOutlet var chartView: ScatterChartView! + @IBOutlet var sliderX: UISlider! + @IBOutlet var sliderY: UISlider! + @IBOutlet var sliderTextX: UITextField! + @IBOutlet var sliderTextY: UITextField! + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + self.title = "Scatter Bar Chart" + self.options = [.toggleValues, + .toggleHighlight, + .animateX, + .animateY, + .animateXY, + .saveToGallery, + .togglePinchZoom, + .toggleAutoScaleMinMax, + .toggleData] + + chartView.delegate = self + + chartView.chartDescription?.enabled = false + + chartView.dragEnabled = true + chartView.setScaleEnabled(true) + chartView.maxVisibleCount = 200 + chartView.pinchZoomEnabled = true + + let l = chartView.legend + l.horizontalAlignment = .right + l.verticalAlignment = .top + l.orientation = .vertical + l.drawInside = false + l.font = .systemFont(ofSize: 10, weight: .light) + l.xOffset = 5 + + let leftAxis = chartView.leftAxis + leftAxis.labelFont = .systemFont(ofSize: 10, weight: .light) + leftAxis.axisMinimum = 0 + + chartView.rightAxis.enabled = false + + + let xAxis = chartView.xAxis + xAxis.labelFont = .systemFont(ofSize: 10, weight: .light) + + sliderX.value = 45 + sliderY.value = 100 + slidersValueChanged(nil) + } + + override func updateChartData() { + if self.shouldHideData { + chartView.data = nil + return + } + + self.setDataCount(Int(sliderX.value + 1), range: UInt32(sliderY.value)) + } + + func setDataCount(_ count: Int, range: UInt32) { + let values1 = (0.. ChartDataEntry in + let val = Double(arc4random_uniform(range) + 3) + return ChartDataEntry(x: Double(i), y: val) + } + let values2 = (0.. ChartDataEntry in + let val = Double(arc4random_uniform(range) + 3) + return ChartDataEntry(x: Double(i) + 0.33, y: val) + } + let values3 = (0.. ChartDataEntry in + let val = Double(arc4random_uniform(range) + 3) + return ChartDataEntry(x: Double(i) + 0.66, y: val) + } + + + let set1 = ScatterChartDataSet(values: values1, label: "DS 1") + set1.setScatterShape(.square) + set1.setColor(ChartColorTemplates.colorful()[0]) + set1.scatterShapeSize = 8 + + let set2 = ScatterChartDataSet(values: values2, label: "DS 2") + set2.setScatterShape(.circle) + set2.scatterShapeHoleColor = ChartColorTemplates.colorful()[3] + set2.scatterShapeHoleRadius = 3.5 + set2.setColor(ChartColorTemplates.colorful()[1]) + set2.scatterShapeSize = 8 + + let set3 = ScatterChartDataSet(values: values3, label: "DS 3") + set3.setScatterShape(.cross) + set3.setColor(ChartColorTemplates.colorful()[2]) + set3.scatterShapeSize = 8 + + let data = ScatterChartData(dataSets: [set1, set2, set3]) + data.setValueFont(.systemFont(ofSize: 7, weight: .light)) + + chartView.data = data + } + + override func optionTapped(_ option: Option) { + super.handleOption(option, forChartView: chartView) + } + + @IBAction func slidersValueChanged(_ sender: Any?) { + sliderTextX.text = "\(Int(sliderX.value))" + sliderTextY.text = "\(Int(sliderY.value))" + + self.updateChartData() + } +} diff --git a/ChartsDemo/Swift/Demos/SinusBarChartViewController.swift b/ChartsDemo/Swift/Demos/SinusBarChartViewController.swift new file mode 100644 index 0000000000..790d5c6721 --- /dev/null +++ b/ChartsDemo/Swift/Demos/SinusBarChartViewController.swift @@ -0,0 +1,108 @@ +// +// SinusBarChartViewController.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-09. +// Copyright © 2017 jc. All rights reserved. +// + +import UIKit +import Charts + +class SinusBarChartViewController: DemoBaseViewController { + + @IBOutlet var chartView: BarChartView! + @IBOutlet var sliderX: UISlider! + @IBOutlet var sliderTextX: UITextField! + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + self.title = "Line Chart 2" + self.options = [.toggleValues, + .toggleHighlight, + .animateX, + .animateY, + .animateXY, + .saveToGallery, + .togglePinchZoom, + .toggleAutoScaleMinMax, + .toggleData] + + chartView.delegate = self + + chartView.chartDescription?.enabled = false + + chartView.drawBarShadowEnabled = false + chartView.drawValueAboveBarEnabled = false + chartView.maxVisibleCount = 60 + + let xAxis = chartView.xAxis + xAxis.labelPosition = .bottom + xAxis.enabled = false + + let leftAxis = chartView.leftAxis + leftAxis.labelCount = 6 + leftAxis.axisMinimum = -2.5 + leftAxis.axisMaximum = 2.5 + leftAxis.granularityEnabled = true + leftAxis.granularity = 0.1 + + let rightAxis = chartView.rightAxis + rightAxis.labelCount = 6 + rightAxis.axisMinimum = -2.5 + rightAxis.axisMaximum = 2.5 + rightAxis.granularity = 0.1 + + let l = chartView.legend + l.horizontalAlignment = .left + l.verticalAlignment = .bottom + l.orientation = .horizontal + l.drawInside = false + l.form = .square + l.formSize = 9 + l.font = .systemFont(ofSize: 11) + l.xEntrySpace = 4 +// chartView.legend = l + + sliderX.value = 150 + slidersValueChanged(nil) + + chartView.animate(xAxisDuration: 2, yAxisDuration: 2) + } + + override func updateChartData() { + if self.shouldHideData { + chartView.data = nil + return + } + + self.setDataCount(Int(sliderX.value)) + } + + func setDataCount(_ count: Int) { + let entries = (0.. BarChartDataEntry in + let mult = range + 1 + let val1 = Double(arc4random_uniform(mult) + mult / 3) + let val2 = Double(arc4random_uniform(mult) + mult / 3) + let val3 = Double(arc4random_uniform(mult) + mult / 3) + + return BarChartDataEntry(x: Double(i), yValues: [val1, val2, val3], icon: #imageLiteral(resourceName: "icon")) + } + + let set = BarChartDataSet(values: yVals, label: "Statistics Vienna 2014") + set.drawIconsEnabled = false + set.colors = [ChartColorTemplates.material()[0], ChartColorTemplates.material()[1], ChartColorTemplates.material()[2]] + set.stackLabels = ["Births", "Divorces", "Marriages"] + + let data = BarChartData(dataSet: set) + data.setValueFont(.systemFont(ofSize: 7, weight: .light)) + data.setValueFormatter(DefaultValueFormatter(formatter: formatter)) + data.setValueTextColor(.white) + + chartView.fitBars = true + chartView.data = data + } + + override func optionTapped(_ option: Option) { + super.handleOption(option, forChartView: chartView) + } + + @IBAction func slidersValueChanged(_ sender: Any?) { + sliderTextX.text = "\(Int(sliderX.value))" + sliderTextY.text = "\(Int(sliderY.value))" + + updateChartData() + } +} diff --git a/ChartsDemo/Swift/Formatters/DateValueFormatter.swift b/ChartsDemo/Swift/Formatters/DateValueFormatter.swift new file mode 100644 index 0000000000..2962a6852a --- /dev/null +++ b/ChartsDemo/Swift/Formatters/DateValueFormatter.swift @@ -0,0 +1,23 @@ +// +// DateValueFormatter.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-09. +// Copyright © 2017 jc. All rights reserved. +// + +import Foundation +import Charts + +public class DateValueFormatter: NSObject, IAxisValueFormatter { + private let dateFormatter = DateFormatter() + + override init() { + super.init() + dateFormatter.dateFormat = "dd MMM HH:mm" + } + + public func stringForValue(_ value: Double, axis: AxisBase?) -> String { + return dateFormatter.string(from: Date(timeIntervalSince1970: value)) + } +} diff --git a/ChartsDemo/Swift/Formatters/DayAxisValueFormatter.swift b/ChartsDemo/Swift/Formatters/DayAxisValueFormatter.swift new file mode 100644 index 0000000000..245a25c83e --- /dev/null +++ b/ChartsDemo/Swift/Formatters/DayAxisValueFormatter.swift @@ -0,0 +1,109 @@ +// +// DayAxisValueFormatter.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-09. +// Copyright © 2017 jc. All rights reserved. +// + +import Foundation +import Charts + +public class DayAxisValueFormatter: NSObject, IAxisValueFormatter { + weak var chart: BarLineChartViewBase? + let months = ["Jan", "Feb", "Mar", + "Apr", "May", "Jun", + "Jul", "Aug", "Sep", + "Oct", "Nov", "Dec"] + + init(chart: BarLineChartViewBase) { + self.chart = chart + } + + public func stringForValue(_ value: Double, axis: AxisBase?) -> String { + let days = Int(value) + let year = determineYear(forDays: days) + let month = determineMonth(forDayOfYear: days) + + let monthName = months[month % months.count] + let yearName = "\(year)" + + if let chart = chart, + chart.visibleXRange > 30 * 6 { + return monthName + yearName + } else { + let dayOfMonth = determineDayOfMonth(forDays: days, month: month + 12 * (year - 2016)) + var appendix: String + + switch dayOfMonth { + case 1, 21, 31: appendix = "st" + case 2, 22: appendix = "nd" + case 3, 23: appendix = "rd" + default: appendix = "th" + } + + return dayOfMonth == 0 ? "" : String(format: "%d\(appendix) \(monthName)", dayOfMonth) + } + } + + private func days(forMonth month: Int, year: Int) -> Int { + // month is 0-based + switch month { + case 1: + var is29Feb = false + if year < 1582 { + is29Feb = (year < 1 ? year + 1 : year) % 4 == 0 + } else if year > 1582 { + is29Feb = year % 4 == 0 && (year % 100 != 0 || year % 400 == 0) + } + + return is29Feb ? 29 : 28 + + case 3, 5, 8, 10: + return 30 + + default: + return 31 + } + } + + private func determineMonth(forDayOfYear dayOfYear: Int) -> Int { + var month = -1 + var days = 0 + + while days < dayOfYear { + month += 1 + if month >= 12 { + month = 0 + } + + let year = determineYear(forDays: days) + days += self.days(forMonth: month, year: year) + } + + return max(month, 0) + } + + private func determineDayOfMonth(forDays days: Int, month: Int) -> Int { + var count = 0 + var daysForMonth = 0 + + while count < month { + let year = determineYear(forDays: days) + daysForMonth += self.days(forMonth: count % 12, year: year) + count += 1 + } + + return days - daysForMonth + } + + private func determineYear(forDays days: Int) -> Int { + switch days { + case ...366: return 2016 + case 367...730: return 2017 + case 731...1094: return 2018 + case 1095...1458: return 2019 + default: return 2020 + } + } +} diff --git a/ChartsDemo/Swift/Formatters/IntAxisValueFormatter.swift b/ChartsDemo/Swift/Formatters/IntAxisValueFormatter.swift new file mode 100644 index 0000000000..bd3062a190 --- /dev/null +++ b/ChartsDemo/Swift/Formatters/IntAxisValueFormatter.swift @@ -0,0 +1,16 @@ +// +// IntAxisValueFormatter.swift +// ChartsDemo-iOS +// +// Created by Jacob Christie on 2017-07-09. +// Copyright © 2017 jc. All rights reserved. +// + +import Foundation +import Charts + +public class IntAxisValueFormatter: NSObject, IAxisValueFormatter { + public func stringForValue(_ value: Double, axis: AxisBase?) -> String { + return "\(Int(value))" + } +} diff --git a/ChartsDemo/Swift/Formatters/LargeValueFormatter.swift b/ChartsDemo/Swift/Formatters/LargeValueFormatter.swift new file mode 100644 index 0000000000..c95ca034a6 --- /dev/null +++ b/ChartsDemo/Swift/Formatters/LargeValueFormatter.swift @@ -0,0 +1,58 @@ +// +// LargeValueFormatter.swift +// ChartsDemo +// Copyright © 2016 dcg. All rights reserved. +// + +import Foundation +import Charts + +private let MAX_LENGTH = 5 + +@objc protocol Testing123 { } + +public class LargeValueFormatter: NSObject, IValueFormatter, IAxisValueFormatter { + + /// Suffix to be appended after the values. + /// + /// **default**: suffix: ["", "k", "m", "b", "t"] + public var suffix = ["", "k", "m", "b", "t"] + + /// An appendix text to be added at the end of the formatted value. + public var appendix: String? + + public init(appendix: String? = nil) { + self.appendix = appendix + } + + fileprivate func format(value: Double) -> String { + var sig = value + var length = 0 + let maxLength = suffix.count - 1 + + while sig >= 1000.0 && length < maxLength { + sig /= 1000.0 + length += 1 + } + + var r = String(format: "%2.f", sig) + suffix[length] + + if let appendix = appendix { + r += appendix + } + + return r + } + + public func stringForValue(_ value: Double, axis: AxisBase?) -> String { + return format(value: value) + } + + public func stringForValue( + _ value: Double, + entry: ChartDataEntry, + dataSetIndex: Int, + viewPortHandler: ViewPortHandler?) -> String { + return format(value: value) + } +} diff --git a/ChartsDemo/XIBs/DemoListViewController.xib b/ChartsDemo/XIBs/DemoListViewController.xib index 70df94ae66..83417cd823 100644 --- a/ChartsDemo/XIBs/DemoListViewController.xib +++ b/ChartsDemo/XIBs/DemoListViewController.xib @@ -1,12 +1,15 @@ - - + + + + + - + - + @@ -18,6 +21,7 @@ + diff --git a/ChartsDemo/XIBs/Demos/AnotherBarChartViewController.xib b/ChartsDemo/XIBs/Demos/AnotherBarChartViewController.xib index 546a6bd904..345954a821 100644 --- a/ChartsDemo/XIBs/Demos/AnotherBarChartViewController.xib +++ b/ChartsDemo/XIBs/Demos/AnotherBarChartViewController.xib @@ -1,12 +1,20 @@ - - + + + + + - + + + + HelveticaNeue-Light + + - + @@ -22,6 +30,7 @@ + + + + @@ -53,6 +66,7 @@ + diff --git a/ChartsDemo/XIBs/Demos/BarChartViewController.xib b/ChartsDemo/XIBs/Demos/BarChartViewController.xib index 2098f36e87..34fdfc9b28 100644 --- a/ChartsDemo/XIBs/Demos/BarChartViewController.xib +++ b/ChartsDemo/XIBs/Demos/BarChartViewController.xib @@ -1,12 +1,20 @@ - - + + + + + - + + + + HelveticaNeue-Light + + - + @@ -22,6 +30,7 @@ + + + + @@ -53,6 +66,7 @@ + diff --git a/ChartsDemo/XIBs/Demos/BubbleChartViewController.xib b/ChartsDemo/XIBs/Demos/BubbleChartViewController.xib index 5883ff604f..25bb807b6f 100644 --- a/ChartsDemo/XIBs/Demos/BubbleChartViewController.xib +++ b/ChartsDemo/XIBs/Demos/BubbleChartViewController.xib @@ -1,12 +1,20 @@ - - + + + + + - + + + + HelveticaNeue-Light + + - + @@ -22,6 +30,7 @@ + + + + @@ -53,6 +66,7 @@ + diff --git a/ChartsDemo/XIBs/Demos/CandleStickChartViewController.xib b/ChartsDemo/XIBs/Demos/CandleStickChartViewController.xib index 2f814db531..927bccf6e6 100644 --- a/ChartsDemo/XIBs/Demos/CandleStickChartViewController.xib +++ b/ChartsDemo/XIBs/Demos/CandleStickChartViewController.xib @@ -1,12 +1,20 @@ - - + + + + + - + + + + HelveticaNeue-Light + + - + @@ -22,6 +30,7 @@ + + + + @@ -53,6 +66,7 @@ + diff --git a/ChartsDemo/XIBs/Demos/ColoredLineChartViewController.xib b/ChartsDemo/XIBs/Demos/ColoredLineChartViewController.xib index 7f92d45b88..2a484ef92b 100644 --- a/ChartsDemo/XIBs/Demos/ColoredLineChartViewController.xib +++ b/ChartsDemo/XIBs/Demos/ColoredLineChartViewController.xib @@ -1,18 +1,21 @@ - - + + + + + - + - + - - - - + + + + @@ -21,15 +24,19 @@ + + + + diff --git a/ChartsDemo/XIBs/Demos/CombinedChartViewController.xib b/ChartsDemo/XIBs/Demos/CombinedChartViewController.xib index 54477530db..37127411f9 100644 --- a/ChartsDemo/XIBs/Demos/CombinedChartViewController.xib +++ b/ChartsDemo/XIBs/Demos/CombinedChartViewController.xib @@ -1,12 +1,20 @@ - - + + + + + - + + + + HelveticaNeue-Light + + - + @@ -18,6 +26,7 @@ + diff --git a/ChartsDemo/XIBs/Demos/CubicLineChartViewController.xib b/ChartsDemo/XIBs/Demos/CubicLineChartViewController.xib index a991036be4..fcfa83aa7a 100644 --- a/ChartsDemo/XIBs/Demos/CubicLineChartViewController.xib +++ b/ChartsDemo/XIBs/Demos/CubicLineChartViewController.xib @@ -1,12 +1,20 @@ - - + + + + + - + + + + HelveticaNeue-Light + + - + @@ -22,6 +30,7 @@ + + + + @@ -53,6 +66,7 @@ + diff --git a/ChartsDemo/XIBs/Demos/HalfPieChartViewController.xib b/ChartsDemo/XIBs/Demos/HalfPieChartViewController.xib index 29922a188a..85b8f03231 100644 --- a/ChartsDemo/XIBs/Demos/HalfPieChartViewController.xib +++ b/ChartsDemo/XIBs/Demos/HalfPieChartViewController.xib @@ -1,12 +1,20 @@ - - + + + + + - + + + + HelveticaNeue-Light + + - + @@ -18,6 +26,7 @@ + diff --git a/ChartsDemo/XIBs/Demos/HorizontalBarChartViewController.xib b/ChartsDemo/XIBs/Demos/HorizontalBarChartViewController.xib index c2eca08e9b..0cd037f149 100644 --- a/ChartsDemo/XIBs/Demos/HorizontalBarChartViewController.xib +++ b/ChartsDemo/XIBs/Demos/HorizontalBarChartViewController.xib @@ -1,12 +1,20 @@ - - + + + + + - + + + + HelveticaNeue-Light + + - + @@ -22,6 +30,7 @@ + + + + @@ -53,6 +66,7 @@ + diff --git a/ChartsDemo/XIBs/Demos/LineChart1ViewController.xib b/ChartsDemo/XIBs/Demos/LineChart1ViewController.xib index 84be1eb5de..a3d577495e 100644 --- a/ChartsDemo/XIBs/Demos/LineChart1ViewController.xib +++ b/ChartsDemo/XIBs/Demos/LineChart1ViewController.xib @@ -1,12 +1,20 @@ - - + + + + + - + + + + HelveticaNeue-Light + + - + @@ -22,6 +30,7 @@ + + + + @@ -53,6 +66,7 @@ + diff --git a/ChartsDemo/XIBs/Demos/LineChart2ViewController.xib b/ChartsDemo/XIBs/Demos/LineChart2ViewController.xib index c37e4dd5d0..3cd27f52fa 100644 --- a/ChartsDemo/XIBs/Demos/LineChart2ViewController.xib +++ b/ChartsDemo/XIBs/Demos/LineChart2ViewController.xib @@ -1,12 +1,20 @@ - - + + + + + - + + + + HelveticaNeue-Light + + - + @@ -22,6 +30,7 @@ + + + + @@ -53,6 +66,7 @@ + diff --git a/ChartsDemo/XIBs/Demos/LineChartFilledViewController.xib b/ChartsDemo/XIBs/Demos/LineChartFilledViewController.xib index 116668ae42..262c5726b4 100644 --- a/ChartsDemo/XIBs/Demos/LineChartFilledViewController.xib +++ b/ChartsDemo/XIBs/Demos/LineChartFilledViewController.xib @@ -1,12 +1,20 @@ - - + + + + + - + + + + HelveticaNeue-Light + + - + @@ -22,19 +30,23 @@ + + + + @@ -43,6 +55,7 @@ + diff --git a/ChartsDemo/XIBs/Demos/LineChartTimeViewController.xib b/ChartsDemo/XIBs/Demos/LineChartTimeViewController.xib index 16b53d9d1b..5b1422b8e2 100644 --- a/ChartsDemo/XIBs/Demos/LineChartTimeViewController.xib +++ b/ChartsDemo/XIBs/Demos/LineChartTimeViewController.xib @@ -1,12 +1,20 @@ - - + + + + + - + + + + HelveticaNeue-Light + + - + @@ -20,6 +28,7 @@ + + @@ -41,6 +52,7 @@ + diff --git a/ChartsDemo/XIBs/Demos/MultipleBarChartViewController.xib b/ChartsDemo/XIBs/Demos/MultipleBarChartViewController.xib index 99fd12c09a..f0058e62dc 100644 --- a/ChartsDemo/XIBs/Demos/MultipleBarChartViewController.xib +++ b/ChartsDemo/XIBs/Demos/MultipleBarChartViewController.xib @@ -1,15 +1,20 @@ - + - + + + + HelveticaNeue-Light + + - + diff --git a/ChartsDemo/XIBs/Demos/MultipleLinesChartViewController.xib b/ChartsDemo/XIBs/Demos/MultipleLinesChartViewController.xib index 664ed9881c..332652a16f 100644 --- a/ChartsDemo/XIBs/Demos/MultipleLinesChartViewController.xib +++ b/ChartsDemo/XIBs/Demos/MultipleLinesChartViewController.xib @@ -1,12 +1,20 @@ - - + + + + + - + + + + HelveticaNeue-Light + + - + @@ -22,6 +30,7 @@ + + + + @@ -53,6 +66,7 @@ + diff --git a/ChartsDemo/XIBs/Demos/NegativeStackedBarChartViewController.xib b/ChartsDemo/XIBs/Demos/NegativeStackedBarChartViewController.xib index a2ce947ba2..7171239b8b 100644 --- a/ChartsDemo/XIBs/Demos/NegativeStackedBarChartViewController.xib +++ b/ChartsDemo/XIBs/Demos/NegativeStackedBarChartViewController.xib @@ -1,12 +1,20 @@ - - + + + + + - + + + + HelveticaNeue-Light + + - + @@ -18,6 +26,7 @@ + diff --git a/ChartsDemo/XIBs/Demos/PieChartViewController.xib b/ChartsDemo/XIBs/Demos/PieChartViewController.xib index 9561343870..db8be72a0e 100644 --- a/ChartsDemo/XIBs/Demos/PieChartViewController.xib +++ b/ChartsDemo/XIBs/Demos/PieChartViewController.xib @@ -1,12 +1,20 @@ - - + + + + + - + + + + HelveticaNeue-Light + + - + @@ -22,6 +30,7 @@ + + + @@ -50,6 +62,7 @@ + @@ -58,6 +71,7 @@ + diff --git a/ChartsDemo/XIBs/Demos/PiePolylineChartViewController.xib b/ChartsDemo/XIBs/Demos/PiePolylineChartViewController.xib index 9ef36e8e63..e731aef6e6 100644 --- a/ChartsDemo/XIBs/Demos/PiePolylineChartViewController.xib +++ b/ChartsDemo/XIBs/Demos/PiePolylineChartViewController.xib @@ -1,12 +1,20 @@ - - + + + + + - + + + + HelveticaNeue-Light + + - + @@ -22,6 +30,7 @@ + + + @@ -50,6 +62,7 @@ + @@ -58,6 +71,7 @@ + diff --git a/ChartsDemo/XIBs/Demos/PositiveNegativeBarChartViewController.xib b/ChartsDemo/XIBs/Demos/PositiveNegativeBarChartViewController.xib index 311a874345..6163198789 100644 --- a/ChartsDemo/XIBs/Demos/PositiveNegativeBarChartViewController.xib +++ b/ChartsDemo/XIBs/Demos/PositiveNegativeBarChartViewController.xib @@ -1,12 +1,20 @@ - - + + + + + - + + + + HelveticaNeue-Light + + - + @@ -18,6 +26,7 @@ + diff --git a/ChartsDemo/XIBs/Demos/RadarChartViewController.xib b/ChartsDemo/XIBs/Demos/RadarChartViewController.xib index fb3209f598..51de0648c6 100644 --- a/ChartsDemo/XIBs/Demos/RadarChartViewController.xib +++ b/ChartsDemo/XIBs/Demos/RadarChartViewController.xib @@ -1,13 +1,21 @@ - - + + + + + - + + + + HelveticaNeue-Light + + - + @@ -19,6 +27,7 @@ + diff --git a/ChartsDemo/XIBs/Demos/RealmDemosViewController.xib b/ChartsDemo/XIBs/Demos/RealmDemosViewController.xib index 0d3788dd13..80ad80558f 100644 --- a/ChartsDemo/XIBs/Demos/RealmDemosViewController.xib +++ b/ChartsDemo/XIBs/Demos/RealmDemosViewController.xib @@ -1,15 +1,20 @@ - + - + + + + HelveticaNeue-Light + + - + diff --git a/ChartsDemo/XIBs/Demos/ScatterChartViewController.xib b/ChartsDemo/XIBs/Demos/ScatterChartViewController.xib index 8fb1ad6909..c5cf2cb124 100644 --- a/ChartsDemo/XIBs/Demos/ScatterChartViewController.xib +++ b/ChartsDemo/XIBs/Demos/ScatterChartViewController.xib @@ -1,12 +1,20 @@ - - + + + + + - + + + + HelveticaNeue-Light + + - + @@ -22,6 +30,7 @@ + + + + @@ -53,6 +66,7 @@ + diff --git a/ChartsDemo/XIBs/Demos/SinusBarChartViewController.xib b/ChartsDemo/XIBs/Demos/SinusBarChartViewController.xib index 27fd60b479..3c4a8eb3c4 100644 --- a/ChartsDemo/XIBs/Demos/SinusBarChartViewController.xib +++ b/ChartsDemo/XIBs/Demos/SinusBarChartViewController.xib @@ -1,12 +1,20 @@ - - + + + + + - + + + + HelveticaNeue-Light + + - + @@ -20,6 +28,7 @@ + + @@ -43,6 +54,7 @@ + diff --git a/ChartsDemo/XIBs/Demos/StackedBarChartViewController.xib b/ChartsDemo/XIBs/Demos/StackedBarChartViewController.xib index 7473b3ffa7..8d714f8be5 100644 --- a/ChartsDemo/XIBs/Demos/StackedBarChartViewController.xib +++ b/ChartsDemo/XIBs/Demos/StackedBarChartViewController.xib @@ -14,7 +14,7 @@ - + diff --git a/ChartsDemo/XIBs/RadarMarkerView.xib b/ChartsDemo/XIBs/RadarMarkerView.xib index a515cc9ca9..8ffdb62c0d 100644 --- a/ChartsDemo/XIBs/RadarMarkerView.xib +++ b/ChartsDemo/XIBs/RadarMarkerView.xib @@ -1,22 +1,31 @@ - - + + + + + - + + + + HelveticaNeue-Light + + - + - +

S^pvhYR^W$;o%< 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 IIm^g@0c)79&;S4c diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Assets.xcassets/AppIcon.appiconset/Icon-29@3x.png b/ChartsDemo-iOS/ChartsDemo-iOS/Assets.xcassets/AppIcon.appiconset/Icon-29@3x.png deleted file mode 100644 index ef18aba824097d907faf79251338789f90356692..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10210 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 Wi~3w&#sBk@?u(@Sr!sMUzyATj7qnOa diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Assets.xcassets/AppIcon.appiconset/Icon-40@2x.png b/ChartsDemo-iOS/ChartsDemo-iOS/Assets.xcassets/AppIcon.appiconset/Icon-40@2x.png deleted file mode 100644 index 775e7277c87f33e5894daa86b314de4fd2e4b07a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9266 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 U7%vlQ|B3)&f9CH~?#)m6H}^Ndr~m)} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Assets.xcassets/LaunchImage.launchimage/Default-667h@2x.png b/ChartsDemo-iOS/ChartsDemo-iOS/Assets.xcassets/LaunchImage.launchimage/Default-667h@2x.png deleted file mode 100644 index a3bc101148bbb81e66044955d9d9ff5f6f6f6d74..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22355 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 diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Assets.xcassets/LaunchImage.launchimage/Default@2x.png b/ChartsDemo-iOS/ChartsDemo-iOS/Assets.xcassets/LaunchImage.launchimage/Default@2x.png deleted file mode 100644 index 16802b260b097c043a1d96e7cf24a3a0b5405506..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14035 zcmeAS@N?(olHy`uVBq!ia0y~yU}|7sU_QXX1{7KP=)`Xz=R>BmbAYF_vqC^oep+Tu zDg%Q>Z*S<`{M#WS_MQ1LOT_FKZ0zF`?Oq=m9KBOoYV9#L&&f+)I!Wz3dqZo<$?nFwWr=OcEr*QB-~}_ddm%&Y##nf5tTHFh$Puj_O|=mM^RJ+ZCh7 zq<5^<{o3Jp#e?_E*>Ao6UtAitayhfgJg1y++giDgnGI7`TCd|*xaaosgXVq5J0EQx z$?B6mHSrzQuX{IM*l+Mo*XLPOo!INes_)zj?q5E3x}#d4{>80VEaxL5 zmZil#{nx797tdELa7}k}$P>Fxm%R&)IlQ~R{MZg%%Lk7Yi=vHUjr&BL{!L0|+uX5p z;^#c)wJmd`XU#rcZ2!b=tJcEvSJthXmbzEgrADGp)nq}!VV-wZ5gQndR!nH;*(X~N z7|hJFV+~P&vuc^LtVSW9V?_$}% zC(g;#o?pR!;4t5o8O$Glt=IdzLHpB2C%rw@n_s^Y^08UDf936!U$1bzTfK5?$HZT@ zTif=BdL-wiO}J=d=Qg2T{Io*c;nbR%3kCm~E6aMet0tYbx-OgX}hY$ZF$eB z_ovuT6@AM6bWc%v^z_?hop_1i{^ z^-WRCeypMuj_tY@n{)p;XJ7Je^GLjXg>Q3Yp5c)>Gej>dbXOl0EcB2`-!XOm4)#*z z9nZJ<%>6fmE2BqreX+s}E3?&SsuV9&I@DI(N*8~-;_aNm-kZDh-v>{*{?w#y)ry!6 zUk=tq8v9xXRBrONeWiEdmBNPi3i}tyuQ>Q!cjMzCHb_`sNdc^+B->Ug!Z$#{ zIlm}X!Bo#g&p^qJOF==wrYI%ND#*nRsvXF)RmvzSDX`MlFE20GD>v55FG|-pw6wI; zH!#vSGSUUA&@HaaD@m--%_~-h7y>iLCAB!YD6^m>Ge1uOWNuJ**9#9ZqJ{ZIDce;{r$hM(47(sY92y*a4lwkH>ghrG zKo2pGdT2C;fXQJr$pJIMXdVIY(bmss>u0p} zGurwYZT*b4enwkA!>aW&IzvetTZ1;}VwJ6hI42G>R#V51GN(RFU43-?BsRx*vQ z6$Op2j4pl!w!cSL^8)LH#?kfGz{#i41>~cJ0%Y8oriDTy{~vSiNdYI-9Y9-8JYD@< J);T3K0RVdZWCZ{K diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Assets.xcassets/icon.imageset/Contents.json b/ChartsDemo-iOS/ChartsDemo-iOS/Assets.xcassets/icon.imageset/Contents.json deleted file mode 100644 index 8c89aaaae3..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Assets.xcassets/icon.imageset/Contents.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "star-2.png", - "scale" : "1x" - }, - { - "idiom" : "universal", - "filename" : "star-1.png", - "scale" : "2x" - }, - { - "idiom" : "universal", - "filename" : "star.png", - "scale" : "3x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Assets.xcassets/icon.imageset/star-1.png b/ChartsDemo-iOS/ChartsDemo-iOS/Assets.xcassets/icon.imageset/star-1.png deleted file mode 100644 index c7811ef2b89b0097f0c64f26718cc07e5a5b64b8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1221 zcmV;$1UmbPP)U=4^(ZyKr5oQs+34wu%k3i zNrRP02!%k}R7xn6hXLd3$C)m$1Abpf`mL-pbLRVIe9oD<1dF&C47!xayF?TakzQhM zS4ugv<`@CXL=;uPlm=Yy8ykyRiA&WSrh~z50)|-R0+<~Z_3i{Nx z4%V9S_?HZP0zk7!T!^%YdaaVv3{NeCoRRJ@> z;G0793j^NgM7|G^)r`oQ{_*j-vI4T1|7wYx2;LKo0D!eS>y||bk^gWdIQL^N6spUX z-BRX_-7d5STF@G3fxF9PO#qRPfFEYgovSGlunT-)`9CMXd+I=^ug?ci)eDtF4>=s4 z=Lwh&2D`JT-4YtQ+^F#$+{jv=1MW^|g&jrsbS4z)d@6u|Ay~a?M0wfgP-?9LY$P%S z05p64ygQ}qPpm#N?pK{?d;jH6YOp~>%_NeWDI~X&5G6&v%v_5^;;fB`0)-jC0S&P30N){L?eO+cHH@{;!IHze|*0P4|J3)aTZEsiHRs$DG&o_ z_7L_>shqtl-rBvKZ zCU0#s0Ad~+n4H|P0RS?YVQAV%0Boh4YYQrnPAV+je2k^v zo&Zef^f%*`lg-d{KD4K{EV)uDB{th-Alrh!zISi^ z%&!;vZ+jS?HYfg$uEG`v8Vq~U^~#7~GnIm>0bV@e!`g!woSVg6P?U7O}^7nU=4^(ZyKr5oQs+34wu%k3i zNrRP02!%k}R7xn6hXLd3$C)m$1Abpf`mL-pbLRVIe9oD<1dF&C47!xayF?TakzQhM zS4ugv<`@CXL=;uPlm=Yy8ykyRiA&WSrh~z50)|-R0+<~Z_3i{Nx z4%V9S_?HZP0zk7!T!^%YdaaVv3{NeCoRRJ@> z;G0793j^NgM7|G^)r`oQ{_*j-vI4T1|7wYx2;LKo0D!eS>y||bk^gWdIQL^N6spUX z-BRX_-7d5STF@G3fxF9PO#qRPfFEYgovSGlunT-)`9CMXd+I=^ug?ci)eDtF4>=s4 z=Lwh&2D`JT-4YtQ+^F#$+{jv=1MW^|g&jrsbS4z)d@6u|Ay~a?M0wfgP-?9LY$P%S z05p64ygQ}qPpm#N?pK{?d;jH6YOp~>%_NeWDI~X&5G6&v%v_5^;;fB`0)-jC0S&P30N){L?eO+cHH@{;!IHze|*0P4|J3)aTZEsiHRs$DG&o_ z_7L_>shqtl-rBvKZ zCU0#s0Ad~+n4H|P0RS?YVQAV%0Boh4YYQrnPAV+je2k^v zo&Zef^f%*`lg-d{KD4K{EV)uDB{th-Alrh!zISi^ z%&!;vZ+jS?HYfg$uEG`v8Vq~U^~#7~GnIm>0bV@e!`g!woSVg6P?U7O}^7nU=4^(ZyKr5oQs+34wu%k3i zNrRP02!%k}R7xn6hXLd3$C)m$1Abpf`mL-pbLRVIe9oD<1dF&C47!xayF?TakzQhM zS4ugv<`@CXL=;uPlm=Yy8ykyRiA&WSrh~z50)|-R0+<~Z_3i{Nx z4%V9S_?HZP0zk7!T!^%YdaaVv3{NeCoRRJ@> z;G0793j^NgM7|G^)r`oQ{_*j-vI4T1|7wYx2;LKo0D!eS>y||bk^gWdIQL^N6spUX z-BRX_-7d5STF@G3fxF9PO#qRPfFEYgovSGlunT-)`9CMXd+I=^ug?ci)eDtF4>=s4 z=Lwh&2D`JT-4YtQ+^F#$+{jv=1MW^|g&jrsbS4z)d@6u|Ay~a?M0wfgP-?9LY$P%S z05p64ygQ}qPpm#N?pK{?d;jH6YOp~>%_NeWDI~X&5G6&v%v_5^;;fB`0)-jC0S&P30N){L?eO+cHH@{;!IHze|*0P4|J3)aTZEsiHRs$DG&o_ z_7L_>shqtl-rBvKZ zCU0#s0Ad~+n4H|P0RS?YVQAV%0Boh4YYQrnPAV+je2k^v zo&Zef^f%*`lg-d{KD4K{EV)uDB{th-Alrh!zISi^ z%&!;vZ+jS?HYfg$uEG`v8Vq~U^~#7~GnIm>0bV@e!`g!woSVg6P?U7O}^7n - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/AppDelegate.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/AppDelegate.swift deleted file mode 100644 index 7f13108e70..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/AppDelegate.swift +++ /dev/null @@ -1,54 +0,0 @@ -// -// AppDelegate.swift -// ChartsDemo-iOS -// -// Created by Jacob Christie on 2017-07-03. -// Copyright © 2017 jc. All rights reserved. -// - -import UIKit - -@UIApplicationMain -class AppDelegate: UIResponder, UIApplicationDelegate { - - var window: UIWindow? - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { - // Override point for customization after application launch. - self.window = UIWindow(frame: UIScreen.main.bounds) - - - let vc = DemoListViewController() - let nav = UINavigationController(rootViewController: vc) - - window?.rootViewController = nav - window?.makeKeyAndVisible() - - return true - } - - func applicationWillResignActive(_ application: UIApplication) { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. - } - - func applicationDidEnterBackground(_ application: UIApplication) { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. - } - - func applicationWillEnterForeground(_ application: UIApplication) { - // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. - } - - func applicationDidBecomeActive(_ application: UIApplication) { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. - } - - func applicationWillTerminate(_ application: UIApplication) { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. - } - - -} - diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Components/BalloonMarker.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Components/BalloonMarker.swift deleted file mode 100644 index d18b3d2823..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Components/BalloonMarker.swift +++ /dev/null @@ -1,122 +0,0 @@ -// -// BalloonMarker.swift -// ChartsDemo-iOS -// -// Created by Jacob Christie on 2017-07-09. -// Copyright © 2017 jc. All rights reserved. -// - -import Foundation -import Charts - -public class BalloonMarker: MarkerImage { - public var color: UIColor - public var arrowSize = CGSize(width: 15, height: 11) - public var font: UIFont - public var textColor: UIColor - public var insets: UIEdgeInsets - public var minimumSize = CGSize() - - fileprivate var label: String? - fileprivate var _labelSize: CGSize = CGSize() - fileprivate var _paragraphStyle: NSMutableParagraphStyle? - fileprivate var _drawAttributes = [NSAttributedStringKey : AnyObject]() - - public init(color: UIColor, font: UIFont, textColor: UIColor, insets: UIEdgeInsets) { - self.color = color - self.font = font - self.textColor = textColor - self.insets = insets - - _paragraphStyle = NSParagraphStyle.default.mutableCopy() as? NSMutableParagraphStyle - _paragraphStyle?.alignment = .center - super.init() - } - - public override func offsetForDrawing(atPoint point: CGPoint) -> CGPoint { - let size = self.size - var point = point - point.x -= size.width / 2.0 - point.y -= size.height - return super.offsetForDrawing(atPoint: point) - } - - public override func draw(context: CGContext, point: CGPoint) { - guard let label = label else { return } - - let offset = self.offsetForDrawing(atPoint: point) - let size = self.size - - var rect = CGRect( - origin: CGPoint( - x: point.x + offset.x, - y: point.y + offset.y), - size: size) - rect.origin.x -= size.width / 2.0 - rect.origin.y -= size.height - - context.saveGState() - - context.setFillColor(color.cgColor) - context.beginPath() - context.move(to: CGPoint( - x: rect.origin.x, - y: rect.origin.y)) - context.addLine(to: CGPoint( - x: rect.origin.x + rect.size.width, - y: rect.origin.y)) - context.addLine(to: CGPoint( - x: rect.origin.x + rect.size.width, - y: rect.origin.y + rect.size.height - arrowSize.height)) - context.addLine(to: CGPoint( - x: rect.origin.x + (rect.size.width + arrowSize.width) / 2.0, - y: rect.origin.y + rect.size.height - arrowSize.height)) - context.addLine(to: CGPoint( - x: rect.origin.x + rect.size.width / 2.0, - y: rect.origin.y + rect.size.height)) - context.addLine(to: CGPoint( - x: rect.origin.x + (rect.size.width - arrowSize.width) / 2.0, - y: rect.origin.y + rect.size.height - arrowSize.height)) - context.addLine(to: CGPoint( - x: rect.origin.x, - y: rect.origin.y + rect.size.height - arrowSize.height)) - context.addLine(to: CGPoint( - x: rect.origin.x, - y: rect.origin.y)) - context.fillPath() - - rect.origin.y += self.insets.top - rect.size.height -= self.insets.top + self.insets.bottom - - UIGraphicsPushContext(context) - - label.draw(in: rect, withAttributes: _drawAttributes) - - UIGraphicsPopContext() - - context.restoreGState() - } - - public override func refreshContent(entry: ChartDataEntry, highlight: Highlight) { - setLabel(String(entry.y)) - } - - public func setLabel(_ newLabel: String) { - label = newLabel - - _drawAttributes.removeAll() - _drawAttributes[.font] = self.font - _drawAttributes[.paragraphStyle] = _paragraphStyle - _drawAttributes[.foregroundColor] = self.textColor - - _labelSize = label?.size(withAttributes: _drawAttributes) ?? CGSize.zero - - var size = CGSize() - size.width = _labelSize.width + self.insets.left + self.insets.right - size.height = _labelSize.height + self.insets.top + self.insets.bottom - size.width = max(minimumSize.width, size.width) - size.height = max(minimumSize.height, size.height) - self.size = size - } - -} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Components/RadarMarkerView.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Components/RadarMarkerView.swift deleted file mode 100644 index 019196d5e8..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Components/RadarMarkerView.swift +++ /dev/null @@ -1,27 +0,0 @@ -// -// RadarMarkerView.swift -// ChartsDemo -// -// 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 Charts - -public class RadarMarkerView: MarkerView { - @IBOutlet var label: UILabel! - - public override func awakeFromNib() { - self.offset.x = -self.frame.size.width / 2.0 - self.offset.y = -self.frame.size.height - 7.0 - } - - public override func refreshContent(entry: ChartDataEntry, highlight: Highlight) { - label.text = String.init(format: "%d %%", Int(round(entry.y))) - layoutIfNeeded() - } -} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Components/RadarMarkerView.xib b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Components/RadarMarkerView.xib deleted file mode 100644 index 687b73c95b..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Components/RadarMarkerView.xib +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - HelveticaNeue-Light - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Components/XYMarkerView.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Components/XYMarkerView.swift deleted file mode 100644 index 290ab85011..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Components/XYMarkerView.swift +++ /dev/null @@ -1,32 +0,0 @@ -// -// XYMarkerView.swift -// ChartsDemo-iOS -// -// Created by Jacob Christie on 2017-07-09. -// Copyright © 2017 jc. All rights reserved. -// - -import Foundation -import Charts - -public class XYMarkerView: BalloonMarker { - public var xAxisValueFormatter: AxisValueFormatter - fileprivate var yFormatter = NumberFormatter() - - public init(color: UIColor, font: UIFont, textColor: UIColor, insets: UIEdgeInsets, - xAxisValueFormatter: AxisValueFormatter) { - self.xAxisValueFormatter = xAxisValueFormatter - yFormatter.minimumFractionDigits = 1 - yFormatter.maximumFractionDigits = 1 - super.init(color: color, font: font, textColor: textColor, insets: insets) - } - - public override func refreshContent(entry: ChartDataEntry, highlight: Highlight) { - let string = "x: " - + xAxisValueFormatter.stringForValue(entry.x, axis: XAxis()) - + ", y: " - + yFormatter.string(from: NSNumber(floatLiteral: entry.y))! - setLabel(string) - } - -} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/DemoBaseViewController.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/DemoBaseViewController.swift deleted file mode 100644 index 2de87b60dc..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/DemoBaseViewController.swift +++ /dev/null @@ -1,362 +0,0 @@ -// -// DemoBaseViewController.swift -// ChartsDemo-iOS -// -// Created by Jacob Christie on 2017-07-03. -// Copyright © 2017 jc. All rights reserved. -// - -import UIKit -import Charts - -enum Option { - case toggleValues - case toggleIcons - case toggleHighlight - case animateX - case animateY - case animateXY - case saveToGallery - case togglePinchZoom - case toggleAutoScaleMinMax - case toggleData - case toggleBarBorders - // CandleChart - case toggleShadowColorSameAsCandle - // CombinedChart - case toggleLineValues - case toggleBarValues - case removeDataSet - // CubicLineSampleFillFormatter - case toggleFilled - case toggleCircles - case toggleCubic - case toggleHorizontalCubic - case toggleStepped - // HalfPieChartController - case toggleXValues - case togglePercent - case toggleHole - case spin - case drawCenter - // RadarChart - case toggleXLabels - case toggleYLabels - case toggleRotate - case toggleHighlightCircle - - var label: String { - switch self { - case .toggleValues: return "Toggle Y-Values" - case .toggleIcons: return "Toggle Icons" - case .toggleHighlight: return "Toggle Highlight" - case .animateX: return "Animate X" - case .animateY: return "Animate Y" - case .animateXY: return "Animate XY" - case .saveToGallery: return "Save to Camera Roll" - case .togglePinchZoom: return "Toggle PinchZoom" - case .toggleAutoScaleMinMax: return "Toggle auto scale min/max" - case .toggleData: return "Toggle Data" - case .toggleBarBorders: return "Toggle Bar Borders" - // CandleChart - case .toggleShadowColorSameAsCandle: return "Toggle shadow same color" - // CombinedChart - case .toggleLineValues: return "Toggle Line Values" - case .toggleBarValues: return "Toggle Bar Values" - case .removeDataSet: return "Remove Random Set" - // CubicLineSampleFillFormatter - case .toggleFilled: return "Toggle Filled" - case .toggleCircles: return "Toggle Circles" - case .toggleCubic: return "Toggle Cubic" - case .toggleHorizontalCubic: return "Toggle Horizontal Cubic" - case .toggleStepped: return "Toggle Stepped" - // HalfPieChartController - case .toggleXValues: return "Toggle X-Values" - case .togglePercent: return "Toggle Percent" - case .toggleHole: return "Toggle Hole" - case .spin: return "Spin" - case .drawCenter: return "Draw CenterText" - // RadarChart - case .toggleXLabels: return "Toggle X-Labels" - case .toggleYLabels: return "Toggle Y-Labels" - case .toggleRotate: return "Toggle Rotate" - case .toggleHighlightCircle: return "Toggle highlight circle" - } - } -} - -class DemoBaseViewController: UIViewController, ChartViewDelegate { - private var optionsTableView: UITableView? = nil - let parties = ["Party A", "Party B", "Party C", "Party D", "Party E", "Party F", - "Party G", "Party H", "Party I", "Party J", "Party K", "Party L", - "Party M", "Party N", "Party O", "Party P", "Party Q", "Party R", - "Party S", "Party T", "Party U", "Party V", "Party W", "Party X", - "Party Y", "Party Z"] - - @IBOutlet weak var optionsButton: UIButton! - var options: [Option]! - - var shouldHideData: Bool = false - - required init?(coder aDecoder: NSCoder) { - super.init(coder: aDecoder) - self.initialize() - } - - override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { - super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) - self.initialize() - } - - private func initialize() { - self.edgesForExtendedLayout = [] - } - - func optionTapped(_ option: Option) {} - - func handleOption(_ option: Option, forChartView chartView: ChartViewBase) { - switch option { - case .toggleValues: - for set in chartView.data!.dataSets { - set.isDrawValuesEnabled = !set.isDrawValuesEnabled - } - chartView.setNeedsDisplay() - - case .toggleIcons: - for set in chartView.data!.dataSets { - set.isDrawIconsEnabled = !set.isDrawIconsEnabled - } - chartView.setNeedsDisplay() - - case .toggleHighlight: - chartView.data!.highlightEnabled = !chartView.data!.isHighlightEnabled - chartView.setNeedsDisplay() - - case .animateX: - chartView.animate(xAxisDuration: 3) - - case .animateY: - chartView.animate(yAxisDuration: 3) - - case .animateXY: - chartView.animate(xAxisDuration: 3, yAxisDuration: 3) - - case .saveToGallery: - UIImageWriteToSavedPhotosAlbum(chartView.getChartImage(transparent: false)!, nil, nil, nil) - - case .togglePinchZoom: - let barLineChart = chartView as! BarLineChartViewBase - barLineChart.isPinchZoomEnabled = !barLineChart.isPinchZoomEnabled - chartView.setNeedsDisplay() - - case .toggleAutoScaleMinMax: - let barLineChart = chartView as! BarLineChartViewBase - barLineChart.autoScaleMinMaxEnabled = !barLineChart.isAutoScaleMinMaxEnabled - chartView.notifyDataSetChanged() - - case .toggleData: - shouldHideData = !shouldHideData - updateChartData() - - case .toggleBarBorders: - for set in chartView.data!.dataSets { - if let set = set as? BarChartDataSet { - set.barBorderWidth = set.barBorderWidth == 1.0 ? 0.0 : 1.0 - } - } - chartView.setNeedsDisplay() - default: - break - } - } - - @IBAction func optionsButtonTapped(_ sender: Any) { - if let optionsTableView = self.optionsTableView { - optionsTableView.removeFromSuperview() - self.optionsTableView = nil - return - } - - let optionsTableView = UITableView() - optionsTableView.backgroundColor = UIColor(white: 0, alpha: 0.9) - optionsTableView.delegate = self - optionsTableView.dataSource = self - - optionsTableView.translatesAutoresizingMaskIntoConstraints = false - - self.optionsTableView = optionsTableView - - var constraints = [NSLayoutConstraint]() - - constraints.append(NSLayoutConstraint(item: optionsTableView, - attribute: .leading, - relatedBy: .equal, - toItem: self.view, - attribute: .leading, - multiplier: 1, - constant: 40)) - - constraints.append(NSLayoutConstraint(item: optionsTableView, - attribute: .trailing, - relatedBy: .equal, - toItem: sender as! UIView, - attribute: .trailing, - multiplier: 1, - constant: 0)) - - constraints.append(NSLayoutConstraint(item: optionsTableView, - attribute: .top, - relatedBy: .equal, - toItem: sender, - attribute: .bottom, - multiplier: 1, - constant: 5)) - - self.view.addSubview(optionsTableView) - constraints.forEach { $0.isActive = true } - - let constraint = NSLayoutConstraint(item: optionsTableView, - attribute: .height, - relatedBy: .equal, - toItem: nil, - attribute: .height, - multiplier: 1, - constant: 220) - constraint.isActive = true - } - - func updateChartData() { - fatalError("updateChartData not overridden") - } - - func setup(pieChartView chartView: PieChartView) { - chartView.usePercentValues = true - chartView.isDrawSlicesUnderHoleEnabled = false - chartView.holeRadiusPercent = 0.58 - chartView.transparentCircleRadiusPercent = 0.61 - chartView.chartDescription?.isEnabled = false - chartView.setExtraOffsets(left: 5, top: 10, right: 5, bottom: 5) - - chartView.isDrawCenterTextEnabled = true - - let paragraphStyle = NSParagraphStyle.default.mutableCopy() as! NSMutableParagraphStyle - paragraphStyle.lineBreakMode = .byTruncatingTail - paragraphStyle.alignment = .center - - let centerText = NSMutableAttributedString(string: "Charts\nby Daniel Cohen Gindi") - centerText.setAttributes([.font : UIFont(name: "HelveticaNeue-Light", size: 13)!, - .paragraphStyle : paragraphStyle], range: NSRange(location: 0, length: centerText.length)) - centerText.addAttributes([.font : UIFont(name: "HelveticaNeue-Light", size: 11)!, - .foregroundColor : UIColor.gray], range: NSRange(location: 10, length: centerText.length - 10)) - centerText.addAttributes([.font : UIFont(name: "HelveticaNeue-Light", size: 11)!, - .foregroundColor : UIColor(red: 51/255, green: 181/255, blue: 229/255, alpha: 1)], range: NSRange(location: centerText.length - 19, length: 19)) - chartView.centerAttributedText = centerText; - - chartView.isDrawHoleEnabled = true - chartView.rotationAngle = 0 - chartView.isRotationEnabled = true - chartView.isHighlightPerTapEnabled = true - - var l = chartView.legend - l.horizontalAlignment = .right - l.verticalAlignment = .top - l.orientation = .vertical - l.drawInside = false - l.xEntrySpace = 7 - l.yEntrySpace = 0 - l.yOffset = 0 - chartView.legend = l - } - - func setup(radarChartView chartView: RadarChartView) { - chartView.chartDescription?.isEnabled = false - } - - func setup(barLineChartView chartView: BarLineChartViewBase) { - chartView.chartDescription?.isEnabled = false - - chartView.isDragEnabled = true - chartView.setScaleEnabled(true) - chartView.isPinchZoomEnabled = false - - // ChartYAxis *leftAxis = chartView.leftAxis; - - let xAxis = chartView.xAxis - xAxis.labelPosition = .bottom - - chartView.rightAxis.isEnabled = false - } - // TODO: Cannot override from extensions - //extension DemoBaseViewController: ChartViewDelegate { - func chartValueSelected(_ chartView: ChartViewBase, entry: ChartDataEntry, highlight: Highlight) { - NSLog("chartValueSelected"); - } - - func chartValueNothingSelected(_ chartView: ChartViewBase) { - NSLog("chartValueNothingSelected"); - } - - func chartScaled(_ chartView: ChartViewBase, scaleX: CGFloat, scaleY: CGFloat) { - - } - - func chartTranslated(_ chartView: ChartViewBase, dX: CGFloat, dY: CGFloat) { - - } -} - -extension DemoBaseViewController: UITableViewDelegate, UITableViewDataSource { - func numberOfSections(in tableView: UITableView) -> Int { - if optionsTableView != nil { - return 1 - } - - return 0 - } - - @available(iOS 2.0, *) - func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - if optionsTableView != nil { - return options.count - } - - return 0 - - } - - func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { - if optionsTableView != nil { - return 40.0; - } - - return 44.0; - } - - @available(iOS 2.0, *) - func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - var cell = tableView.dequeueReusableCell(withIdentifier: "Cell") - - if cell == nil { - cell = UITableViewCell(style: .default, reuseIdentifier: "Cell") - cell?.backgroundView = nil - cell?.backgroundColor = .clear - cell?.textLabel?.textColor = .white - } - cell?.textLabel?.text = self.options[indexPath.row].label - - return cell! - } - - func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - if optionsTableView != nil { - tableView.deselectRow(at: indexPath, animated: true) - - optionsTableView?.removeFromSuperview() - self.optionsTableView = nil - - self.optionTapped(self.options[indexPath.row]) - } - - } -} - diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/DemoListViewController.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/DemoListViewController.swift deleted file mode 100644 index 1322e488cb..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/DemoListViewController.swift +++ /dev/null @@ -1,129 +0,0 @@ -// -// DemoListViewController.swift -// ChartsDemo-iOS -// -// Created by Jacob Christie on 2017-07-09. -// Copyright © 2017 jc. All rights reserved. -// - -import UIKit - -private struct ItemDef { - let title: String - let subtitle: String - let `class`: AnyClass -} - -class DemoListViewController: UIViewController { - - @IBOutlet var tableView: UITableView! - private var itemDefs = [ItemDef(title: "Line Chart", - subtitle: "A simple demonstration of the linechart.", - class: LineChart1ViewController.self), - ItemDef(title: "Line Chart (Dual YAxis)", - subtitle: "Demonstration of the linechart with dual y-axis.", - class: LineChart2ViewController.self), - ItemDef(title: "Bar Chart", - subtitle: "A simple demonstration of the bar chart.", - class: BarChartViewController.self), - ItemDef(title: "Horizontal Bar Chart", - subtitle: "A simple demonstration of the horizontal bar chart.", - class: HorizontalBarChartViewController.self), - ItemDef(title: "Combined Chart", - subtitle: "Demonstrates how to create a combined chart (bar and line in this case).", - class: CombinedChartViewController.self), - ItemDef(title: "Pie Chart", - subtitle: "A simple demonstration of the pie chart.", - class: PieChartViewController.self), - ItemDef(title: "Pie Chart with value lines", - subtitle: "A simple demonstration of the pie chart with polyline notes.", - class: PiePolylineChartViewController.self), - ItemDef(title: "Scatter Chart", - subtitle: "A simple demonstration of the scatter chart.", - class: ScatterChartViewController.self), - ItemDef(title: "Bubble Chart", - subtitle: "A simple demonstration of the bubble chart.", - class: BubbleChartViewController.self), - ItemDef(title: "Stacked Bar Chart", - subtitle: "A simple demonstration of a bar chart with stacked bars.", - class: StackedBarChartViewController.self), - ItemDef(title: "Stacked Bar Chart Negative", - subtitle: "A simple demonstration of stacked bars with negative and positive values.", - class: NegativeStackedBarChartViewController.self), - ItemDef(title: "Another Bar Chart", - subtitle: "Implementation of a BarChart that only shows values at the bottom.", - class: AnotherBarChartViewController.self), - ItemDef(title: "Multiple Lines Chart", - subtitle: "A line chart with multiple DataSet objects. One color per DataSet.", - class: MultipleLinesChartViewController.self), - ItemDef(title: "Multiple Bars Chart", - subtitle: "A bar chart with multiple DataSet objects. One multiple colors per DataSet.", - class: MultipleBarChartViewController.self), - ItemDef(title: "Candle Stick Chart", - subtitle: "Demonstrates usage of the CandleStickChart.", - class: CandleStickChartViewController.self), - ItemDef(title: "Cubic Line Chart", - subtitle: "Demonstrates cubic lines in a LineChart.", - class: CubicLineChartViewController.self), - ItemDef(title: "Radar Chart", - subtitle: "Demonstrates the use of a spider-web like (net) chart.", - class: RadarChartViewController.self), - ItemDef(title: "Colored Line Chart", - subtitle: "Shows a LineChart with different background and line color.", - class: ColoredLineChartViewController.self), - ItemDef(title: "Sinus Bar Chart", - subtitle: "A Bar Chart plotting the sinus function with 8.000 values.", - class: SinusBarChartViewController.self), - ItemDef(title: "BarChart positive / negative", - subtitle: "This demonstrates how to create a BarChart with positive and negative values in different colors.", - class: PositiveNegativeBarChartViewController.self), - ItemDef(title: "Time Line Chart", - subtitle: "Simple demonstration of a time-chart. This chart draws one line entry per hour originating from the current time in milliseconds.", - class: LineChartTimeViewController.self), - ItemDef(title: "Filled Line Chart", - subtitle: "This demonstrates how to fill an area between two LineDataSets.", - class: LineChartFilledViewController.self), - ItemDef(title: "Half Pie Chart", - subtitle: "This demonstrates how to create a 180 degree PieChart.", - class: HalfPieChartViewController.self) - ] - - override func viewDidLoad() { - super.viewDidLoad() - - self.title = "Charts Demonstration" - self.tableView.rowHeight = 70 - //FIXME: Add TimeLineChart - - } -} - -extension DemoListViewController: UITableViewDelegate, UITableViewDataSource { - func numberOfSections(in tableView: UITableView) -> Int { - return 1 - } - - func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return self.itemDefs.count - } - - func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let def = self.itemDefs[indexPath.row] - let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") ?? UITableViewCell(style: .subtitle, reuseIdentifier: "Cell") - cell.textLabel?.text = def.title - cell.detailTextLabel?.text = def.subtitle - cell.detailTextLabel?.numberOfLines = 0 - - return cell - } - - func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - let def = self.itemDefs[indexPath.row] - - let vcClass = def.class as! UIViewController.Type - let vc = vcClass.init() - - self.navigationController?.pushViewController(vc, animated: true) - tableView.deselectRow(at: indexPath, animated: true) - } -} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/DemoListViewController.xib b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/DemoListViewController.xib deleted file mode 100644 index 40845c0a91..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/DemoListViewController.xib +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/AnotherBarChartViewController.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/AnotherBarChartViewController.swift deleted file mode 100644 index 8e84fa699c..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/AnotherBarChartViewController.swift +++ /dev/null @@ -1,98 +0,0 @@ -// -// AnotherBarChartViewController.swift -// ChartsDemo-iOS -// -// Created by Jacob Christie on 2017-07-09. -// Copyright © 2017 jc. All rights reserved. -// - -import UIKit -import Charts - -class AnotherBarChartViewController: DemoBaseViewController { - - @IBOutlet var chartView: BarChartView! - @IBOutlet var sliderX: UISlider! - @IBOutlet var sliderY: UISlider! - @IBOutlet var sliderTextX: UITextField! - @IBOutlet var sliderTextY: UITextField! - - override func viewDidLoad() { - super.viewDidLoad() - - // Do any additional setup after loading the view. - self.options = [.toggleValues, - .toggleHighlight, - .animateX, - .animateY, - .animateXY, - .saveToGallery, - .togglePinchZoom, - .toggleData, - .toggleBarBorders] - - chartView.delegate = self - - chartView.chartDescription?.isEnabled = false - chartView.maxVisibleCount = 60 - chartView.isPinchZoomEnabled = false - chartView.isDrawBarShadowEnabled = false - - let xAxis = chartView.xAxis - xAxis.labelPosition = .bottom - - chartView.legend.isEnabled = false - - sliderX.value = 10 - sliderY.value = 100 - self.slidersValueChanged(nil) - } - - - override func updateChartData() { - if self.shouldHideData { - chartView.data = nil - return - } - - self.setDataCount(Int(sliderX.value) + 1, range: Double(sliderY.value)) - } - - func setDataCount(_ count: Int, range: Double) { - let yVals = (0.. BarChartDataEntry in - let mult = range + 1 - let val = Double(arc4random_uniform(UInt32(mult))) + mult/3 - return BarChartDataEntry(x: Double(i), y: val) - } - - var set1: BarChartDataSet! = nil - if let set = chartView.data?.dataSets.first as? BarChartDataSet { - set1 = set - set1?.values = yVals - chartView.data?.notifyDataChanged() - chartView.notifyDataSetChanged() - } else { - set1 = BarChartDataSet(values: yVals, label: "Data Set") - set1.colors = ChartColorTemplates.vordiplom - set1.isDrawValuesEnabled = false - - let data = BarChartData(dataSet: set1) - chartView.data = data - chartView.fitBars = true - } - - chartView.setNeedsDisplay() - } - - override func optionTapped(_ option: Option) { - super.handleOption(option, forChartView: chartView) - } - - // MARK: - Actions - @IBAction func slidersValueChanged(_ sender: Any?) { - sliderTextX.text = "\(Int(sliderX.value))" - sliderTextY.text = "\(Int(sliderY.value))" - - self.updateChartData() - } -} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/AnotherBarChartViewController.xib b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/AnotherBarChartViewController.xib deleted file mode 100644 index 330b30940b..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/AnotherBarChartViewController.xib +++ /dev/null @@ -1,100 +0,0 @@ - - - - - - - - - - - - HelveticaNeue-Light - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/BarChartViewController.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/BarChartViewController.swift deleted file mode 100644 index f2f9c38978..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/BarChartViewController.swift +++ /dev/null @@ -1,152 +0,0 @@ -// -// BarChartViewController.swift -// ChartsDemo-iOS -// -// Created by Jacob Christie on 2017-07-09. -// Copyright © 2017 jc. All rights reserved. -// - -import UIKit -import Charts - -class BarChartViewController: DemoBaseViewController { - - @IBOutlet var chartView: BarChartView! - @IBOutlet var sliderX: UISlider! - @IBOutlet var sliderY: UISlider! - @IBOutlet var sliderTextX: UITextField! - @IBOutlet var sliderTextY: UITextField! - - override func viewDidLoad() { - super.viewDidLoad() - - // Do any additional setup after loading the view. - self.title = "Bar Chart" - - self.options = [.toggleValues, - .toggleHighlight, - .animateX, - .animateY, - .animateXY, - .saveToGallery, - .togglePinchZoom, - .toggleData, - .toggleBarBorders] - - self.setup(barLineChartView: chartView) - - chartView.delegate = self - - chartView.isDrawBarShadowEnabled = false - chartView.isDrawValueAboveBarEnabled = false - - chartView.maxVisibleCount = 60 - - let xAxis = chartView.xAxis - xAxis.labelPosition = .bottom - xAxis.labelFont = .systemFont(ofSize: 10) - xAxis.granularity = 1 - xAxis.labelCount = 7 - xAxis.valueFormatter = DayAxisValueFormatter(chart: chartView) - - let leftAxisFormatter = NumberFormatter() - leftAxisFormatter.minimumFractionDigits = 0 - leftAxisFormatter.maximumFractionDigits = 1 - leftAxisFormatter.negativeSuffix = " $" - leftAxisFormatter.positiveSuffix = " $" - - let leftAxis = chartView.leftAxis - leftAxis.labelFont = .systemFont(ofSize: 10) - leftAxis.labelCount = 8 - leftAxis.valueFormatter = DefaultAxisValueFormatter(formatter: leftAxisFormatter) - leftAxis.labelPosition = .outsideChart - leftAxis.spaceTop = 0.15 - leftAxis.axisMinimum = 0 // FIXME: HUH?? this replaces startAtZero = YES - - let rightAxis = chartView.rightAxis - rightAxis.isEnabled = true - rightAxis.labelFont = .systemFont(ofSize: 10) - rightAxis.labelCount = 8 - rightAxis.valueFormatter = leftAxis.valueFormatter - rightAxis.spaceTop = 0.15 - rightAxis.axisMinimum = 0 - - var l = chartView.legend - l.horizontalAlignment = .left - l.verticalAlignment = .bottom - l.orientation = .horizontal - l.drawInside = false - l.form = .circle - l.formSize = 9 - l.font = UIFont(name: "HelveticaNeue-Light", size: 11)! - l.xEntrySpace = 4 - chartView.legend = l - - let marker = XYMarkerView(color: UIColor(white: 180/250, alpha: 1), - font: .systemFont(ofSize: 12), - textColor: .white, - insets: UIEdgeInsets(top: 8, left: 8, bottom: 20, right: 8), - xAxisValueFormatter: chartView.xAxis.valueFormatter!) - marker.chartView = chartView - marker.minimumSize = CGSize(width: 80, height: 40) - chartView.marker = marker - - sliderX.value = 12 - sliderY.value = 50 - slidersValueChanged(nil) - } - - override func updateChartData() { - if self.shouldHideData { - chartView.data = nil - return - } - - self.setDataCount(Int(sliderX.value) + 1, range: UInt32(sliderY.value)) - } - - func setDataCount(_ count: Int, range: UInt32) { - let start = 1 - - let yVals = (start.. BarChartDataEntry in - let mult = range + 1 - let val = Double(arc4random_uniform(mult)) - if arc4random_uniform(100) < 25 { - return BarChartDataEntry(x: Double(i), y: val, icon: UIImage(named: "icon")) - } else { - return BarChartDataEntry(x: Double(i), y: val) - } - } - - var set1: BarChartDataSet! = nil - if let set = chartView.data?.dataSets.first as? BarChartDataSet { - set1 = set - set1.values = yVals - chartView.data?.notifyDataChanged() - chartView.notifyDataSetChanged() - } else { - set1 = BarChartDataSet(values: yVals, label: "The year 2017") - set1.colors = ChartColorTemplates.material - set1.isDrawValuesEnabled = false - - let data = BarChartData(dataSet: set1) - data.setValueFont(UIFont(name: "HelveticaNeue-Light", size: 10)!) - data.barWidth = 0.9 - chartView.data = data - } - -// chartView.setNeedsDisplay() - } - - override func optionTapped(_ option: Option) { - super.handleOption(option, forChartView: chartView) - } - - // MARK: - Actions - @IBAction func slidersValueChanged(_ sender: Any?) { - sliderTextX.text = "\(Int(sliderX.value + 2))" - sliderTextY.text = "\(Int(sliderY.value))" - - self.updateChartData() - } -} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/BarChartViewController.xib b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/BarChartViewController.xib deleted file mode 100644 index 1c769416b8..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/BarChartViewController.xib +++ /dev/null @@ -1,100 +0,0 @@ - - - - - - - - - - - - HelveticaNeue-Light - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/BubbleChartViewController.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/BubbleChartViewController.swift deleted file mode 100644 index 3df67ae068..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/BubbleChartViewController.swift +++ /dev/null @@ -1,127 +0,0 @@ -// -// BubbleChartViewController.swift -// ChartsDemo-iOS -// -// Created by Jacob Christie on 2017-07-09. -// Copyright © 2017 jc. All rights reserved. -// - -import UIKit -import Charts - -class BubbleChartViewController: DemoBaseViewController { - - @IBOutlet var chartView: BubbleChartView! - @IBOutlet var sliderX: UISlider! - @IBOutlet var sliderY: UISlider! - @IBOutlet var sliderTextX: UITextField! - @IBOutlet var sliderTextY: UITextField! - - override func viewDidLoad() { - super.viewDidLoad() - - // Do any additional setup after loading the view. - self.title = "Bubble Chart" - self.options = [.toggleValues, - .toggleIcons, - .toggleHighlight, - .animateX, - .animateY, - .animateXY, - .saveToGallery, - .togglePinchZoom, - .toggleAutoScaleMinMax, - .toggleData] - - chartView.delegate = self - - chartView.chartDescription?.isEnabled = false - - chartView.isDragEnabled = false - chartView.setScaleEnabled(true) - chartView.maxVisibleCount = 200 - chartView.isPinchZoomEnabled = true - - chartView.legend.horizontalAlignment = .right - chartView.legend.verticalAlignment = .top - chartView.legend.orientation = .vertical - chartView.legend.drawInside = false - chartView.legend.font = UIFont(name: "HelveticaNeue-Light", size: 10)! - - chartView.leftAxis.labelFont = UIFont(name: "HelveticaNeue-Light", size: 10)! - chartView.leftAxis.spaceTop = 0.3 - chartView.leftAxis.spaceBottom = 0.3 - chartView.leftAxis.axisMinimum = 0 - - chartView.rightAxis.isEnabled = false - - chartView.xAxis.labelPosition = .bottom - chartView.xAxis.labelFont = UIFont(name: "HelveticaNeue-Light", size: 10)! - - sliderX.value = 10 - sliderY.value = 50 - slidersValueChanged(nil) - } - - override func updateChartData() { - if self.shouldHideData { - chartView.data = nil - return - } - - self.setDataCount(Int(sliderX.value), range: UInt32(sliderY.value)) - } - - func setDataCount(_ count: Int, range: UInt32) { - let yVals1 = (0.. BubbleChartDataEntry in - let val = Double(arc4random_uniform(range)) - let size = CGFloat(arc4random_uniform(range)) - return BubbleChartDataEntry(x: Double(i), y: val, size: size, icon: UIImage(named: "icon")) - } - let yVals2 = (0.. BubbleChartDataEntry in - let val = Double(arc4random_uniform(range)) - let size = CGFloat(arc4random_uniform(range)) - return BubbleChartDataEntry(x: Double(i), y: val, size: size, icon: UIImage(named: "icon")) - } - let yVals3 = (0.. BubbleChartDataEntry in - let val = Double(arc4random_uniform(range)) - let size = CGFloat(arc4random_uniform(range)) - return BubbleChartDataEntry(x: Double(i), y: val, size: size) - } - - let set1 = BubbleChartDataSet(values: yVals1, label: "DS 1") - set1.isDrawIconsEnabled = false - set1.setColor(ChartColorTemplates.colorful[0], alpha: 0.5) - set1.isDrawValuesEnabled = true - - let set2 = BubbleChartDataSet(values: yVals2, label: "DS 2") - set2.isDrawIconsEnabled = false - set2.iconsOffset = CGPoint(x: 0, y: 15) - set2.setColor(ChartColorTemplates.colorful[1], alpha: 0.5) - set2.isDrawValuesEnabled = true - - let set3 = BubbleChartDataSet(values: yVals3, label: "DS 3") - set3.setColor(ChartColorTemplates.colorful[2], alpha: 0.5) - set3.isDrawValuesEnabled = true - - let data = BubbleChartData(dataSets: [set1, set2, set3]) - data.setDrawValues(false) - data.setValueFont(UIFont(name: "HelveticaNeue-Light", size: 7)!) - data.setHighlightCircleWidth(1.5) - data.setValueTextColor(.white) - - chartView.data = data - } - - override func optionTapped(_ option: Option) { - super.handleOption(option, forChartView: chartView) - } - - // MARK: - Actions - @IBAction func slidersValueChanged(_ sender: Any?) { - sliderTextX.text = "\(Int(sliderX.value))" - sliderTextY.text = "\(Int(sliderY.value))" - - self.updateChartData() - } -} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/BubbleChartViewController.xib b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/BubbleChartViewController.xib deleted file mode 100644 index f49a384cbe..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/BubbleChartViewController.xib +++ /dev/null @@ -1,100 +0,0 @@ - - - - - - - - - - - - HelveticaNeue-Light - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/CandleStickChartViewController.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/CandleStickChartViewController.swift deleted file mode 100644 index df04b90db1..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/CandleStickChartViewController.swift +++ /dev/null @@ -1,122 +0,0 @@ -// -// CandleStickChartViewController.swift -// ChartsDemo-iOS -// -// Created by Jacob Christie on 2017-07-09. -// Copyright © 2017 jc. All rights reserved. -// - -import UIKit -import Charts - -class CandleStickChartViewController: DemoBaseViewController { - - @IBOutlet var chartView: CandleStickChartView! - @IBOutlet var sliderX: UISlider! - @IBOutlet var sliderY: UISlider! - @IBOutlet var sliderTextX: UITextField! - @IBOutlet var sliderTextY: UITextField! - - override func viewDidLoad() { - super.viewDidLoad() - - // Do any additional setup after loading the view. - self.title = "Bubble Chart" - self.options = [.toggleValues, - .toggleIcons, - .toggleHighlight, - .animateX, - .animateY, - .animateXY, - .saveToGallery, - .togglePinchZoom, - .toggleAutoScaleMinMax, - .toggleShadowColorSameAsCandle, - .toggleData] - - chartView.delegate = self - - chartView.chartDescription?.isEnabled = false - - chartView.isDragEnabled = false - chartView.setScaleEnabled(true) - chartView.maxVisibleCount = 200 - chartView.isPinchZoomEnabled = true - - chartView.legend.horizontalAlignment = .right - chartView.legend.verticalAlignment = .top - chartView.legend.orientation = .vertical - chartView.legend.drawInside = false - chartView.legend.font = UIFont(name: "HelveticaNeue-Light", size: 10)! - - chartView.leftAxis.labelFont = UIFont(name: "HelveticaNeue-Light", size: 10)! - chartView.leftAxis.spaceTop = 0.3 - chartView.leftAxis.spaceBottom = 0.3 - chartView.leftAxis.axisMinimum = 0 - - chartView.rightAxis.isEnabled = false - - chartView.xAxis.labelPosition = .bottom - chartView.xAxis.labelFont = UIFont(name: "HelveticaNeue-Light", size: 10)! - - sliderX.value = 10 - sliderY.value = 50 - slidersValueChanged(nil) - } - - override func updateChartData() { - if self.shouldHideData { - chartView.data = nil - return - } - - self.setDataCount(Int(sliderX.value), range: UInt32(sliderY.value)) - } - - func setDataCount(_ count: Int, range: UInt32) { - let yVals1 = (0.. CandleChartDataEntry in - let mult = range + 1 - let val = Double(arc4random_uniform(40) + mult) - let high = Double(arc4random_uniform(9) + 8) - let low = Double(arc4random_uniform(9) + 8) - let open = Double(arc4random_uniform(6) + 1) - let close = Double(arc4random_uniform(6) + 1) - let even = i % 2 == 0 - - return CandleChartDataEntry(x: Double(i), shadowH: val + high, shadowL: val - low, open: even ? val + open : val - open, close: even ? val - close : val + close, icon: UIImage(named: "icon")!) - } - - let set1 = CandleChartDataSet(values: yVals1, label: "Data Set") - set1.axisDependency = .left - set1.setColor(UIColor(white: 80/255, alpha: 1)) - set1.isDrawIconsEnabled = false - set1.shadowColor = .darkGray - set1.shadowWidth = 0.7 - set1.decreasingColor = .red - set1.decreasingFilled = true - set1.increasingColor = UIColor(red: 122/255, green: 242/255, blue: 84/255, alpha: 1) - set1.increasingFilled = false - set1.neutralColor = .blue - - let data = CandleChartData(dataSet: set1) - chartView.data = data - } - - override func optionTapped(_ option: Option) { - if .toggleShadowColorSameAsCandle ~= option { - for set in chartView.data!.dataSets as! [CandleChartDataSet] { - set.shadowColorSameAsCandle = !set.shadowColorSameAsCandle - } - chartView.notifyDataSetChanged() - } else { - super.handleOption(option, forChartView: chartView) - } - } - - // MARK: - Actions - @IBAction func slidersValueChanged(_ sender: Any?) { - sliderTextX.text = "\(Int(sliderX.value))" - sliderTextY.text = "\(Int(sliderY.value))" - - self.updateChartData() - }} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/CandleStickChartViewController.xib b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/CandleStickChartViewController.xib deleted file mode 100644 index 598f366e54..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/CandleStickChartViewController.xib +++ /dev/null @@ -1,100 +0,0 @@ - - - - - - - - - - - - HelveticaNeue-Light - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/ColoredLineChartViewController.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/ColoredLineChartViewController.swift deleted file mode 100644 index 0c2e651594..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/ColoredLineChartViewController.swift +++ /dev/null @@ -1,77 +0,0 @@ -// -// ColoredLineChartViewController.swift -// ChartsDemo-iOS -// -// Created by Jacob Christie on 2017-07-04. -// Copyright © 2017 jc. All rights reserved. -// - -import UIKit -import Charts - -class ColoredLineChartViewController: DemoBaseViewController { - @IBOutlet var chartViews: [LineChartView]! - - override func viewDidLoad() { - super.viewDidLoad() - - self.title = "Colored Line Chart" - - let colors = [UIColor(red: 137/255, green: 230/255, blue: 81/255, alpha: 1), - UIColor(red: 240/255, green: 240/255, blue: 30/255, alpha: 1), - UIColor(red: 89/255, green: 199/255, blue: 250/255, alpha: 1), - UIColor(red: 250/255, green: 104/255, blue: 104/255, alpha: 1)] - - for (i, chartView) in chartViews.enumerated() { - let data = dataWithCount(36, range: 100) - data.setValueFont(UIFont(name: "HelveticaNeue", size: 7)!) - - setupChart(chartView, data: data, color: colors[i % colors.count]) - } - } - - func setupChart(_ chart: LineChartView, data: LineChartData, color: UIColor) { - (data.getDataSetByIndex(0) as! LineChartDataSet).circleHoleColor = color - - chart.delegate = self - chart.backgroundColor = color - - chart.chartDescription?.isEnabled = false - - chart.isDragEnabled = true - chart.setScaleEnabled(true) - chart.isPinchZoomEnabled = false - chart.setViewPortOffsets(left: 10, top: 0, right: 10, bottom: 0) - - chart.legend.isEnabled = false - - chart.leftAxis.isEnabled = false - chart.leftAxis.spaceTop = 0.4 - chart.leftAxis.spaceBottom = 0.4 - chart.rightAxis.isEnabled = false - chart.xAxis.isEnabled = false - - chart.data = data - - chart.animate(xAxisDuration: 2.5) - } - - func dataWithCount(_ count: Int, range: UInt32) -> LineChartData { - let yVals = (0.. ChartDataEntry in - let val = Double(arc4random_uniform(range)) + 3 - return ChartDataEntry(x: Double(i), y: val) - } - - let set1 = LineChartDataSet(values: yVals, label: "DataSet 1") - - set1.lineWidth = 1.75 - set1.circleRadius = 5.0 - set1.circleHoleRadius = 2.5 - set1.setColor(.white) - set1.setCircleColor(.white) - set1.highlightColor = .white - set1.isDrawValuesEnabled = false - - return LineChartData(dataSet: set1) - } -} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/ColoredLineChartViewController.xib b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/ColoredLineChartViewController.xib deleted file mode 100644 index bb0f701ec3..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/ColoredLineChartViewController.xib +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/CombinedChartViewController.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/CombinedChartViewController.swift deleted file mode 100644 index b5c14ac68e..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/CombinedChartViewController.swift +++ /dev/null @@ -1,233 +0,0 @@ -// -// CombinedChartViewController.swift -// ChartsDemo-iOS -// -// Created by Jacob Christie on 2017-07-09. -// Copyright © 2017 jc. All rights reserved. -// - -import UIKit -import Charts - -private let ITEM_COUNT = 12 - -class CombinedChartViewController: DemoBaseViewController { - @IBOutlet var chartView: CombinedChartView! - - let months = ["Jan", "Feb", "Mar", - "Apr", "May", "Jun", - "Jul", "Aug", "Sep", - "Oct", "Nov", "Dec"] - - - override func viewDidLoad() { - super.viewDidLoad() - - // Do any additional setup after loading the view. - self.title = "Combined Chart" - self.options = [.toggleLineValues, - .toggleBarValues, - .saveToGallery, - .toggleData, - .toggleBarBorders, - .removeDataSet] - - chartView.delegate = self - - chartView.chartDescription?.isEnabled = false - - chartView.isDrawBarShadowEnabled = false - chartView.isHighlightFullBarEnabled = false - - - chartView.drawOrder = [.bar, - .bubble, - .candle, - .line, - .scatter] - - var l = chartView.legend - l.wordWrapEnabled = true - l.horizontalAlignment = .center - l.verticalAlignment = .bottom - l.orientation = .horizontal - l.drawInside = false - chartView.legend = l - - let rightAxis = chartView.rightAxis - rightAxis.axisMinimum = 0 - - let leftAxis = chartView.leftAxis - leftAxis.axisMinimum = 0 - - let xAxis = chartView.xAxis - xAxis.labelPosition = .bothSided - xAxis.axisMinimum = 0 - xAxis.granularity = 1 - xAxis.valueFormatter = self - - self.updateChartData() - } - - override func updateChartData() { - if self.shouldHideData { - chartView.data = nil - return - } - - self.setChartData() - } - - func setChartData() { - let data = CombinedChartData() - data.lineData = generateLineData() - data.barData = generateBarData() - data.bubbleData = generateBubbleData() - data.scatterData = generateScatterData() - data.candleData = generateCandleData() - - chartView.xAxis.axisMaximum = data.xMax + 0.25 - - chartView.data = data - } - - override func optionTapped(_ option: Option) { - switch option { - case .toggleLineValues: - for set in chartView.data!.dataSets { - if let set = set as? LineChartDataSet { - set.isDrawValuesEnabled = !set .isDrawValuesEnabled - - } - } - chartView.setNeedsDisplay() - - case .toggleBarValues: - for set in chartView.data!.dataSets { - if let set = set as? BarChartDataSet { - set.isDrawValuesEnabled = !set .isDrawValuesEnabled - } - } - chartView.setNeedsDisplay() - - case .removeDataSet: - let rnd = Int(arc4random_uniform(UInt32(chartView.data!.dataSetCount))) - chartView.data?.removeDataSet(chartView.data!.getDataSetByIndex(rnd)) - chartView.data?.notifyDataChanged() - chartView.notifyDataSetChanged() - - default: - super.handleOption(option, forChartView: chartView) - } - } - - func generateLineData() -> LineChartData { - let entries = (0.. ChartDataEntry in - return ChartDataEntry(x: Double(i) + 0.5, y: Double(arc4random_uniform(15) + 5)) - } - - let set = LineChartDataSet(values: entries, label: "Line DataSet") - set.setColor(UIColor(red: 240/255, green: 238/255, blue: 70/255, alpha: 1)) - set.lineWidth = 2.5 - set.setCircleColor(UIColor(red: 240/255, green: 238/255, blue: 70/255, alpha: 1)) - set.circleRadius = 5 - set.circleHoleRadius = 2.5 - set.fillColor = UIColor(red: 240/255, green: 238/255, blue: 70/255, alpha: 1) - set.mode = .cubicBezier - set.isDrawValuesEnabled = true - set.valueFont = .systemFont(ofSize: 10) - set.valueTextColor = UIColor(red: 240/255, green: 238/255, blue: 70/255, alpha: 1) - - set.axisDependency = .left - - return LineChartData(dataSet: set) - } - - func generateBarData() -> BarChartData { - let entries1 = (0.. BarChartDataEntry in - return BarChartDataEntry(x: 0, y: Double(arc4random_uniform(25) + 25)) - } - let entries2 = (0.. BarChartDataEntry in - return BarChartDataEntry(x: 0, yValues: [Double(arc4random_uniform(13) + 12), Double(arc4random_uniform(13) + 12)]) - } - - let set1 = BarChartDataSet(values: entries1, label: "Bar 1") - set1.setColor(UIColor(red: 60/255, green: 220/255, blue: 78/255, alpha: 1)) - set1.valueTextColor = UIColor(red: 60/255, green: 220/255, blue: 78/255, alpha: 1) - set1.valueFont = .systemFont(ofSize: 10) - set1.axisDependency = .left - - let set2 = BarChartDataSet(values: entries2, label: "") - set2.stackLabels = ["Stack 1", "Stack 2"] - set2.colors = [UIColor(red: 61/255, green: 165/255, blue: 255/255, alpha: 1), - UIColor(red: 23/255, green: 197/255, blue: 255/255, alpha: 1) - ] - set2.valueTextColor = UIColor(red: 61/255, green: 165/255, blue: 255/255, alpha: 1) - set2.valueFont = .systemFont(ofSize: 10) - set2.axisDependency = .left - - let groupSpace = 0.06 - let barSpace = 0.02 // x2 dataset - let barWidth = 0.45 // x2 dataset - // (0.45 + 0.02) * 2 + 0.06 = 1.00 -> interval per "group" - - let data = BarChartData(dataSets: [set1, set2]) - data.barWidth = barWidth - - // make this BarData object grouped - data.groupBars(fromX: 0, groupSpace: groupSpace, barSpace: barSpace) - - return data - } - - func generateScatterData() -> ScatterChartData { - let entries = stride(from: 0.0, to: Double(ITEM_COUNT), by: 0.5).map { (i) -> ChartDataEntry in - return ChartDataEntry(x: i+0.25, y: Double(arc4random_uniform(10) + 55)) - } - - let set = ScatterChartDataSet(values: entries, label: "Scatter DataSet") - set.colors = ChartColorTemplates.material - set.scatterShapeSize = 4.5 - set.isDrawValuesEnabled = false - set.valueFont = .systemFont(ofSize: 10) - - return ScatterChartData(dataSet: set) - } - - func generateCandleData() -> CandleChartData { - let entries = stride(from: 0, to: ITEM_COUNT, by: 2).map { (i) -> CandleChartDataEntry in - return CandleChartDataEntry(x: Double(i+1), shadowH: 90, shadowL: 70, open: 85, close: 75) - } - - let set = CandleChartDataSet(values: entries, label: "Candle DataSet") - set.setColor(UIColor(red: 80/255, green: 80/255, blue: 80/255, alpha: 1)) - set.decreasingColor = UIColor(red: 142/255, green: 150/255, blue: 175/255, alpha: 1) - set.shadowColor = .darkGray - set.valueFont = .systemFont(ofSize: 10) - set.isDrawValuesEnabled = false - - return CandleChartData(dataSet: set) - } - - func generateBubbleData() -> BubbleChartData { - let entries = (0.. BubbleChartDataEntry in - return BubbleChartDataEntry(x: Double(i) + 0.5, - y: Double(arc4random_uniform(10) + 105), - size: CGFloat(arc4random_uniform(50) + 105)) - } - - let set = BubbleChartDataSet(values: entries, label: "Bubble DataSet") - set.setColors(ChartColorTemplates.vordiplom) - set.valueTextColor = .white - set.valueFont = .systemFont(ofSize: 10) - set.isDrawValuesEnabled = true - - return BubbleChartData(dataSet: set) - } -} - -extension CombinedChartViewController: AxisValueFormatter { - func stringForValue(_ value: Double, axis: AxisBase) -> String { - return months[Int(value) % months.count] - } -} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/CombinedChartViewController.xib b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/CombinedChartViewController.xib deleted file mode 100644 index 6d4e1009b0..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/CombinedChartViewController.xib +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - HelveticaNeue-Light - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/CubicLineChartViewController.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/CubicLineChartViewController.swift deleted file mode 100644 index 1018141ba6..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/CubicLineChartViewController.swift +++ /dev/null @@ -1,155 +0,0 @@ -// -// CubicLineChartViewController.swift -// ChartsDemo-iOS -// -// Created by Jacob Christie on 2017-07-09. -// Copyright © 2017 jc. All rights reserved. -// - -import UIKit -import Charts - -private class CubicLineSampleFillFormatter: FillFormatter { - func getFillLinePosition(dataSet: LineChartDataSet, dataProvider: LineChartDataProvider) -> CGFloat { - return -10 - } -} - -class CubicLineChartViewController: DemoBaseViewController { - - @IBOutlet var chartView: LineChartView! - @IBOutlet var sliderX: UISlider! - @IBOutlet var sliderY: UISlider! - @IBOutlet var sliderTextX: UITextField! - @IBOutlet var sliderTextY: UITextField! - - override func viewDidLoad() { - super.viewDidLoad() - - // Do any additional setup after loading the view. - self.title = "Cubic Line Chart" - - self.options = [.toggleValues, - .toggleFilled, - .toggleCircles, - .toggleCubic, - .toggleHorizontalCubic, - .toggleStepped, - .toggleHighlight, - .animateX, - .animateY, - .animateXY, - .saveToGallery, - .togglePinchZoom, - .toggleAutoScaleMinMax, - .toggleData] - - chartView.delegate = self - - chartView.setViewPortOffsets(left: 0, top: 20, right: 0, bottom: 0) - chartView.backgroundColor = UIColor(red: 104/255, green: 241/255, blue: 175/255, alpha: 1) - - chartView.isDragEnabled = true - chartView.setScaleEnabled(true) - chartView.isPinchZoomEnabled = false - chartView.maxHighlightDistance = 300 - - chartView.xAxis.isEnabled = false - - let yAxis = chartView.leftAxis - yAxis.labelFont = UIFont(name: "HelveticaNeue-Light", size:12)! - yAxis.setLabelCount(6, force: false) - yAxis.labelTextColor = .white - yAxis.labelPosition = .insideChart - yAxis.axisLineColor = .white - - chartView.rightAxis.isEnabled = false - chartView.legend.isEnabled = false - - sliderX.value = 45 - sliderY.value = 100 - self.slidersValueChanged(nil) - - chartView.animate(xAxisDuration: 2, yAxisDuration: 2) - } - - override func updateChartData() { - if self.shouldHideData { - chartView.data = nil - return - } - - self.setDataCount(Int(sliderX.value + 1), range: UInt32(sliderY.value)) - } - - func setDataCount(_ count: Int, range: UInt32) { - let yVals1 = (0.. ChartDataEntry in - let mult = range + 1 - let val = Double(arc4random_uniform(mult) + 20) - return ChartDataEntry(x: Double(i), y: val) - } - - let set1 = LineChartDataSet(values: yVals1, label: "DataSet 1") - set1.mode = .cubicBezier - set1.isDrawCirclesEnabled = false - set1.lineWidth = 1.8 - set1.circleRadius = 4 - set1.setCircleColor(.white) - set1.highlightColor = UIColor(red: 244/255, green: 117/255, blue: 117/255, alpha: 1) - set1.fillColor = .white - set1.fillAlpha = 1 - set1.isHorizontalHighlightIndicatorEnabled = false - set1.fillFormatter = CubicLineSampleFillFormatter() - - let data = LineChartData(dataSet: set1) - data.setValueFont(UIFont(name: "HelveticaNeue-Light", size: 9)!) - data.setDrawValues(false) - - chartView.data = data - } - - override func optionTapped(_ option: Option) { - switch option { - case .toggleFilled: - for set in chartView.data!.dataSets as! [LineChartDataSet] { - set.isDrawFilledEnabled = !set.isDrawFilledEnabled - } - chartView.setNeedsDisplay() - - case .toggleCircles: - for set in chartView.data!.dataSets as! [LineChartDataSet] { - set.isDrawCirclesEnabled = !set.isDrawCirclesEnabled - } - chartView.setNeedsDisplay() - - case .toggleCubic: - for set in chartView.data!.dataSets as! [LineChartDataSet] { - set.mode = (set.mode == .cubicBezier) ? .linear : .cubicBezier - } - chartView.setNeedsDisplay() - - case .toggleStepped: - for set in chartView.data!.dataSets as! [LineChartDataSet] { - set.mode = (set.mode == .stepped) ? .linear : .stepped - } - chartView.setNeedsDisplay() - - case .toggleHorizontalCubic: - for set in chartView.data!.dataSets as! [LineChartDataSet] { - set.mode = (set.mode == .cubicBezier) ? .horizontalBezier : .cubicBezier - } - chartView.setNeedsDisplay() - - default: - super.handleOption(option, forChartView: chartView) - } - } - - // MARK: - Actions - @IBAction func slidersValueChanged(_ sender: Any?) { - sliderTextX.text = "\(Int(sliderX.value))" - sliderTextY.text = "\(Int(sliderY.value))" - - self.updateChartData() - } -} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/CubicLineChartViewController.xib b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/CubicLineChartViewController.xib deleted file mode 100644 index debfd87e93..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/CubicLineChartViewController.xib +++ /dev/null @@ -1,100 +0,0 @@ - - - - - - - - - - - - HelveticaNeue-Light - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/HalfPieChartViewController.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/HalfPieChartViewController.swift deleted file mode 100644 index e203833273..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/HalfPieChartViewController.swift +++ /dev/null @@ -1,142 +0,0 @@ -// -// HalfPieChartViewController.swift -// ChartsDemo-iOS -// -// Created by Jacob Christie on 2017-07-09. -// Copyright © 2017 jc. All rights reserved. -// - -import UIKit -import Charts - -class HalfPieChartViewController: DemoBaseViewController { - - @IBOutlet var chartView: PieChartView! - - override func viewDidLoad() { - super.viewDidLoad() - - // Do any additional setup after loading the view. - self.title = "Half Pie Bar Chart" - - self.options = [.toggleValues, - .toggleXValues, - .togglePercent, - .toggleHole, - .animateX, - .animateY, - .animateXY, - .spin, - .drawCenter, - .saveToGallery, - .toggleData] - - self.setup(pieChartView: chartView) - - chartView.delegate = self - - chartView.holeColor = .white - chartView.transparentCircleColor = Color.white.withAlphaComponent(0.43) - chartView.holeRadiusPercent = 0.58 - chartView.isRotationEnabled = false - chartView.isHighlightPerTapEnabled = true - - chartView.maxAngle = 180 // Half chart - chartView.rotationAngle = 180 // Rotate to make the half on the upper side - chartView.centerTextOffset = CGPoint(x: 0, y: -20) - - var l = chartView.legend - l.horizontalAlignment = .center - l.verticalAlignment = .top - l.orientation = .horizontal - l.drawInside = false - l.xEntrySpace = 7 - l.yEntrySpace = 0 - l.yOffset = 0 - chartView.legend = l - - // entry label styling - chartView.entryLabelColor = .white - chartView.entryLabelFont = UIFont(name:"HelveticaNeue-Light", size:12)! - - self.updateChartData() - - chartView.animate(xAxisDuration: 1.4, easingOption: .easeOutBack) - } - - override func updateChartData() { - if self.shouldHideData { - chartView.data = nil - return - } - - self.setDataCount(4, range: 100) - } - - func setDataCount(_ count: Int, range: UInt32) { - let entries = (0.. PieChartDataEntry in - // IMPORTANT: In a PieChart, no values (Entry) should have the same xIndex (even if from different DataSets), since no values can be drawn above each other. - return PieChartDataEntry(value: Double(arc4random_uniform(range) + range / 5), - label: parties[i % parties.count]) - } - - let set = PieChartDataSet(values: entries, label: "Election Results") - set.sliceSpace = 3 - set.selectionShift = 5 - set.colors = ChartColorTemplates.material - - let data = PieChartData(dataSet: set) - - let pFormatter = NumberFormatter() - pFormatter.numberStyle = .percent - pFormatter.maximumFractionDigits = 1 - pFormatter.multiplier = 1 - pFormatter.percentSymbol = " %" - data.setValueFormatter(DefaultValueFormatter(formatter: pFormatter)) - - data.setValueFont(UIFont(name: "HelveticaNeue-Light", size: 11)!) - data.setValueTextColor(.white) - - chartView.data = data - - chartView.setNeedsDisplay() - } - - override func optionTapped(_ option: Option) { - switch option { - case .toggleXValues: - chartView.isDrawEntryLabelsEnabled = !chartView.isDrawEntryLabelsEnabled - chartView.setNeedsDisplay() - - case .togglePercent: - chartView.usePercentValues = !chartView.usePercentValues - chartView.setNeedsDisplay() - - case .toggleHole: - chartView.isDrawHoleEnabled = !chartView.isDrawHoleEnabled - chartView.setNeedsDisplay() - - case .drawCenter: - chartView.isDrawCenterTextEnabled = !chartView.isDrawCenterTextEnabled - chartView.setNeedsDisplay() - - case .animateX: - chartView.animate(xAxisDuration: 1.4) - - case .animateY: - chartView.animate(yAxisDuration: 1.4) - - case .animateXY: - chartView.animate(xAxisDuration: 1.4, yAxisDuration: 1.4) - - case .spin: - chartView.spin(duration: 2, - fromAngle: chartView.rotationAngle, - toAngle: chartView.rotationAngle + 360, - easingOption: .easeInCubic) - - default: - handleOption(option, forChartView: chartView) - } - } -} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/HalfPieChartViewController.xib b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/HalfPieChartViewController.xib deleted file mode 100644 index d757d173bf..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/HalfPieChartViewController.xib +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - HelveticaNeue-Light - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/HorizontalBarChartViewController.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/HorizontalBarChartViewController.swift deleted file mode 100644 index 896b655a57..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/HorizontalBarChartViewController.swift +++ /dev/null @@ -1,124 +0,0 @@ -// -// HorizontalBarChartViewController.swift -// ChartsDemo-iOS -// -// Created by Jacob Christie on 2017-07-09. -// Copyright © 2017 jc. All rights reserved. -// - -import UIKit -import Charts - -class HorizontalBarChartViewController: DemoBaseViewController { - - @IBOutlet var chartView: HorizontalBarChartView! - @IBOutlet var sliderX: UISlider! - @IBOutlet var sliderY: UISlider! - @IBOutlet var sliderTextX: UITextField! - @IBOutlet var sliderTextY: UITextField! - - override func viewDidLoad() { - super.viewDidLoad() - - // Do any additional setup after loading the view. - self.title = "Horizontal Bar Char" - self.options = [.toggleValues, - .toggleIcons, - .toggleHighlight, - .animateX, - .animateY, - .animateXY, - .saveToGallery, - .togglePinchZoom, - .toggleAutoScaleMinMax, - .toggleData, - .toggleBarBorders] - - self.setup(barLineChartView: chartView) - - chartView.delegate = self - - chartView.isDrawBarShadowEnabled = false - chartView.isDrawValueAboveBarEnabled = true - - chartView.maxVisibleCount = 60 - - let xAxis = chartView.xAxis - xAxis.labelPosition = .bottom - xAxis.labelFont = .systemFont(ofSize: 10) - xAxis.isDrawAxisLineEnabled = true - xAxis.granularity = 10 - - let leftAxis = chartView.leftAxis - leftAxis.labelFont = .systemFont(ofSize: 10) - leftAxis.isDrawAxisLineEnabled = true - leftAxis.isDrawGridLinesEnabled = true - leftAxis.axisMinimum = 0 - - let rightAxis = chartView.rightAxis - rightAxis.isEnabled = true - rightAxis.labelFont = .systemFont(ofSize: 10) - rightAxis.isDrawAxisLineEnabled = true - rightAxis.axisMinimum = 0 - - var l = chartView.legend - l.horizontalAlignment = .left - l.verticalAlignment = .bottom - l.orientation = .horizontal - l.drawInside = false - l.form = .square - l.formSize = 8 - l.font = UIFont(name: "HelveticaNeue-Light", size: 11)! - l.xEntrySpace = 4 - chartView.legend = l - - chartView.fitBars = true - - sliderX.value = 12 - sliderY.value = 50 - slidersValueChanged(nil) - - chartView.animate(yAxisDuration: 2.5) - } - - override func updateChartData() { - if self.shouldHideData { - chartView.data = nil - return - } - - self.setDataCount(Int(sliderX.value) + 1, range: UInt32(sliderY.value)) - } - - func setDataCount(_ count: Int, range: UInt32) { - let barWidth = 9.0 - let spaceForBar = 10.0 - - let yVals = (0.. BarChartDataEntry in - let mult = range + 1 - let val = Double(arc4random_uniform(mult)) - return BarChartDataEntry(x: Double(i)*spaceForBar, y: val, icon: #imageLiteral(resourceName: "icon")) - } - - let set1 = BarChartDataSet(values: yVals, label: "DataSet") - set1.isDrawIconsEnabled = false - - let data = BarChartData(dataSet: set1) - data.setValueFont(UIFont(name:"HelveticaNeue-Light", size:10)!) - data.barWidth = barWidth - - chartView.data = data - } - - override func optionTapped(_ option: Option) { - super.handleOption(option, forChartView: chartView) - } - - // MARK: - Actions - @IBAction func slidersValueChanged(_ sender: Any?) { - sliderTextX.text = "\(Int(sliderX.value))" - sliderTextY.text = "\(Int(sliderY.value))" - - self.updateChartData() - } -} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/HorizontalBarChartViewController.xib b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/HorizontalBarChartViewController.xib deleted file mode 100644 index 19560cd484..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/HorizontalBarChartViewController.xib +++ /dev/null @@ -1,100 +0,0 @@ - - - - - - - - - - - - HelveticaNeue-Light - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChart1ViewController.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChart1ViewController.swift deleted file mode 100644 index 8681cd099d..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChart1ViewController.swift +++ /dev/null @@ -1,187 +0,0 @@ -// -// LineChart1ViewController.swift -// ChartsDemo-iOS -// -// Created by Jacob Christie on 2017-07-09. -// Copyright © 2017 jc. All rights reserved. -// - -import UIKit -import Charts - -class LineChart1ViewController: DemoBaseViewController { - - @IBOutlet var chartView: LineChartView! - @IBOutlet var sliderX: UISlider! - @IBOutlet var sliderY: UISlider! - @IBOutlet var sliderTextX: UITextField! - @IBOutlet var sliderTextY: UITextField! - - override func viewDidLoad() { - super.viewDidLoad() - - // Do any additional setup after loading the view. - self.title = "Line Chart 1" - self.options = [.toggleValues, - .toggleFilled, - .toggleCircles, - .toggleCubic, - .toggleHorizontalCubic, - .toggleIcons, - .toggleStepped, - .toggleHighlight, - .animateX, - .animateY, - .animateXY, - .saveToGallery, - .togglePinchZoom, - .toggleAutoScaleMinMax, - .toggleData] - - chartView.delegate = self - - chartView.chartDescription?.isEnabled = false - chartView.isDragEnabled = true - chartView.setScaleEnabled(true) - chartView.isPinchZoomEnabled = true - - // x-axis limit line - let llXAxis = ChartLimitLine(limit: 10, label: "Index 10") - llXAxis.lineWidth = 4 - llXAxis.lineDashLengths = [10, 10, 0] - llXAxis.labelPosition = .rightBottom - llXAxis.valueFont = .systemFont(ofSize: 10) - - chartView.xAxis.gridLineDashLengths = [10, 10] - chartView.xAxis.gridLineDashPhase = 0 - - let ll1 = ChartLimitLine(limit: 150, label: "Upper Limit") - ll1.lineWidth = 4 - ll1.lineDashLengths = [5, 5] - ll1.labelPosition = .rightTop - ll1.valueFont = .systemFont(ofSize: 10) - - let ll2 = ChartLimitLine(limit: -30, label: "Lower Limit") - ll2.lineWidth = 4 - ll2.lineDashLengths = [5,5] - ll2.labelPosition = .rightBottom - ll2.valueFont = .systemFont(ofSize: 10) - - let leftAxis = chartView.leftAxis - leftAxis.removeAllLimitLines() - leftAxis.addLimitLine(ll1) - leftAxis.addLimitLine(ll2) - leftAxis.axisMaximum = 200 - leftAxis.axisMinimum = -50 - leftAxis.gridLineDashLengths = [5, 5] - leftAxis.isDrawLimitLinesBehindDataEnabled = true - - chartView.rightAxis.isEnabled = false - - //[_chartView.viewPortHandler setMaximumScaleY: 2.f]; - //[_chartView.viewPortHandler setMaximumScaleX: 2.f]; - - let marker = BalloonMarker(color: UIColor(white: 180/255, alpha: 1), - font: .systemFont(ofSize: 12), - textColor: .white, - insets: UIEdgeInsets(top: 8, left: 8, bottom: 20, right: 8)) - marker.chartView = chartView - marker.minimumSize = CGSize(width: 80, height: 40) - chartView.marker = marker - - chartView.legend.form = .line - - sliderX.value = 45 - sliderY.value = 100 - slidersValueChanged(nil) - - chartView.animate(xAxisDuration: 2.5) - } - - override func updateChartData() { - if self.shouldHideData { - chartView.data = nil - return - } - - self.setDataCount(Int(sliderX.value), range: UInt32(sliderY.value)) - } - - func setDataCount(_ count: Int, range: UInt32) { - let values = (0.. ChartDataEntry in - let val = Double(arc4random_uniform(range) + 3) - return ChartDataEntry(x: Double(i), y: val, icon: #imageLiteral(resourceName: "icon")) - } - - let set1 = LineChartDataSet(values: values, label: "DataSet 1") - set1.isDrawIconsEnabled = false - - set1.lineDashLengths = [5, 2.5] - set1.highlightLineDashLengths = [5, 2.5] - set1.setColor(.black) - set1.setCircleColor(.black) - set1.lineWidth = 1 - set1.circleRadius = 3 - set1.isDrawCircleHoleEnabled = false - set1.valueFont = .systemFont(ofSize: 9) - set1.formLineDashLengths = [5, 2.5] - set1.formLineWidth = 1 - set1.formLineWidth = 15 - - let gradientColors = [Color(string: "#00ff0000").cgColor, - Color(string: "#ffff0000").cgColor] as CFArray - let gradient = CGGradient(colorsSpace: nil, colors: gradientColors, locations: nil)! - - set1.fillAlpha = 1 - set1.fill = .linearGradient(gradient, angle: 90) - set1.isDrawFilledEnabled = true - - let data = LineChartData(dataSet: set1) - - chartView.data = data - } - - override func optionTapped(_ option: Option) { - switch option { - case .toggleFilled: - for set in chartView.data!.dataSets as! [LineChartDataSet] { - set.isDrawFilledEnabled = !set.isDrawFilledEnabled - } - chartView.setNeedsDisplay() - - case .toggleCircles: - for set in chartView.data!.dataSets as! [LineChartDataSet] { - set.isDrawCirclesEnabled = !set.isDrawCirclesEnabled - } - chartView.setNeedsDisplay() - - case .toggleCubic: - for set in chartView.data!.dataSets as! [LineChartDataSet] { - set.mode = (set.mode == .cubicBezier) ? .linear : .cubicBezier - } - chartView.setNeedsDisplay() - - case .toggleStepped: - for set in chartView.data!.dataSets as! [LineChartDataSet] { - set.mode = (set.mode == .stepped) ? .linear : .stepped - } - chartView.setNeedsDisplay() - - case .toggleHorizontalCubic: - for set in chartView.data!.dataSets as! [LineChartDataSet] { - set.mode = (set.mode == .cubicBezier) ? .horizontalBezier : .cubicBezier - } - chartView.setNeedsDisplay() - - default: - super.handleOption(option, forChartView: chartView) - } - } - - @IBAction func slidersValueChanged(_ sender: Any?) { - sliderTextX.text = "\(Int(sliderX.value))" - sliderTextY.text = "\(Int(sliderY.value))" - - self.updateChartData() - } -} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChart1ViewController.xib b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChart1ViewController.xib deleted file mode 100644 index 274c26069c..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChart1ViewController.xib +++ /dev/null @@ -1,100 +0,0 @@ - - - - - - - - - - - - HelveticaNeue-Light - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChart2ViewController.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChart2ViewController.swift deleted file mode 100644 index 8f9206e173..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChart2ViewController.swift +++ /dev/null @@ -1,200 +0,0 @@ -// -// LineChart2ViewController.swift -// ChartsDemo-iOS -// -// Created by Jacob Christie on 2017-07-09. -// Copyright © 2017 jc. All rights reserved. -// - -import UIKit -import Charts - -class LineChart2ViewController: DemoBaseViewController { - - @IBOutlet var chartView: LineChartView! - @IBOutlet var sliderX: UISlider! - @IBOutlet var sliderY: UISlider! - @IBOutlet var sliderTextX: UITextField! - @IBOutlet var sliderTextY: UITextField! - - override func viewDidLoad() { - super.viewDidLoad() - - // Do any additional setup after loading the view. - self.title = "Line Chart 2" - self.options = [.toggleValues, - .toggleFilled, - .toggleCircles, - .toggleCubic, - .toggleHorizontalCubic, - .toggleStepped, - .toggleHighlight, - .animateX, - .animateY, - .animateXY, - .saveToGallery, - .togglePinchZoom, - .toggleAutoScaleMinMax, - .toggleData] - - chartView.delegate = self - - chartView.chartDescription?.isEnabled = false - chartView.isDragEnabled = true - chartView.setScaleEnabled(true) - chartView.isPinchZoomEnabled = true - - var l = chartView.legend - l.form = .line - l.font = UIFont(name: "HelveticaNeue-Light", size: 11)! - l.textColor = .white - l.horizontalAlignment = .left - l.verticalAlignment = .bottom - l.orientation = .horizontal - l.drawInside = false - - let xAxis = chartView.xAxis - xAxis.labelFont = .systemFont(ofSize: 11) - xAxis.labelTextColor = .white - xAxis.isDrawAxisLineEnabled = false - - let leftAxis = chartView.leftAxis - leftAxis.labelTextColor = UIColor(red: 51/255, green: 181/255, blue: 229/255, alpha: 1) - leftAxis.axisMaximum = 200 - leftAxis.axisMinimum = 0 - leftAxis.isDrawGridLinesEnabled = true - leftAxis.isGranularityEnabled = true - - let rightAxis = chartView.rightAxis - rightAxis.labelTextColor = .red - rightAxis.axisMaximum = 900 - rightAxis.axisMinimum = -200 - rightAxis.isGranularityEnabled = false - - sliderX.value = 20 - sliderY.value = 30 - slidersValueChanged(nil) - - chartView.animate(xAxisDuration: 2.5) - } - - override func updateChartData() { - if self.shouldHideData { - chartView.data = nil - return - } - - self.setDataCount(Int(sliderX.value + 1), range: UInt32(sliderY.value)) - } - - func setDataCount(_ count: Int, range: UInt32) { - let yVals1 = (0.. ChartDataEntry in - let mult = range / 2 - let val = Double(arc4random_uniform(mult) + 50) - return ChartDataEntry(x: Double(i), y: val) - } - let yVals2 = (0.. ChartDataEntry in - let val = Double(arc4random_uniform(range) + 450) - return ChartDataEntry(x: Double(i), y: val) - } - let yVals3 = (0.. ChartDataEntry in - let val = Double(arc4random_uniform(range) + 500) - return ChartDataEntry(x: Double(i), y: val) - } - - let set1 = LineChartDataSet(values: yVals1, label: "DataSet 1") - set1.axisDependency = .left - set1.setColor(UIColor(red: 51/255, green: 181/255, blue: 229/255, alpha: 1)) - set1.setCircleColor(.white) - set1.lineWidth = 2 - set1.circleRadius = 3 - set1.fillAlpha = 65/255 - set1.fillColor = UIColor(red: 51/255, green: 181/255, blue: 229/255, alpha: 1) - set1.highlightColor = UIColor(red: 244/255, green: 117/255, blue: 117/255, alpha: 1) - set1.isDrawCircleHoleEnabled = false - - let set2 = LineChartDataSet(values: yVals2, label: "DataSet 2") - set2.axisDependency = .right - set2.setColor(.red) - set2.setCircleColor(.white) - set2.lineWidth = 2 - set2.circleRadius = 3 - set2.fillAlpha = 65/255 - set2.fillColor = .red - set2.highlightColor = UIColor(red: 244/255, green: 117/255, blue: 117/255, alpha: 1) - set2.isDrawCircleHoleEnabled = false - - let set3 = LineChartDataSet(values: yVals3, label: "DataSet 3") - set3.axisDependency = .right - set3.setColor(.yellow) - set3.setCircleColor(.white) - set3.lineWidth = 2 - set3.circleRadius = 3 - set3.fillAlpha = 65/255 - set3.fillColor = UIColor.yellow.withAlphaComponent(200/255) - set3.highlightColor = UIColor(red: 244/255, green: 117/255, blue: 117/255, alpha: 1) - set3.isDrawCircleHoleEnabled = false - - let data = LineChartData(dataSets: [set1, set2, set3]) - data.setValueTextColor(.white) - data.setValueFont(.systemFont(ofSize: 9)) - - chartView.data = data - } - - override func optionTapped(_ option: Option) { - switch option { - case .toggleFilled: - for set in chartView.data!.dataSets as! [LineChartDataSet] { - set.isDrawFilledEnabled = !set.isDrawFilledEnabled - } - chartView.setNeedsDisplay() - - case .toggleCircles: - for set in chartView.data!.dataSets as! [LineChartDataSet] { - set.isDrawCirclesEnabled = !set.isDrawCirclesEnabled - } - chartView.setNeedsDisplay() - - case .toggleCubic: - for set in chartView.data!.dataSets as! [LineChartDataSet] { - set.mode = (set.mode == .cubicBezier) ? .linear : .cubicBezier - } - chartView.setNeedsDisplay() - - case .toggleStepped: - for set in chartView.data!.dataSets as! [LineChartDataSet] { - set.mode = (set.mode == .stepped) ? .linear : .stepped - } - chartView.setNeedsDisplay() - - case .toggleHorizontalCubic: - for set in chartView.data!.dataSets as! [LineChartDataSet] { - set.mode = (set.mode == .cubicBezier) ? .horizontalBezier : .cubicBezier - } - chartView.setNeedsDisplay() - - default: - super.handleOption(option, forChartView: chartView) - } - } - - @IBAction func slidersValueChanged(_ sender: Any?) { - sliderTextX.text = "\(Int(sliderX.value))" - sliderTextY.text = "\(Int(sliderY.value))" - - self.updateChartData() - } -//} - // TODO: Declarations in extensions cannot override yet. -//extension LineChart2ViewController { - override func chartValueSelected(_ chartView: ChartViewBase, entry: ChartDataEntry, highlight: Highlight) { - super.chartValueSelected(chartView, entry: entry, highlight: highlight) - - self.chartView.centerViewToAnimated(xValue: entry.x, yValue: entry.y, - axis: self.chartView.data!.getDataSetByIndex(highlight.dataSetIndex).axisDependency, - duration: 1) - //[_chartView moveViewToAnimatedWithXValue:entry.x yValue:entry.y axis:[_chartView.data getDataSetByIndex:dataSetIndex].axisDependency duration:1.0]; - //[_chartView zoomAndCenterViewAnimatedWithScaleX:1.8 scaleY:1.8 xValue:entry.x yValue:entry.y axis:[_chartView.data getDataSetByIndex:dataSetIndex].axisDependency duration:1.0]; - } -} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChart2ViewController.xib b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChart2ViewController.xib deleted file mode 100644 index 08ccd86308..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChart2ViewController.xib +++ /dev/null @@ -1,100 +0,0 @@ - - - - - - - - - - - - HelveticaNeue-Light - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChartFilledViewController.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChartFilledViewController.swift deleted file mode 100644 index 01f87f69cb..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChartFilledViewController.swift +++ /dev/null @@ -1,117 +0,0 @@ -// -// LineChartFilledViewController.swift -// ChartsDemo-iOS -// -// Created by Jacob Christie on 2017-07-09. -// Copyright © 2017 jc. All rights reserved. -// - -import UIKit -import Charts - -class LineChartFilledViewController: DemoBaseViewController { - - @IBOutlet var chartView: LineChartView! - @IBOutlet var sliderX: UISlider! - @IBOutlet var sliderY: UISlider! - @IBOutlet var sliderTextX: UITextField! - @IBOutlet var sliderTextY: UITextField! - - override func viewDidLoad() { - super.viewDidLoad() - - // Do any additional setup after loading the view. - self.title = "Filled Line Chart" - - chartView.delegate = self - - chartView.backgroundColor = .white - chartView.gridBackgroundColor = UIColor(red: 51/255, green: 181/255, blue: 229/255, alpha: 150/255) - chartView.isDrawGridBackgroundEnabled = true - - chartView.isDrawBordersEnabled = true - - chartView.chartDescription?.isEnabled = false - - chartView.isPinchZoomEnabled = false - chartView.isDragEnabled = true - chartView.setScaleEnabled(true) - - chartView.legend.isEnabled = false - - chartView.xAxis.isEnabled = false - - let leftAxis = chartView.leftAxis - leftAxis.axisMaximum = 900 - leftAxis.axisMinimum = -250 - leftAxis.isDrawAxisLineEnabled = false - - chartView.rightAxis.isEnabled = false - - sliderX.value = 100 - sliderY.value = 60 - slidersValueChanged(nil) - } - - override func updateChartData() { - if self.shouldHideData { - chartView.data = nil - return - } - - self.setDataCount(Int(sliderX.value), range: UInt32(sliderY.value)) - } - - func setDataCount(_ count: Int, range: UInt32) { - let yVals1 = (0.. ChartDataEntry in - let val = Double(arc4random_uniform(range) + 50) - return ChartDataEntry(x: Double(i), y: val) - } - let yVals2 = (0.. ChartDataEntry in - let val = Double(arc4random_uniform(range) + 450) - return ChartDataEntry(x: Double(i), y: val) - } - - let set1 = LineChartDataSet(values: yVals1, label: "DataSet 1") - set1.axisDependency = .left - set1.setColor(UIColor(red: 255/255, green: 241/255, blue: 46/255, alpha: 1)) - set1.isDrawCirclesEnabled = false - set1.lineWidth = 2 - set1.circleRadius = 3 - set1.fillAlpha = 1 - set1.isDrawFilledEnabled = true - set1.fillColor = .white - set1.highlightColor = UIColor(red: 244/255, green: 117/255, blue: 117/255, alpha: 1) - set1.isDrawCircleHoleEnabled = false - set1.fillFormatter = DefaultFillFormatter { _,_ -> CGFloat in - return CGFloat(self.chartView.leftAxis.axisMinimum) - } - - let set2 = LineChartDataSet(values: yVals2, label: "DataSet 2") - set2.axisDependency = .left - set2.setColor(UIColor(red: 255/255, green: 241/255, blue: 46/255, alpha: 1)) - set2.isDrawCirclesEnabled = false - set2.lineWidth = 2 - set2.circleRadius = 3 - set2.fillAlpha = 1 - set2.isDrawFilledEnabled = true - set2.fillColor = .white - set2.highlightColor = UIColor(red: 244/255, green: 117/255, blue: 117/255, alpha: 1) - set2.isDrawCircleHoleEnabled = false - set2.fillFormatter = DefaultFillFormatter { _,_ -> CGFloat in - return CGFloat(self.chartView.leftAxis.axisMaximum) - } - - let data = LineChartData(dataSets: [set1, set2]) - data.setDrawValues(false) - - chartView.data = data - } - - @IBAction func slidersValueChanged(_ sender: Any?) { - sliderTextX.text = "\(Int(sliderX.value))" - sliderTextY.text = "\(Int(sliderY.value))" - - self.updateChartData() - } -} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChartFilledViewController.xib b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChartFilledViewController.xib deleted file mode 100644 index 08c6253a69..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChartFilledViewController.xib +++ /dev/null @@ -1,86 +0,0 @@ - - - - - - - - - - - - HelveticaNeue-Light - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChartTimeViewController.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChartTimeViewController.swift deleted file mode 100644 index e41761ec9b..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChartTimeViewController.swift +++ /dev/null @@ -1,161 +0,0 @@ -// -// LineChartTimeViewController.swift -// ChartsDemo-iOS -// -// Created by Jacob Christie on 2017-07-09. -// Copyright © 2017 jc. All rights reserved. -// - -import UIKit -import Charts - -class LineChartTimeViewController: DemoBaseViewController { - @IBOutlet var chartView: LineChartView! - @IBOutlet var sliderX: UISlider! - @IBOutlet var sliderTextX: UITextField! - - override func viewDidLoad() { - super.viewDidLoad() - - // Do any additional setup after loading the view. - self.title = "Line Chart 2" - self.options = [.toggleValues, - .toggleFilled, - .toggleCircles, - .toggleCubic, - .toggleHorizontalCubic, - .toggleStepped, - .toggleHighlight, - .animateX, - .animateY, - .animateXY, - .saveToGallery, - .togglePinchZoom, - .toggleAutoScaleMinMax, - .toggleData] - - chartView.delegate = self - - chartView.chartDescription?.isEnabled = false - - chartView.isDragEnabled = true - chartView.setScaleEnabled(true) - chartView.isPinchZoomEnabled = false - chartView.isHighlightPerDragEnabled = true - - chartView.backgroundColor = .white - - chartView.legend.isEnabled = false - - let xAxis = chartView.xAxis - xAxis.labelPosition = .topInside - xAxis.labelFont = .systemFont(ofSize: 10, weight: .light) - xAxis.labelTextColor = UIColor(red: 255/255, green: 192/255, blue: 56/255, alpha: 1) - xAxis.isDrawAxisLineEnabled = false - xAxis.isDrawGridLinesEnabled = true - xAxis.isCenterAxisLabelsEnabled = true - xAxis.granularity = 3600 - xAxis.valueFormatter = DateValueFormatter() - - let leftAxis = chartView.leftAxis - leftAxis.labelPosition = .insideChart - leftAxis.labelFont = .systemFont(ofSize: 12, weight: .light) - leftAxis.isDrawGridLinesEnabled = true - leftAxis.isGranularityEnabled = true - leftAxis.axisMinimum = 0 - leftAxis.axisMaximum = 170 - leftAxis.yOffset = -9 - leftAxis.labelTextColor = UIColor(red: 255/255, green: 192/255, blue: 56/255, alpha: 1) - - - chartView.rightAxis.isEnabled = false - - chartView.legend.form = .line - - sliderX.value = 100 - slidersValueChanged(nil) - - chartView.animate(xAxisDuration: 2.5) - } - - override func updateChartData() { - if self.shouldHideData { - chartView.data = nil - return - } - - self.setDataCount(Int(sliderX.value), range: 30) - } - - func setDataCount(_ count: Int, range: UInt32) { - let now = Date().timeIntervalSince1970 - let hourSeconds: TimeInterval = 3600 - - let from = now - (Double(count) / 2) * hourSeconds - let to = now + (Double(count) / 2) * hourSeconds - - let values = stride(from: from, to: to, by: hourSeconds).map { (x) -> ChartDataEntry in - let y = arc4random_uniform(range) + 50 - return ChartDataEntry(x: x, y: Double(y)) - } - - let set1 = LineChartDataSet(values: values, label: "DataSet 1") - set1.axisDependency = .left - set1.setColor(UIColor(red: 51/255, green: 181/255, blue: 229/255, alpha: 1)) - set1.lineWidth = 1.5 - set1.isDrawCirclesEnabled = false - set1.isDrawValuesEnabled = false - set1.fillAlpha = 0.26 - set1.fillColor = UIColor(red: 51/255, green: 181/255, blue: 229/255, alpha: 1) - set1.highlightColor = UIColor(red: 244/255, green: 117/255, blue: 117/255, alpha: 1) - set1.isDrawCircleHoleEnabled = false - - let data = LineChartData(dataSet: set1) - data.setValueTextColor(.white) - data.setValueFont(.systemFont(ofSize: 9, weight: .light)) - - chartView.data = data - } - - override func optionTapped(_ option: Option) { - switch option { - case .toggleFilled: - for set in chartView.data!.dataSets as! [LineChartDataSet] { - set.isDrawFilledEnabled = !set.isDrawFilledEnabled - } - chartView.setNeedsDisplay() - - case .toggleCircles: - for set in chartView.data!.dataSets as! [LineChartDataSet] { - set.isDrawCirclesEnabled = !set.isDrawCirclesEnabled - } - chartView.setNeedsDisplay() - - case .toggleCubic: - for set in chartView.data!.dataSets as! [LineChartDataSet] { - set.mode = (set.mode == .cubicBezier) ? .linear : .cubicBezier - } - chartView.setNeedsDisplay() - - case .toggleStepped: - for set in chartView.data!.dataSets as! [LineChartDataSet] { - set.mode = (set.mode == .stepped) ? .linear : .stepped - } - chartView.setNeedsDisplay() - - case .toggleHorizontalCubic: - for set in chartView.data!.dataSets as! [LineChartDataSet] { - set.mode = (set.mode == .cubicBezier) ? .horizontalBezier : .cubicBezier - } - chartView.setNeedsDisplay() - - default: - super.handleOption(option, forChartView: chartView) - } - } - - @IBAction func slidersValueChanged(_ sender: Any?) { - sliderTextX.text = "\(Int(sliderX.value))" - self.updateChartData() - } -} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChartTimeViewController.xib b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChartTimeViewController.xib deleted file mode 100644 index f4daf06a19..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/LineChartTimeViewController.xib +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - - - - HelveticaNeue-Light - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/MultipleBarChartViewController.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/MultipleBarChartViewController.swift deleted file mode 100644 index 2e9b3ad992..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/MultipleBarChartViewController.swift +++ /dev/null @@ -1,154 +0,0 @@ -// -// MultipleBarChartViewController.swift -// ChartsDemo-iOS -// -// Created by Jacob Christie on 2017-07-09. -// Copyright © 2017 jc. All rights reserved. -// - -import UIKit -import Charts - -class MultipleBarChartViewController: DemoBaseViewController { - - @IBOutlet var chartView: BarChartView! - @IBOutlet var sliderX: UISlider! - @IBOutlet var sliderY: UISlider! - @IBOutlet var sliderTextX: UITextField! - @IBOutlet var sliderTextY: UITextField! - - override func viewDidLoad() { - super.viewDidLoad() - - // Do any additional setup after loading the view. - self.title = "Multiple Bar Chart" - - self.options = [.toggleValues, - .toggleHighlight, - .animateX, - .animateY, - .animateXY, - .saveToGallery, - .togglePinchZoom, - .toggleAutoScaleMinMax, - .toggleData, - .toggleBarBorders] - - chartView.delegate = self - - chartView.chartDescription?.isEnabled = false - - chartView.isPinchZoomEnabled = false - chartView.isDrawBarShadowEnabled = false - - let marker = BalloonMarker(color: UIColor(white: 180/255, alpha: 1), font: .systemFont(ofSize: 12), textColor: .white, insets: UIEdgeInsets(top: 8, left: 8, bottom: 20, right: 8)) - marker.chartView = chartView - marker.minimumSize = CGSize(width: 80, height: 40) - chartView.marker = marker - - var l = chartView.legend - l.horizontalAlignment = .right - l.verticalAlignment = .top - l.orientation = .vertical - l.drawInside = true - l.font = .systemFont(ofSize: 8, weight: .light) - l.yOffset = 10 - l.xOffset = 10 - l.yEntrySpace = 0 - chartView.legend = l - - let xAxis = chartView.xAxis - xAxis.labelFont = .systemFont(ofSize: 10, weight: .light) - xAxis.granularity = 1 - xAxis.isCenterAxisLabelsEnabled = true - xAxis.valueFormatter = IntAxisValueFormatter() - - let leftAxisFormatter = NumberFormatter() - leftAxisFormatter.maximumFractionDigits = 1 - - let leftAxis = chartView.leftAxis - leftAxis.labelFont = .systemFont(ofSize: 10, weight: .light) - leftAxis.valueFormatter = LargeValueFormatter() - leftAxis.spaceTop = 0.35 - leftAxis.axisMinimum = 0 - - chartView.rightAxis.isEnabled = false - - sliderX.value = 10 - sliderY.value = 100 - slidersValueChanged(nil) - } - - override func updateChartData() { - if self.shouldHideData { - chartView.data = nil - return - } - - self.setDataCount(Int(sliderX.value), range: UInt32(sliderY.value)) - } - - func setDataCount(_ count: Int, range: UInt32) { - let groupSpace = 0.08 - let barSpace = 0.03 - let barWidth = 0.2 - // (0.2 + 0.03) * 4 + 0.08 = 1.00 -> interval per "group" - - let randomMultiplier = range * 100000 - let groupCount = count + 1 - let startYear = 1980 - let endYear = startYear + groupCount - - let block: (Int) -> BarChartDataEntry = { (i) -> BarChartDataEntry in - return BarChartDataEntry(x: Double(i), y: Double(arc4random_uniform(randomMultiplier))) - } - let yVals1 = (startYear ..< endYear).map(block) - let yVals2 = (startYear ..< endYear).map(block) - let yVals3 = (startYear ..< endYear).map(block) - let yVals4 = (startYear ..< endYear).map(block) - - let set1 = BarChartDataSet(values: yVals1, label: "Company A") - set1.setColor(UIColor(red: 104/255, green: 241/255, blue: 175/255, alpha: 1)) - - let set2 = BarChartDataSet(values: yVals2, label: "Company B") - set2.setColor(UIColor(red: 164/255, green: 228/255, blue: 251/255, alpha: 1)) - - let set3 = BarChartDataSet(values: yVals3, label: "Company C") - set3.setColor(UIColor(red: 242/255, green: 247/255, blue: 158/255, alpha: 1)) - - let set4 = BarChartDataSet(values: yVals4, label: "Company D") - set4.setColor(UIColor(red: 255/255, green: 102/255, blue: 0/255, alpha: 1)) - - let data = BarChartData(dataSets: [set1, set2, set3, set4]) - data.setValueFont(.systemFont(ofSize: 10, weight: .light)) - data.setValueFormatter(LargeValueFormatter()) - - // specify the width each bar should have - data.barWidth = barWidth - - // restrict the x-axis range - chartView.xAxis.axisMinimum = Double(startYear) - - // groupWidthWithGroupSpace(...) is a helper that calculates the width each group needs based on the provided parameters - chartView.xAxis.axisMaximum = Double(startYear) + data.groupWidth(groupSpace: groupSpace, barSpace: barSpace) * Double(groupCount) - - data.groupBars(fromX: Double(startYear), groupSpace: groupSpace, barSpace: barSpace) - - chartView.data = data - } - - override func optionTapped(_ option: Option) { - super.handleOption(option, forChartView: chartView) - } - - // MARK: - Actions - @IBAction func slidersValueChanged(_ sender: Any?) { - let startYear = 1980 - let endYear = startYear + Int(sliderX.value) - - sliderTextX.text = "\(startYear)-\(endYear)" - sliderTextY.text = "\(Int(sliderY.value))" - - self.updateChartData() - } -} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/MultipleBarChartViewController.xib b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/MultipleBarChartViewController.xib deleted file mode 100644 index 5a67858835..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/MultipleBarChartViewController.xib +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - - - - - - - HelveticaNeue-Light - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/MultipleLinesChartViewController.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/MultipleLinesChartViewController.swift deleted file mode 100644 index 7ccb56c029..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/MultipleLinesChartViewController.swift +++ /dev/null @@ -1,138 +0,0 @@ -// -// MultipleLinesChartViewController.swift -// ChartsDemo-iOS -// -// Created by Jacob Christie on 2017-07-09. -// Copyright © 2017 jc. All rights reserved. -// - -import UIKit -import Charts - -class MultipleLinesChartViewController: DemoBaseViewController { - - @IBOutlet var chartView: LineChartView! - @IBOutlet var sliderX: UISlider! - @IBOutlet var sliderY: UISlider! - @IBOutlet var sliderTextX: UITextField! - @IBOutlet var sliderTextY: UITextField! - - override func viewDidLoad() { - super.viewDidLoad() - - // Do any additional setup after loading the view. - self.title = "Multiple Lines Chart" - self.options = [.toggleValues, - .toggleFilled, - .toggleCircles, - .toggleCubic, - .toggleStepped, - .toggleHighlight, - .animateX, - .animateY, - .animateXY, - .saveToGallery, - .togglePinchZoom, - .toggleAutoScaleMinMax, - .toggleData] - - chartView.delegate = self - - chartView.chartDescription?.isEnabled = false - - chartView.leftAxis.isEnabled = false - chartView.rightAxis.isDrawAxisLineEnabled = false - chartView.xAxis.isDrawAxisLineEnabled = false - - chartView.isDrawBordersEnabled = false - chartView.setScaleEnabled(true) - - var l = chartView.legend - l.horizontalAlignment = .right - l.verticalAlignment = .top - l.orientation = .vertical - l.drawInside = false - chartView.legend = l - - sliderX.value = 20 - sliderY.value = 100 - slidersValueChanged(nil) - } - - override func updateChartData() { - if self.shouldHideData { - chartView.data = nil - return - } - - self.setDataCount(Int(sliderX.value), range: UInt32(sliderY.value)) - } - - // TODO: Refine data creation - func setDataCount(_ count: Int, range: UInt32) { - let colors = ChartColorTemplates.vordiplom[0...2] - - let block: (Int) -> ChartDataEntry = { (i) -> ChartDataEntry in - let val = Double(arc4random_uniform(range) + 3) - return ChartDataEntry(x: Double(i), y: val) - } - let dataSets = (0..<3).map { i -> LineChartDataSet in - let yVals = (0.. - - - - - - - - - - - HelveticaNeue-Light - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/NegativeStackedBarChartViewController.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/NegativeStackedBarChartViewController.swift deleted file mode 100644 index 6edcd712b5..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/NegativeStackedBarChartViewController.swift +++ /dev/null @@ -1,134 +0,0 @@ -// -// NegativeStackedBarChartViewController.swift -// ChartsDemo-iOS -// -// Created by Jacob Christie on 2017-07-09. -// Copyright © 2017 jc. All rights reserved. -// - -import UIKit -import Charts - -class NegativeStackedBarChartViewController: DemoBaseViewController { - - @IBOutlet var chartView: HorizontalBarChartView! - - lazy var customFormatter: NumberFormatter = { - let formatter = NumberFormatter() - formatter.negativePrefix = "" - formatter.positiveSuffix = "m" - formatter.negativeSuffix = "m" - formatter.minimumSignificantDigits = 1 - formatter.minimumFractionDigits = 1 - return formatter - }() - - override func viewDidLoad() { - super.viewDidLoad() - - // Do any additional setup after loading the view. - self.title = "Stacked Bar Chart Negative" - self.options = [.toggleValues, - .toggleIcons, - .toggleHighlight, - .animateX, - .animateY, - .animateXY, - .saveToGallery, - .togglePinchZoom, - .toggleAutoScaleMinMax, - .toggleData, - .toggleBarBorders] - - - chartView.delegate = self - - chartView.chartDescription?.isEnabled = false - - chartView.isDrawBarShadowEnabled = false - chartView.isDrawValueAboveBarEnabled = true - - chartView.leftAxis.isEnabled = false - let rightAxis = chartView.rightAxis - rightAxis.axisMaximum = 25 - rightAxis.axisMinimum = -25 - rightAxis.isDrawZeroLineEnabled = true - rightAxis.labelCount = 7 - rightAxis.valueFormatter = DefaultAxisValueFormatter(formatter: customFormatter) - rightAxis.labelFont = .systemFont(ofSize: 9) - - let xAxis = chartView.xAxis - xAxis.labelPosition = .bothSided - xAxis.isDrawAxisLineEnabled = false - xAxis.axisMinimum = 0 - xAxis.axisMaximum = 110 - xAxis.isCenterAxisLabelsEnabled = true - xAxis.labelCount = 12 - xAxis.granularity = 10 - xAxis.valueFormatter = self - xAxis.labelFont = .systemFont(ofSize: 9) - - var l = chartView.legend - l.horizontalAlignment = .right - l.verticalAlignment = .bottom - l.orientation = .horizontal - l.formSize = 8 - l.formToTextSpace = 8 - l.xEntrySpace = 6 - chartView.legend = l - - self.updateChartData() - } - - override func updateChartData() { - if self.shouldHideData { - chartView.data = nil - return - } - - self.setChartData() - } - - func setChartData() { - let yVals = [BarChartDataEntry(x: 5, yValues: [-10, 10]), - BarChartDataEntry(x: 15, yValues: [-12, 13]), - BarChartDataEntry(x: 25, yValues: [-15, 15]), - BarChartDataEntry(x: 35, yValues: [-17, 17]), - BarChartDataEntry(x: 45, yValues: [-19, 120]), - BarChartDataEntry(x: 55, yValues: [-19, 19]), - BarChartDataEntry(x: 65, yValues: [-16, 16]), - BarChartDataEntry(x: 75, yValues: [-13, 14]), - BarChartDataEntry(x: 85, yValues: [-10, 11]), - BarChartDataEntry(x: 95, yValues: [-5, 6]), - BarChartDataEntry(x: 105, yValues: [-1, 2]) - ] - - let set = BarChartDataSet(values: yVals, label: "Age Distribution") - set.isDrawIconsEnabled = false - set.valueFormatter = DefaultValueFormatter(formatter: customFormatter) - set.valueFont = .systemFont(ofSize: 7) - set.axisDependency = .right - set.colors = [UIColor(red: 67/255, green: 67/255, blue: 72/255, alpha: 1), - UIColor(red: 124/255, green: 181/255, blue: 236/255, alpha: 1) - ] - set.stackLabels = ["Men", "Women"] - - let data = BarChartData(dataSet: set) - data.barWidth = 8.5 - - chartView.data = data - chartView.setNeedsDisplay() - } - - override func optionTapped(_ option: Option) { - super.handleOption(option, forChartView: chartView) - } -} - -extension NegativeStackedBarChartViewController: AxisValueFormatter { - func stringForValue(_ value: Double, axis: AxisBase) -> String { - return String(format: "%03.0f-%03.0f", value, value + 10) - } - - -} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/NegativeStackedBarChartViewController.xib b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/NegativeStackedBarChartViewController.xib deleted file mode 100644 index f30f9f8646..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/NegativeStackedBarChartViewController.xib +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - HelveticaNeue-Light - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/PieChartViewController.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/PieChartViewController.swift deleted file mode 100644 index d5c4d4d9ad..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/PieChartViewController.swift +++ /dev/null @@ -1,153 +0,0 @@ -// -// PieChartViewController.swift -// ChartsDemo-iOS -// -// Created by Jacob Christie on 2017-07-09. -// Copyright © 2017 jc. All rights reserved. -// - -import UIKit -import Charts - -class PieChartViewController: DemoBaseViewController { - - @IBOutlet var chartView: PieChartView! - @IBOutlet var sliderX: UISlider! - @IBOutlet var sliderY: UISlider! - @IBOutlet var sliderTextX: UITextField! - @IBOutlet var sliderTextY: UITextField! - - override func viewDidLoad() { - super.viewDidLoad() - - // Do any additional setup after loading the view. - self.title = "Half Pie Bar Chart" - - self.options = [.toggleValues, - .toggleXValues, - .togglePercent, - .toggleHole, - .toggleIcons, - .animateX, - .animateY, - .animateXY, - .spin, - .drawCenter, - .saveToGallery, - .toggleData] - - self.setup(pieChartView: chartView) - - chartView.delegate = self - - var l = chartView.legend - l.horizontalAlignment = .right - l.verticalAlignment = .top - l.orientation = .vertical - l.xEntrySpace = 7 - l.yEntrySpace = 0 - l.yOffset = 0 - chartView.legend = l - - // entry label styling - chartView.entryLabelColor = .white - chartView.entryLabelFont = .systemFont(ofSize: 12, weight: .light) - - sliderX.value = 4 - sliderY.value = 100 - self.slidersValueChanged(nil) - - chartView.animate(xAxisDuration: 1.4, easingOption: .easeOutBack) - } - - override func updateChartData() { - if self.shouldHideData { - chartView.data = nil - return - } - - self.setDataCount(Int(sliderX.value), range: UInt32(sliderY.value)) - } - - func setDataCount(_ count: Int, range: UInt32) { - let entries = (0.. PieChartDataEntry in - // IMPORTANT: In a PieChart, no values (Entry) should have the same xIndex (even if from different DataSets), since no values can be drawn above each other. - return PieChartDataEntry(value: Double(arc4random_uniform(range) + range / 5), - label: parties[i % parties.count], - icon: #imageLiteral(resourceName: "icon")) - } - - let set = PieChartDataSet(values: entries, label: "Election Results") - set.isDrawIconsEnabled = false - set.sliceSpace = 2 - - - set.colors = ChartColorTemplates.vordiplom - + ChartColorTemplates.joyful - + ChartColorTemplates.colorful - + ChartColorTemplates.liberty - + ChartColorTemplates.pastel - + [UIColor(red: 51/255, green: 181/255, blue: 229/255, alpha: 1)] - - let data = PieChartData(dataSet: set) - - let pFormatter = NumberFormatter() - pFormatter.numberStyle = .percent - pFormatter.maximumFractionDigits = 1 - pFormatter.multiplier = 1 - pFormatter.percentSymbol = " %" - data.setValueFormatter(DefaultValueFormatter(formatter: pFormatter)) - - data.setValueFont(.systemFont(ofSize: 11, weight: .light)) - data.setValueTextColor(.white) - - chartView.data = data - chartView.highlightValues(nil) - } - - override func optionTapped(_ option: Option) { - switch option { - case .toggleXValues: - chartView.isDrawEntryLabelsEnabled = !chartView.isDrawEntryLabelsEnabled - chartView.setNeedsDisplay() - - case .togglePercent: - chartView.usePercentValues = !chartView.usePercentValues - chartView.setNeedsDisplay() - - case .toggleHole: - chartView.isDrawHoleEnabled = !chartView.isDrawHoleEnabled - chartView.setNeedsDisplay() - - case .drawCenter: - chartView.isDrawCenterTextEnabled = !chartView.isDrawCenterTextEnabled - chartView.setNeedsDisplay() - - case .animateX: - chartView.animate(xAxisDuration: 1.4) - - case .animateY: - chartView.animate(yAxisDuration: 1.4) - - case .animateXY: - chartView.animate(xAxisDuration: 1.4, yAxisDuration: 1.4) - - case .spin: - chartView.spin(duration: 2, - fromAngle: chartView.rotationAngle, - toAngle: chartView.rotationAngle + 360, - easingOption: .easeInCubic) - - default: - handleOption(option, forChartView: chartView) - } - } - - // MARK: - Actions - @IBAction func slidersValueChanged(_ sender: Any?) { - sliderTextX.text = "\(Int(sliderX.value))" - sliderTextY.text = "\(Int(sliderY.value))" - - self.updateChartData() - } -} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/PieChartViewController.xib b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/PieChartViewController.xib deleted file mode 100644 index 1fc7060ae3..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/PieChartViewController.xib +++ /dev/null @@ -1,100 +0,0 @@ - - - - - - - - - - - - HelveticaNeue-Light - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/PiePolylineChartViewController.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/PiePolylineChartViewController.swift deleted file mode 100644 index 8e9ff773de..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/PiePolylineChartViewController.swift +++ /dev/null @@ -1,145 +0,0 @@ -// -// PiePolylineChartViewController.swift -// ChartsDemo-iOS -// -// Created by Jacob Christie on 2017-07-09. -// Copyright © 2017 jc. All rights reserved. -// - -import UIKit -import Charts - -class PiePolylineChartViewController: DemoBaseViewController { - - @IBOutlet var chartView: PieChartView! - @IBOutlet var sliderX: UISlider! - @IBOutlet var sliderY: UISlider! - @IBOutlet var sliderTextX: UITextField! - @IBOutlet var sliderTextY: UITextField! - - override func viewDidLoad() { - super.viewDidLoad() - - // Do any additional setup after loading the view. - self.title = "Pie Bar Chart" - - self.options = [.toggleValues, - .toggleXValues, - .togglePercent, - .toggleHole, - .animateX, - .animateY, - .animateXY, - .spin, - .drawCenter, - .saveToGallery, - .toggleData] - - self.setup(pieChartView: chartView) - - chartView.delegate = self - - chartView.legend.isEnabled = false - chartView.setExtraOffsets(left: 20, top: 0, right: 20, bottom: 0) - - sliderX.value = 40 - sliderY.value = 100 - self.slidersValueChanged(nil) - - chartView.animate(xAxisDuration: 1.4, easingOption: .easeOutBack) - } - - override func updateChartData() { - if self.shouldHideData { - chartView.data = nil - return - } - - self.setDataCount(Int(sliderX.value), range: UInt32(sliderY.value)) - } - - func setDataCount(_ count: Int, range: UInt32) { - let entries = (0.. PieChartDataEntry in - // IMPORTANT: In a PieChart, no values (Entry) should have the same xIndex (even if from different DataSets), since no values can be drawn above each other. - return PieChartDataEntry(value: Double(arc4random_uniform(range) + range / 5), - label: parties[i % parties.count]) - } - - let set = PieChartDataSet(values: entries, label: "Election Results") - set.sliceSpace = 2 - - - set.colors = ChartColorTemplates.vordiplom - + ChartColorTemplates.joyful - + ChartColorTemplates.colorful - + ChartColorTemplates.liberty - + ChartColorTemplates.pastel - + [UIColor(red: 51/255, green: 181/255, blue: 229/255, alpha: 1)] - - set.valueLinePart1OffsetPercentage = 0.8 - set.valueLinePart1Length = 0.2 - set.valueLinePart2Length = 0.4 - //set.xValuePosition = .outsideSlice - set.yValuePosition = .outsideSlice - - let data = PieChartData(dataSet: set) - - let pFormatter = NumberFormatter() - pFormatter.numberStyle = .percent - pFormatter.maximumFractionDigits = 1 - pFormatter.multiplier = 1 - pFormatter.percentSymbol = " %" - data.setValueFormatter(DefaultValueFormatter(formatter: pFormatter)) - data.setValueFont(.systemFont(ofSize: 11, weight: .light)) - data.setValueTextColor(.black) - - chartView.data = data - chartView.highlightValues(nil) - } - - override func optionTapped(_ option: Option) { - switch option { - case .toggleXValues: - chartView.isDrawEntryLabelsEnabled = !chartView.isDrawEntryLabelsEnabled - chartView.setNeedsDisplay() - - case .togglePercent: - chartView.usePercentValues = !chartView.usePercentValues - chartView.setNeedsDisplay() - - case .toggleHole: - chartView.isDrawHoleEnabled = !chartView.isDrawHoleEnabled - chartView.setNeedsDisplay() - - case .drawCenter: - chartView.isDrawCenterTextEnabled = !chartView.isDrawCenterTextEnabled - chartView.setNeedsDisplay() - - case .animateX: - chartView.animate(xAxisDuration: 1.4) - - case .animateY: - chartView.animate(yAxisDuration: 1.4) - - case .animateXY: - chartView.animate(xAxisDuration: 1.4, yAxisDuration: 1.4) - - case .spin: - chartView.spin(duration: 2, - fromAngle: chartView.rotationAngle, - toAngle: chartView.rotationAngle + 360, - easingOption: .easeInCubic) - - default: - handleOption(option, forChartView: chartView) - } - } - - // MARK: - Actions - @IBAction func slidersValueChanged(_ sender: Any?) { - sliderTextX.text = "\(Int(sliderX.value))" - sliderTextY.text = "\(Int(sliderY.value))" - - self.updateChartData() - } -} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/PiePolylineChartViewController.xib b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/PiePolylineChartViewController.xib deleted file mode 100644 index d355365551..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/PiePolylineChartViewController.xib +++ /dev/null @@ -1,114 +0,0 @@ - - - - - - - - - - - - HelveticaNeue-Light - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/PositiveNegativeBarChartViewController.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/PositiveNegativeBarChartViewController.swift deleted file mode 100644 index 75aacbd6c5..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/PositiveNegativeBarChartViewController.swift +++ /dev/null @@ -1,120 +0,0 @@ -// -// PositiveNegativeBarChartViewController.swift -// ChartsDemo-iOS -// -// Created by Jacob Christie on 2017-07-09. -// Copyright © 2017 jc. All rights reserved. -// - -import UIKit -import Charts - -class PositiveNegativeBarChartViewController: DemoBaseViewController { - - @IBOutlet var chartView: BarChartView! - - let dataLabels = ["12-19", - "12-30", - "12-31", - "01-01", - "01-02"] - - override func viewDidLoad() { - super.viewDidLoad() - - // Do any additional setup after loading the view. - self.title = "Bar Chart" - self.options = [.toggleValues, - .toggleHighlight, - .animateX, - .animateY, - .animateXY, - .saveToGallery, - .togglePinchZoom, - .toggleAutoScaleMinMax, - .toggleData, - .toggleBarBorders] - - self.setup(barLineChartView: chartView) - - chartView.delegate = self - - chartView.setExtraOffsets(left: 70, top: -30, right: 70, bottom: 10) - - chartView.isDrawBarShadowEnabled = false - chartView.isDrawValueAboveBarEnabled = true - - chartView.chartDescription?.isEnabled = false - - chartView.rightAxis.isEnabled = false - - let xAxis = chartView.xAxis - xAxis.labelPosition = .bottom - xAxis.labelFont = .systemFont(ofSize: 13) - xAxis.isDrawAxisLineEnabled = false - xAxis.labelTextColor = .lightGray - xAxis.labelCount = 5 - xAxis.isCenterAxisLabelsEnabled = true - xAxis.granularity = 1 - xAxis.valueFormatter = self - - let leftAxis = chartView.leftAxis - leftAxis.isDrawLabelsEnabled = false - leftAxis.spaceTop = 0.25 - leftAxis.spaceBottom = 0.25 - leftAxis.isDrawAxisLineEnabled = false - leftAxis.isDrawZeroLineEnabled = true - leftAxis.zeroLineColor = .gray - leftAxis.zeroLineWidth = 0.7 - - self.updateChartData() - } - - override func updateChartData() { - if self.shouldHideData { - chartView.data = nil - return - } - - self.setChartData() - } - - func setChartData() { - let yVals = [BarChartDataEntry(x: 0, y: -224.1), - BarChartDataEntry(x: 1, y: 238.5), - BarChartDataEntry(x: 2, y: 1280.1), - BarChartDataEntry(x: 3, y: -442.3), - BarChartDataEntry(x: 4, y: -2280.1) - ] - - let red = UIColor(red: 211/255, green: 74/255, blue: 88/255, alpha: 1) - let green = UIColor(red: 110/255, green: 190/255, blue: 102/255, alpha: 1) - let colors = yVals.map { (entry) -> Color in - return entry.y > 0 ? red : green - } - - let set = BarChartDataSet(values: yVals, label: "Values") - set.colors = colors - set.valueColors = colors - - let data = BarChartData(dataSet: set) - data.setValueFont(.systemFont(ofSize: 13)) - - let formatter = NumberFormatter() - formatter.maximumFractionDigits = 1 - data.setValueFormatter(DefaultValueFormatter(formatter: formatter)) - data.barWidth = 0.8 - - chartView.data = data - } - - override func optionTapped(_ option: Option) { - super.handleOption(option, forChartView: chartView) - } -} - -extension PositiveNegativeBarChartViewController: AxisValueFormatter { - func stringForValue(_ value: Double, axis: AxisBase) -> String { - return dataLabels[min(max(Int(value), 0), dataLabels.count - 1)] - } -} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/PositiveNegativeBarChartViewController.xib b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/PositiveNegativeBarChartViewController.xib deleted file mode 100644 index 9b13e52d8d..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/PositiveNegativeBarChartViewController.xib +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - HelveticaNeue-Light - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/RadarChartViewController.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/RadarChartViewController.swift deleted file mode 100644 index f04db3cfb5..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/RadarChartViewController.swift +++ /dev/null @@ -1,203 +0,0 @@ -// -// RadarChartViewController.swift -// ChartsDemo-iOS -// -// Created by Jacob Christie on 2017-07-09. -// Copyright © 2017 jc. All rights reserved. -// - -import UIKit -import Charts - -class RadarChartViewController: DemoBaseViewController { - - @IBOutlet var chartView: RadarChartView! - - let activities = ["Burger", "Steak", "Salad", "Pasta", "Pizza"] - var originalBarBgColor: UIColor! - var originalBarTintColor: UIColor! - var originalBarStyle: UIBarStyle! - - override func viewDidLoad() { - super.viewDidLoad() - - // Do any additional setup after loading the view. - self.title = "Radar Bar Chart" - self.options = [.toggleValues, - .toggleHighlight, - .toggleHighlightCircle, - .toggleXLabels, - .toggleYLabels, - .toggleRotate, - .toggleFilled, - .animateX, - .animateY, - .animateXY, - .spin, - .saveToGallery, - .toggleData] - - chartView.delegate = self - - chartView.chartDescription?.isEnabled = false - chartView.webLineWidth = 1 - chartView.innerWebLineWidth = 1 - chartView.webColor = .lightGray - chartView.innerWebColor = .lightGray - chartView.webAlpha = 1 - - let marker = RadarMarkerView.viewFromXib()! - marker.chartView = chartView - chartView.marker = marker - - let xAxis = chartView.xAxis - xAxis.labelFont = .systemFont(ofSize: 9, weight: .light) - xAxis.xOffset = 0 - xAxis.yOffset = 0 - xAxis.valueFormatter = self - xAxis.labelTextColor = .white - - let yAxis = chartView.yAxis - yAxis.labelFont = .systemFont(ofSize: 9, weight: .light) - yAxis.labelCount = 5 - yAxis.axisMinimum = 0 - yAxis.axisMaximum = 80 - yAxis.isDrawLabelsEnabled = false - - var l = chartView.legend - l.horizontalAlignment = .center - l.verticalAlignment = .top - l.orientation = .horizontal - l.drawInside = false - l.font = .systemFont(ofSize: 10, weight: .light) - l.xEntrySpace = 7 - l.yEntrySpace = 5 - l.textColor = .white - chartView.legend = l - - self.updateChartData() - - chartView.animate(xAxisDuration: 1.4, yAxisDuration: 1.4, easingOption: .easeOutBack) - } - - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - - UIView.animate(withDuration: 0.15) { - let navBar = self.navigationController!.navigationBar - self.originalBarBgColor = navBar.barTintColor - self.originalBarTintColor = navBar.tintColor - self.originalBarStyle = navBar.barStyle - - navBar.barTintColor = self.view.backgroundColor - navBar.tintColor = .white - navBar.barStyle = .black - } - } - - override func viewWillDisappear(_ animated: Bool) { - super.viewWillDisappear(animated) - - UIView.animate(withDuration: 0.15) { - let navBar = self.navigationController!.navigationBar - navBar.barTintColor = self.originalBarBgColor - navBar.tintColor = self.originalBarTintColor - navBar.barStyle = self.originalBarStyle - } - } - - override func updateChartData() { - if self.shouldHideData { - chartView.data = nil - return - } - - self.setChartData() - } - - func setChartData() { - let mult: UInt32 = 80 - let min: UInt32 = 20 - let cnt = 5 - - let block: (Int) -> RadarChartDataEntry = { _ in return RadarChartDataEntry(value: Double(arc4random_uniform(mult) + min))} - let entries1 = (0.. String { - return activities[Int(value) % activities.count] - } -} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/RadarChartViewController.xib b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/RadarChartViewController.xib deleted file mode 100644 index a3dfdabb90..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/RadarChartViewController.xib +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - - - HelveticaNeue-Light - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/ScatterChartViewController.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/ScatterChartViewController.swift deleted file mode 100644 index 54e9b52774..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/ScatterChartViewController.swift +++ /dev/null @@ -1,124 +0,0 @@ -// -// ScatterChartViewController.swift -// ChartsDemo-iOS -// -// Created by Jacob Christie on 2017-07-09. -// Copyright © 2017 jc. All rights reserved. -// - -import UIKit -import Charts - -class ScatterChartViewController: DemoBaseViewController { - - @IBOutlet var chartView: ScatterChartView! - @IBOutlet var sliderX: UISlider! - @IBOutlet var sliderY: UISlider! - @IBOutlet var sliderTextX: UITextField! - @IBOutlet var sliderTextY: UITextField! - - override func viewDidLoad() { - super.viewDidLoad() - - // Do any additional setup after loading the view. - self.title = "Scatter Bar Chart" - self.options = [.toggleValues, - .toggleHighlight, - .animateX, - .animateY, - .animateXY, - .saveToGallery, - .togglePinchZoom, - .toggleAutoScaleMinMax, - .toggleData] - - chartView.delegate = self - - chartView.chartDescription?.isEnabled = false - - chartView.isDragEnabled = true - chartView.setScaleEnabled(true) - chartView.maxVisibleCount = 200 - chartView.isPinchZoomEnabled = true - - var l = chartView.legend - l.horizontalAlignment = .right - l.verticalAlignment = .top - l.orientation = .vertical - l.drawInside = false - l.font = .systemFont(ofSize: 10, weight: .light) - l.xOffset = 5 - - let leftAxis = chartView.leftAxis - leftAxis.labelFont = .systemFont(ofSize: 10, weight: .light) - leftAxis.axisMinimum = 0 - - chartView.rightAxis.isEnabled = false - - - let xAxis = chartView.xAxis - xAxis.labelFont = .systemFont(ofSize: 10, weight: .light) - - sliderX.value = 45 - sliderY.value = 100 - slidersValueChanged(nil) - } - - override func updateChartData() { - if self.shouldHideData { - chartView.data = nil - return - } - - self.setDataCount(Int(sliderX.value + 1), range: UInt32(sliderY.value)) - } - - func setDataCount(_ count: Int, range: UInt32) { - let values1 = (0.. ChartDataEntry in - let val = Double(arc4random_uniform(range) + 3) - return ChartDataEntry(x: Double(i), y: val) - } - let values2 = (0.. ChartDataEntry in - let val = Double(arc4random_uniform(range) + 3) - return ChartDataEntry(x: Double(i) + 0.33, y: val) - } - let values3 = (0.. ChartDataEntry in - let val = Double(arc4random_uniform(range) + 3) - return ChartDataEntry(x: Double(i) + 0.66, y: val) - } - - - let set1 = ScatterChartDataSet(values: values1, label: "DS 1") - set1.setScatterShape(.square) - set1.setColor(ChartColorTemplates.colorful[0]) - set1.scatterShapeSize = 8 - - let set2 = ScatterChartDataSet(values: values2, label: "DS 2") - set2.setScatterShape(.circle) - set2.scatterShapeHoleColor = ChartColorTemplates.colorful[3] - set2.scatterShapeHoleRadius = 3.5 - set2.setColor(ChartColorTemplates.colorful[1]) - set2.scatterShapeSize = 8 - - let set3 = ScatterChartDataSet(values: values3, label: "DS 3") - set3.setScatterShape(.cross) - set3.setColor(ChartColorTemplates.colorful[2]) - set3.scatterShapeSize = 8 - - let data = ScatterChartData(dataSets: [set1, set2, set3]) - data.setValueFont(.systemFont(ofSize: 7, weight: .light)) - - chartView.data = data - } - - override func optionTapped(_ option: Option) { - super.handleOption(option, forChartView: chartView) - } - - @IBAction func slidersValueChanged(_ sender: Any?) { - sliderTextX.text = "\(Int(sliderX.value))" - sliderTextY.text = "\(Int(sliderY.value))" - - self.updateChartData() - } -} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/ScatterChartViewController.xib b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/ScatterChartViewController.xib deleted file mode 100644 index 289fe5fe0d..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/ScatterChartViewController.xib +++ /dev/null @@ -1,100 +0,0 @@ - - - - - - - - - - - - HelveticaNeue-Light - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/SinusBarChartViewController.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/SinusBarChartViewController.swift deleted file mode 100644 index 32bbc79bb4..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/SinusBarChartViewController.swift +++ /dev/null @@ -1,108 +0,0 @@ -// -// SinusBarChartViewController.swift -// ChartsDemo-iOS -// -// Created by Jacob Christie on 2017-07-09. -// Copyright © 2017 jc. All rights reserved. -// - -import UIKit -import Charts - -class SinusBarChartViewController: DemoBaseViewController { - - @IBOutlet var chartView: BarChartView! - @IBOutlet var sliderX: UISlider! - @IBOutlet var sliderTextX: UITextField! - - override func viewDidLoad() { - super.viewDidLoad() - - // Do any additional setup after loading the view. - self.title = "Line Chart 2" - self.options = [.toggleValues, - .toggleHighlight, - .animateX, - .animateY, - .animateXY, - .saveToGallery, - .togglePinchZoom, - .toggleAutoScaleMinMax, - .toggleData] - - chartView.delegate = self - - chartView.chartDescription?.isEnabled = false - - chartView.isDrawBarShadowEnabled = false - chartView.isDrawValueAboveBarEnabled = false - chartView.maxVisibleCount = 60 - - let xAxis = chartView.xAxis - xAxis.labelPosition = .bottom - xAxis.isEnabled = false - - let leftAxis = chartView.leftAxis - leftAxis.labelCount = 6 - leftAxis.axisMinimum = -2.5 - leftAxis.axisMaximum = 2.5 - leftAxis.isGranularityEnabled = true - leftAxis.granularity = 0.1 - - let rightAxis = chartView.rightAxis - rightAxis.labelCount = 6 - rightAxis.axisMinimum = -2.5 - rightAxis.axisMaximum = 2.5 - rightAxis.granularity = 0.1 - - var l = chartView.legend - l.horizontalAlignment = .left - l.verticalAlignment = .bottom - l.orientation = .horizontal - l.drawInside = false - l.form = .square - l.formSize = 9 - l.font = .systemFont(ofSize: 11) - l.xEntrySpace = 4 - chartView.legend = l - - sliderX.value = 150 - slidersValueChanged(nil) - - chartView.animate(xAxisDuration: 2, yAxisDuration: 2) - } - - override func updateChartData() { - if self.shouldHideData { - chartView.data = nil - return - } - - self.setDataCount(Int(sliderX.value)) - } - - func setDataCount(_ count: Int) { - let entries = (0.. - - - - - - - - - - - HelveticaNeue-Light - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/StackedBarChartViewController.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/StackedBarChartViewController.swift deleted file mode 100644 index 6dd0322805..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/StackedBarChartViewController.swift +++ /dev/null @@ -1,125 +0,0 @@ -// -// StackedBarChartViewController.swift -// ChartsDemo-iOS -// -// Created by Jacob Christie on 2017-07-09. -// Copyright © 2017 jc. All rights reserved. -// - -import UIKit -import Charts - -class StackedBarChartViewController: DemoBaseViewController { - - @IBOutlet var chartView: BarChartView! - @IBOutlet var sliderX: UISlider! - @IBOutlet var sliderY: UISlider! - @IBOutlet var sliderTextX: UITextField! - @IBOutlet var sliderTextY: UITextField! - - lazy var formatter: NumberFormatter = { - let formatter = NumberFormatter() - formatter.maximumFractionDigits = 1 - formatter.negativeSuffix = " $" - formatter.positiveSuffix = " $" - - return formatter - }() - - override func viewDidLoad() { - super.viewDidLoad() - - // Do any additional setup after loading the view. - self.title = "Stacked Bar Chart" - self.options = [.toggleValues, - .toggleIcons, - .toggleHighlight, - .animateX, - .animateY, - .animateXY, - .saveToGallery, - .togglePinchZoom, - .toggleAutoScaleMinMax, - .toggleData, - .toggleBarBorders] - - - chartView.delegate = self - - chartView.chartDescription?.isEnabled = false - - chartView.maxVisibleCount = 40 - chartView.isDrawBarShadowEnabled = false - chartView.isDrawValueAboveBarEnabled = false - chartView.isHighlightFullBarEnabled = false - - let leftAxis = chartView.leftAxis - leftAxis.valueFormatter = DefaultAxisValueFormatter(formatter: formatter) - leftAxis.axisMinimum = 0 - - chartView.rightAxis.isEnabled = false - - let xAxis = chartView.xAxis - xAxis.labelPosition = .top - - var l = chartView.legend - l.horizontalAlignment = .right - l.verticalAlignment = .bottom - l.orientation = .horizontal - l.drawInside = false - l.form = .square - l.formToTextSpace = 4 - l.xEntrySpace = 6 - chartView.legend = l - - sliderX.value = 12 - sliderY.value = 100 - slidersValueChanged(nil) - - self.updateChartData() - } - - override func updateChartData() { - if self.shouldHideData { - chartView.data = nil - return - } - - self.setChartData(count: Int(sliderX.value + 1), range: UInt32(sliderY.value)) - } - - func setChartData(count: Int, range: UInt32) { - let yVals = (0.. BarChartDataEntry in - let mult = range + 1 - let val1 = Double(arc4random_uniform(mult) + mult / 3) - let val2 = Double(arc4random_uniform(mult) + mult / 3) - let val3 = Double(arc4random_uniform(mult) + mult / 3) - - return BarChartDataEntry(x: Double(i), yValues: [val1, val2, val3], icon: #imageLiteral(resourceName: "icon")) - } - - let set = BarChartDataSet(values: yVals, label: "Statistics Vienna 2014") - set.isDrawIconsEnabled = false - set.colors = [ChartColorTemplates.material[0], ChartColorTemplates.material[1], ChartColorTemplates.material[2]] - set.stackLabels = ["Births", "Divorces", "Marriages"] - - let data = BarChartData(dataSet: set) - data.setValueFont(.systemFont(ofSize: 7, weight: .light)) - data.setValueFormatter(DefaultValueFormatter(formatter: formatter)) - data.setValueTextColor(.white) - - chartView.fitBars = true - chartView.data = data - } - - override func optionTapped(_ option: Option) { - super.handleOption(option, forChartView: chartView) - } - - @IBAction func slidersValueChanged(_ sender: Any?) { - sliderTextX.text = "\(Int(sliderX.value))" - sliderTextY.text = "\(Int(sliderY.value))" - - updateChartData() - } -} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/StackedBarChartViewController.xib b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/StackedBarChartViewController.xib deleted file mode 100644 index dca9b05421..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Demos/StackedBarChartViewController.xib +++ /dev/null @@ -1,100 +0,0 @@ - - - - - - - - - - - - HelveticaNeue-Light - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Formatters/DateValueFormatter.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Formatters/DateValueFormatter.swift deleted file mode 100644 index 32367910ed..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Formatters/DateValueFormatter.swift +++ /dev/null @@ -1,22 +0,0 @@ -// -// DateValueFormatter.swift -// ChartsDemo-iOS -// -// Created by Jacob Christie on 2017-07-09. -// Copyright © 2017 jc. All rights reserved. -// - -import Foundation -import Charts - -public class DateValueFormatter: AxisValueFormatter { - private let dateFormatter = DateFormatter() - - init() { - dateFormatter.dateFormat = "dd MMM HH:mm" - } - - public func stringForValue(_ value: Double, axis: AxisBase) -> String { - return dateFormatter.string(from: Date(timeIntervalSince1970: value)) - } -} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Formatters/DayAxisValueFormatter.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Formatters/DayAxisValueFormatter.swift deleted file mode 100644 index df9e781ab7..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Formatters/DayAxisValueFormatter.swift +++ /dev/null @@ -1,109 +0,0 @@ -// -// DayAxisValueFormatter.swift -// ChartsDemo-iOS -// -// Created by Jacob Christie on 2017-07-09. -// Copyright © 2017 jc. All rights reserved. -// - -import Foundation -import Charts - -public class DayAxisValueFormatter: AxisValueFormatter { - weak var chart: BarLineChartViewBase? - let months = ["Jan", "Feb", "Mar", - "Apr", "May", "Jun", - "Jul", "Aug", "Sep", - "Oct", "Nov", "Dec"] - - init(chart: BarLineChartViewBase) { - self.chart = chart - } - - public func stringForValue(_ value: Double, axis: AxisBase) -> String { - let days = Int(value) - let year = determineYear(forDays: days) - let month = determineMonth(forDayOfYear: days) - - let monthName = months[month % months.count] - let yearName = "\(year)" - - if let chart = chart, - chart.visibleXRange > 30 * 6 { - return monthName + yearName - } else { - let dayOfMonth = determineDayOfMonth(forDays: days, month: month + 12 * (year - 2016)) - var appendix: String - - switch dayOfMonth { - case 1, 21, 31: appendix = "st" - case 2, 22: appendix = "nd" - case 3, 23: appendix = "rd" - default: appendix = "th" - } - - return dayOfMonth == 0 ? "" : String(format: "%d\(appendix) \(monthName)", dayOfMonth) - } - } - - private func days(forMonth month: Int, year: Int) -> Int { - // month is 0-based - switch month { - case 1: - var is29Feb = false - if year < 1582 { - is29Feb = (year < 1 ? year + 1 : year) % 4 == 0 - } else if year > 1582 { - is29Feb = year % 4 == 0 && (year % 100 != 0 || year % 400 == 0) - } - - return is29Feb ? 29 : 28 - - case 3, 5, 8, 10: - return 30 - - default: - return 31 - } - } - - private func determineMonth(forDayOfYear dayOfYear: Int) -> Int { - var month = -1 - var days = 0 - - while days < dayOfYear { - month += 1 - if month >= 12 { - month = 0 - } - - let year = determineYear(forDays: days) - days += self.days(forMonth: month, year: year) - } - - return max(month, 0) - } - - private func determineDayOfMonth(forDays days: Int, month: Int) -> Int { - var count = 0 - var daysForMonth = 0 - - while count < month { - let year = determineYear(forDays: days) - daysForMonth += self.days(forMonth: count % 12, year: year) - count += 1 - } - - return days - daysForMonth - } - - private func determineYear(forDays days: Int) -> Int { - switch days { - case ...366: return 2016 - case 367...730: return 2017 - case 731...1094: return 2018 - case 1095...1458: return 2019 - default: return 2020 - } - } -} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Formatters/IntAxisValueFormatter.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Formatters/IntAxisValueFormatter.swift deleted file mode 100644 index 3599910d1b..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Formatters/IntAxisValueFormatter.swift +++ /dev/null @@ -1,16 +0,0 @@ -// -// IntAxisValueFormatter.swift -// ChartsDemo-iOS -// -// Created by Jacob Christie on 2017-07-09. -// Copyright © 2017 jc. All rights reserved. -// - -import Foundation -import Charts - -public class IntAxisValueFormatter: AxisValueFormatter { - public func stringForValue(_ value: Double, axis: AxisBase) -> String { - return "\(Int(value))" - } -} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Formatters/LargeValueFormatter.swift b/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Formatters/LargeValueFormatter.swift deleted file mode 100644 index 4cbe42f431..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Classes/Formatters/LargeValueFormatter.swift +++ /dev/null @@ -1,56 +0,0 @@ -// -// LargeValueFormatter.swift -// ChartsDemo -// Copyright © 2016 dcg. All rights reserved. -// - -import Foundation -import Charts - -private let MAX_LENGTH = 5 - -public class LargeValueFormatter: ValueFormatter, AxisValueFormatter { - - /// Suffix to be appended after the values. - /// - /// **default**: suffix: ["", "k", "m", "b", "t"] - public var suffix = ["", "k", "m", "b", "t"] - - /// An appendix text to be added at the end of the formatted value. - public var appendix: String? - - public init(appendix: String? = nil) { - self.appendix = appendix - } - - fileprivate func format(value: Double) -> String { - var sig = value - var length = 0 - let maxLength = suffix.count - 1 - - while sig >= 1000.0 && length < maxLength { - sig /= 1000.0 - length += 1 - } - - var r = String(format: "%2.f", sig) + suffix[length] - - if let appendix = appendix { - r += appendix - } - - return r - } - - public func stringForValue(_ value: Double, axis: AxisBase) -> String { - return format(value: value) - } - - public func stringForValue( - _ value: Double, - entry: ChartDataEntry, - dataSetIndex: Int, - viewPortHandler: ViewPortHandler?) -> String { - return format(value: value) - } -} diff --git a/ChartsDemo-iOS/ChartsDemo-iOS/Info.plist b/ChartsDemo-iOS/ChartsDemo-iOS/Info.plist deleted file mode 100644 index 4222ac2dd3..0000000000 --- a/ChartsDemo-iOS/ChartsDemo-iOS/Info.plist +++ /dev/null @@ -1,43 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleVersion - 1 - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIRequiredDeviceCapabilities - - armv7 - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - - From b4f84b6d62053a1f546f7a769f6b2e9ca0fd9c56 Mon Sep 17 00:00:00 2001 From: Jacob Christie Date: Mon, 13 Nov 2017 21:02:19 -0800 Subject: [PATCH 6/6] Pulled latest master --- .../Images.xcassets/AppIcon.appiconset/Contents.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ChartsDemo/Resources/Images.xcassets/AppIcon.appiconset/Contents.json b/ChartsDemo/Resources/Images.xcassets/AppIcon.appiconset/Contents.json index 32d8413dd0..7c780dbcb5 100644 --- a/ChartsDemo/Resources/Images.xcassets/AppIcon.appiconset/Contents.json +++ b/ChartsDemo/Resources/Images.xcassets/AppIcon.appiconset/Contents.json @@ -47,8 +47,9 @@ "scale" : "3x" }, { - "idiom" : "ios-marketing", "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "iTunesArtwork@2x.png", "scale" : "1x" } ], @@ -56,4 +57,4 @@ "version" : 1, "author" : "xcode" } -} \ No newline at end of file +}