Compare commits

...

352 Commits

Author SHA1 Message Date
terryworona e7c84aa4de Fixed #192 2015-12-16 20:53:31 -08:00
terryworona b7f7324d96 updated pod spec and change log 2015-12-04 17:38:38 -08:00
terryworona 78b2aa1964 Fixed up gradient bars 2015-12-04 15:22:59 -08:00
terryworona d9ab659422 Updated readme 2015-12-04 15:14:26 -08:00
terryworona 71df60f9a3 added bar chart gradient support 2015-12-04 14:30:47 -08:00
terryworona 728b9420a9 Fixed crasher 2015-12-04 13:04:12 -08:00
terryworona fe42e4f61d PR cleanup 2015-12-04 13:02:16 -08:00
terryworona 45cf0d66ba Merge with master 2015-12-03 17:48:25 -08:00
Terry Worona 5aecb0ba92 Fixed readme typo 2015-11-22 19:13:52 -08:00
Terry Worona 6f14f4099f Updated pod spec and change log 2015-11-22 19:01:36 -08:00
Terry Worona 9fa369ce8d Updated pod spec 2015-11-22 18:59:49 -08:00
Terry Worona 9828034f6b Fixed #94 2015-11-22 18:52:54 -08:00
Terry Worona 58f57fcef2 new version 2015-11-22 13:31:25 -08:00
Terry Worona 78390657d7 Added iPhone 6 support for demo app 2015-11-22 13:17:58 -08:00
Terry Worona 87a5de93af Updated readme 2015-11-22 13:09:50 -08:00
Terry Worona edfca9b780 Moving customization readme 2015-11-22 12:50:02 -08:00
Terry Worona 14c7aa7c98 Updated change log 2015-11-22 12:47:05 -08:00
terryworona b928cd1849 Fixed #159 for real this time 2015-11-20 18:13:19 -08:00
terryworona 2d6c6e291d More cleanup 2015-11-20 17:57:22 -08:00
terryworona 5addeeae83 Spacing 2015-11-20 16:58:30 -08:00
terryworona ec14cc002e Reverted #153 (won't enhance) 2015-11-20 16:47:32 -08:00
terryworona e3174efa9e Fixed #159 2015-11-20 16:08:56 -08:00
terryworona 4a1380668e Enhancement #153 2015-11-20 15:10:52 -08:00
terryworona 3752b7d598 Hide vertical selection when touches begin. 2015-11-19 09:51:26 -08:00
terryworona e1d10ffb7e Updated readme for 185 2015-11-18 17:28:07 -08:00
terryworona f2e5641d58 Fixed #185 2015-11-18 17:23:04 -08:00
terryworona b0c68377a3 Fixed #146 2015-11-18 15:32:01 -08:00
terryworona d3cb39b566 Updated project for iOS 9 support 2015-11-18 14:35:32 -08:00
terryworona 99f727c0d6 updated changelog and pod spec 2015-09-18 11:44:35 -07:00
terryworona b6bc9c29ca readme and comment 2015-09-18 11:41:05 -07:00
terryworona 124eabe98c Merge pull request #188 from andrewloyola/line-chart-touch-ignore
Delegate call to ignore touches on selected lines
2015-09-18 11:30:20 -07:00
Andrew Loyola 1f0f3351c3 Delegate call do ignore touches on selected lines
If you want to display more lines than are touchable, you can use this to ignore certain line indices
2015-09-18 11:20:50 -04:00
Terry Worona 5f8863ede1 updated changeling 2015-08-12 09:07:14 -07:00
Terry Worona bf8d5de61e updated pod spec 2015-08-12 08:49:11 -07:00
Terry Worona 23935a3b55 small cleanup 2015-08-12 08:47:26 -07:00
terryworona f7d15d4905 Merge pull request #183 from 0xPr0xy/master
Return the available height instead of 0
2015-08-12 08:43:08 -07:00
Peter IJlst 372b69ff4a Merge branch 'release/fix-invisible-bars' 2015-08-12 09:16:22 +02:00
Peter IJlst b17a37c1d7 in normalizedHeightForRawHeight () method return availableHeight instead of 0.
Fixes: http://stackoverflow.com/questions/24123794/color-of-bar-chart-not-displaying-in-jbchartview
2015-08-12 09:12:33 +02:00
Ben Norris 69ce275d1a Adds support for gradients to line charts 2015-06-17 13:55:19 -06:00
terryworona a1f34f78fb updated changelog and pod spec 2015-04-30 15:20:27 -07:00
terryworona 15e73af3b3 Merge pull request #165 from eventualbuddha/nil-delegate-and-datasource-on-dealloc
Nil out delegate and datasource on dealloc
2015-04-30 15:13:33 -07:00
Brian Donovan aac41605aa Add dealloc methods to the demos.
This is proper Cocoa etiquette and may help others prevent crashes in
their own apps.
2015-04-30 11:48:47 -07:00
Brian Donovan 0bfc904f58 Ensure our own subviews with a delegate are cleaned up.
This can potentially cause a crash if the `linesView` or `dotsView`
were to send a message to its delegate after the delegate was dealloc’d.
2015-04-30 11:45:25 -07:00
terryworona b54f27e67d Updated changelog and podspec 2015-04-16 11:54:01 -07:00
terryworona ff17a56eff Fixes #157 2015-04-16 11:52:27 -07:00
terryworona 93d98d7b87 updated changeling and pod spec 2015-04-13 12:48:49 -07:00
terryworona ba0a44ba3f Fixed radius width on demo line charts 2015-04-13 11:54:53 -07:00
terryworona 621e9a7386 removed extra synthesize calls for #154 2015-04-13 11:44:21 -07:00
terryworona 28ad5d7557 Merge pull request #154 from amro/master
Fix warnings when building w/ Xcode 6.3
2015-04-13 11:37:32 -07:00
Amro Mousa d299cd6e7e Fix warnings in Xcode 6.3
These warnings are problematic for those who
build with warnings as errors.
2015-04-09 09:43:18 -07:00
Terry Worona abf14f342a Updated readme for issue #150 2015-04-01 12:33:11 -07:00
Terry Worona 299405efe1 Updated pod spec 2015-03-30 20:07:03 -07:00
Terry Worona 27ebf131c9 Updated changelog 2015-03-30 19:07:34 -07:00
Terry Worona e3c8fb2794 Fixes #118 - access to bar and dot views 2015-03-30 19:03:44 -07:00
Terry Worona 93bea88b47 updated readme and header comments for #99 2015-03-30 16:03:45 -07:00
Terry Worona fe7f8bbae7 Fixes issue #99 - radius is now a true dot radius (not diameter) 2015-03-30 15:59:34 -07:00
Terry Worona 394bb70599 Cleaned up pr 143 2015-03-30 15:19:48 -07:00
terryworona 4e1411c302 Merge pull request #143 from ADVSENSOR/empty_data
Fix crash and warnings that can occur when a chart line has no data
2015-03-30 15:15:48 -07:00
Terry Worona 21bc7d3a3e List updates 2015-03-30 15:09:31 -07:00
terryworona 21dc1d004a Merge pull request #144 from ADVSENSOR/tooltip_zorder
Keep tooltip subviews above line subviews
2015-03-30 14:21:25 -07:00
Terry Worona 40e4434e18 Readme update 2015-03-30 14:13:04 -07:00
Terry Worona ac3c379af4 Code cleanup 2015-03-30 14:12:07 -07:00
Terry Worona 2c803e87dd cleaned up strings 2015-03-30 14:09:58 -07:00
Terry Worona 7efeaa1ef1 updated line chart docs 2015-03-30 14:04:35 -07:00
Terry Worona a454e221a6 Updated readme 2015-03-30 14:02:52 -07:00
terryworona 7046cf7045 Merge pull request #116 from sebastianreloaded/missing_values
Add ability to have the line start or end at any given point
2015-03-30 13:56:08 -07:00
terryworona e4b0fddd16 Merge pull request #142 from skywinder/add-change-log-file
Add automatically generated change log file.
2015-03-30 13:46:29 -07:00
Sebastian Opel b1c632f5a3 added docu in readme 2015-03-25 11:56:51 +01:00
Sebastian Opel 162619b825 coding style fixes 2015-03-17 10:45:37 +01:00
Sebastian Opel 32cbb39d0b if all points are NAN no need to continue the path 2015-03-17 10:43:46 +01:00
Trevor Harmon 3a0fac18c5 Keep tooltip subviews above line subviews 2015-03-07 16:43:51 -08:00
Trevor Harmon 4c0a22d962 Fix crash and warnings that can occur when a chart line has no data 2015-03-07 14:27:24 -08:00
Petr Korolev 76c1c41886 Added automatically generated change log file 2015-03-05 15:29:07 +02:00
Terry Worona e3b8ccd704 Fixed #140 2015-03-04 22:34:39 -08:00
terryworona b179f20ef9 Merge pull request #127 from paal123/patch-1
Update README.md
2014-11-25 08:56:52 -08:00
paal123 d89472dea5 Update README.md
Removed a small typo resulting in errors during execution.
2014-11-25 16:12:02 +01:00
Sebastian Opel 907a4f25ae added missing points to new example fake data 2014-10-23 17:08:03 +02:00
Sebastian Opel 51454fe3f6 added a copy of linechart example as a new example for missing points 2014-10-23 17:06:09 +02:00
Sebastian Opel 131f251df8 added handling of missing values within a linechart
JBLineChartView uses numberOfVerticalValuesAtLineIndex to define the number
of points, but subsequently requires that all chartPoints have a value anyway.
This commit allows you to use NAN within the charts data.
2014-10-23 16:44:44 +02:00
Terry Worona 64451dd5ac pod spec and read me updates 2014-09-22 19:05:18 -07:00
Terry Worona 36d72ce510 change log and comments 2014-09-22 19:03:25 -07:00
Terry Worona efd8f97335 Removed changes for setFrame 2014-09-22 19:00:10 -07:00
Terry Worona 243c28cffb update to change log, read me, pod spec, etc 2014-09-22 11:18:11 -07:00
Terry Worona 66bf3b14e8 Fixed #111 2014-09-22 11:16:48 -07:00
Terry Worona 7287712da3 More cleanup of compiler warnings on iOS 8 2014-09-22 11:11:32 -07:00
Terry Worona e71db56a76 updated read me, change log, etc 2014-09-19 19:41:52 -07:00
Terry Worona 4be903eda7 fixed some compiler warnings 2014-09-19 19:35:37 -07:00
Terry Worona d5210eff99 Updated read me, change log and pod spec 2014-09-08 22:35:27 -07:00
Terry Worona 956386c7db Cleanup 2014-09-08 22:17:52 -07:00
terryworona c6dfb48047 Merge pull request #106 from eventualbuddha/reduce-numberOfLinesInLineChartView-calls
Only call `numberOfLinesInLineChartView:` once per loop.
2014-09-08 22:17:06 -07:00
terryworona fff2bd22d6 Merge pull request #107 from thefirstnikhil/master
iOS Framework Support
2014-09-08 22:08:46 -07:00
Nikhil Kalra 23e8e3084a iOS Framework Support
Added a UIKit import statement for use when JBChartView is added to a
Xcode project as a framework (iOS 8).
2014-09-05 21:48:15 -07:00
Brian Donovan d04eaa2622 Only call numberOfLinesInLineChartView: once per loop. 2014-09-05 11:18:21 -07:00
Terry Worona e24d2487f1 updated pod spec 2014-08-29 15:23:25 -07:00
Terry Worona d3a92dd70f updated read me and change log fixed issue #100 2014-08-29 15:22:56 -07:00
Terry Worona c73f494034 added custom dot view hide functionality on selection events 2014-08-29 15:19:49 -07:00
Terry Worona 80708acda1 Updated pod spec 2014-08-28 14:52:58 -07:00
Terry Worona 6308ee1b19 Updated read me and change log 2014-08-28 14:50:42 -07:00
Terry Worona 62965bbd9f Finished line chart padding extension properties 2014-08-28 13:51:33 -07:00
Terry Worona 06bf8b5033 Finished bar chart padding extension properties 2014-08-28 13:37:39 -07:00
Terry Worona c2a16d0fbb added optional protocol for footer/header padding extensions 2014-08-28 13:24:13 -07:00
Terry Worona 9548b2ab32 Don't extend selection views into padding 2014-08-28 13:14:58 -07:00
Terry Worona 295fb40a0b Fixed up bar charts to utilize padding properly 2014-08-28 13:01:57 -07:00
Terry Worona e29ebd39ab Updated line chart view for footer padding 2014-08-28 12:10:35 -07:00
Terry Worona 27b0493b9b Added footer padding property and updated bar chart to use it 2014-08-28 12:00:04 -07:00
Terry Worona 04f40aac1a Updated read me 2014-08-27 11:35:42 -07:00
Terry Worona 833f6e9080 Fixed issue #97 2014-08-27 11:27:58 -07:00
Terry Worona eb48db2e73 Updated comment 2014-08-27 11:21:45 -07:00
Terry Worona 55b6dae956 Cleaned up bar pop animations 2014-08-27 11:19:45 -07:00
Terry Worona c44b276ae1 fixed vertical selection adjustment 2014-08-26 19:14:15 -07:00
Terry Worona 93f3d1862e simplified bar chart animations and added invert flag 2014-08-26 19:02:06 -07:00
Terry Worona 19a4a0bf5c Updated pod spec 2014-08-26 15:49:59 -07:00
Terry Worona 9d43c6dd23 updated read me and pod spec 2014-08-26 15:49:21 -07:00
Terry Worona 8598ff1488 Fixed issue #93 2014-08-26 15:46:03 -07:00
Terry Worona b9d28bfd59 Updated pod spec 2014-08-26 15:40:00 -07:00
Terry Worona dd1dce758e updated read me and change log 2014-08-26 15:39:25 -07:00
Terry Worona 9fce2fc1c0 Fixed #95 2014-08-26 15:35:40 -07:00
Terry Worona ab1cf713e6 Fixed bar chart selection view for non-homogenous bar widths 2014-08-26 15:29:05 -07:00
Terry Worona 4363147303 updated read me 2014-08-22 18:19:34 -07:00
Terry Worona 8a1770c6df Updated pod spec 2014-08-22 18:13:52 -07:00
Terry Worona f84f322598 updated read me 2014-08-22 18:13:20 -07:00
Terry Worona 04e1aa5b98 Hide custom dots on selector for now 2014-08-22 18:10:30 -07:00
Terry Worona ab07aa2399 Fixed padding issues 2014-08-22 15:36:08 -07:00
Terry Worona f01e11a0e2 Added custom dot views to line chart 2014-08-22 14:21:06 -07:00
Terry Worona 76984c7c7c added protocols for custom dots 2014-08-22 12:07:09 -07:00
Terry Worona d38a04a70d Added dot radius on a per horizontal index basis 2014-08-22 11:52:53 -07:00
Terry Worona 385d5b3589 Updated pod spec 2014-08-14 19:26:18 -07:00
Terry Worona 90100c7277 updated read me and change log 2014-08-14 19:25:39 -07:00
Terry Worona eca1c0507e Cleaned up PR #90 2014-08-14 19:23:19 -07:00
terryworona ac870e45ce Merge pull request #90 from mszaro/master
Add per-line vertical selection color support.
2014-08-14 19:17:19 -07:00
mszaro 74f588b7e6 Update comment. 2014-08-14 18:51:48 -07:00
mszaro 406b64ae0c Implement per-line vertical selection colors 2014-08-14 18:50:55 -07:00
Terry Worona 92e56d78c5 updates specs and read me 2014-08-14 18:01:04 -07:00
Terry Worona 36ec328346 Fixed issue #89 2014-08-14 17:57:39 -07:00
Terry Worona b763ae540c updated version 2014-08-07 13:33:46 -07:00
Terry Worona 7ffdf6d9da Fixed issue #83 2014-08-07 13:30:48 -07:00
Terry Worona 6531c68574 version update 2014-08-04 13:37:33 -07:00
Terry Worona ebae36bd2f Pushed base datasource and delegate protocols up to JBChartView (for extensibility) 2014-08-04 13:17:04 -07:00
Terry Worona 8cdff2891c Updated version 2014-08-04 10:15:05 -07:00
Terry Worona 333200d041 Fixed issue #77 2014-08-04 10:13:05 -07:00
Terry Worona 6ad3bd7692 Readme update 2014-08-02 12:20:25 -07:00
Terry Worona 3531e593da update change log, read me, pod spec 2014-08-02 12:13:12 -07:00
Terry Worona eeb9ca604c More refactors 2014-08-02 12:02:01 -07:00
Terry Worona b884108dbb More line chart refactors 2014-08-02 11:46:25 -07:00
Terry Worona 00dd74f733 Started JBLineChartView refactor 2014-08-02 11:22:58 -07:00
Terry Worona c1938147d8 Cleaned up warning 2014-08-02 11:17:09 -07:00
Terry Worona e17c5419f4 Refactor JBBarChartView datasource and delegate 2014-08-02 11:14:36 -07:00
Terry Worona d0cb8b0307 Updated pod spec 2014-07-31 13:30:53 -07:00
Terry Worona fe81df094e Updated change log and read me 2014-07-31 13:29:58 -07:00
Terry Worona 0dae570cc6 Fixed line width bug for JBLineChartView 2014-07-31 13:28:07 -07:00
Terry Worona c5c93cb660 update version, read me, pod spec 2014-07-25 16:43:34 -07:00
Terry Worona 3df69b0a9c more demo chart cleanup 2014-07-25 16:19:28 -07:00
Terry Worona 30305cdde9 String cleanup 2014-07-25 16:12:00 -07:00
Terry Worona 8e1cbba06f Fixed chart coloring 2014-07-25 16:00:07 -07:00
Terry Worona 97e5acdb1a added area controller and assets 2014-07-25 15:55:48 -07:00
Terry Worona 47f1f0ba8d Reverted base to iOS 6 2014-07-25 15:22:08 -07:00
Terry Worona 0be9465049 Fixed OS checks 2014-07-25 15:18:47 -07:00
Terry Worona 7bed3dd5d0 updated pod spec, change log and read me 2014-07-25 14:18:23 -07:00
Luo Sheng 4f1f6760d5 Update the Podspec. 2014-07-25 12:28:33 +08:00
Luo Sheng 8103a1aea4 Make the demo run in iOS 6 too. 2014-07-25 12:27:51 +08:00
Luo Sheng dc6dc647ad Use sizeWithFont: method for iOS 6. 2014-07-25 12:23:26 +08:00
Terry Worona b6ea1a502a Updated pod spec 2014-07-24 16:20:10 -07:00
Terry Worona afcf328158 Fixed readme 2014-07-24 15:43:47 -07:00
Terry Worona 49cf12c568 updated read me and change log of fill functions 2014-07-24 15:39:37 -07:00
Terry Worona 0d4b942b74 Merge branch 'master' of https://github.com/Jawbone/JBChartView 2014-07-24 15:25:22 -07:00
Terry Worona 30a369796f Minor cleanup of PR #71 2014-07-24 15:25:15 -07:00
Terry Worona f2f35312e4 Updated read me 2014-07-24 14:32:22 -07:00
terryworona d32f09a584 Merge pull request #67 from jonparker/master
Added documentation for usage in a Swift project
2014-07-18 11:15:44 -07:00
Damien Legrand 80e179df1d Fill Color
Fill color for line chart :
* Default color is clearColor
* The user can define a color and a selection color for each line with
two new methods in JBLineChartViewDataSource protocol
2014-07-17 17:38:24 +02:00
Terry Worona 48da335f09 added spark friends link 2014-06-30 19:24:06 -07:00
Terry Worona 70c1fb897c added more demos section 2014-06-24 13:05:52 -07:00
Terry Worona 30df02f804 screen update 2014-06-24 12:58:50 -07:00
Terry Worona 9ba20e9e14 updated screenshot 2014-06-24 12:52:37 -07:00
Terry Worona d6d1dd8461 Updated screenshot 2014-06-24 12:21:21 -07:00
Jonathan Parker b0de620503 Added link to iOS documentation. 2014-06-23 15:49:26 +10:00
Jonathan Parker 8e81fb20cd Added instructions for use in a Swift project. 2014-06-23 15:46:37 +10:00
Terry Worona a303422d8e updated read me, pod spec, etc 2014-05-13 19:44:52 -07:00
Terry Worona 1aff68557f Cleaned up demo code and add min value to bar charts 2014-05-13 19:42:14 -07:00
terryworona ac3744c0c9 Merge pull request #57 from pala/master
Fixed barView's frame.
2014-05-13 19:33:55 -07:00
Tao Zhang a6ea0c30f8 Update JBBarChartView.m 2014-05-13 21:56:02 -04:00
pala ea531e3cb1 Fixed barView's frame. 2014-05-13 19:42:06 -04:00
terryworona b1a3ebd4ed Merge pull request #55 from pala/patch-1
Update sample code in readme
2014-05-13 10:39:24 -07:00
Tao Zhang 554f93f3d3 Update sample code 2014-05-12 23:41:25 -04:00
Terry Worona 2ddd38fc9d updated change log 2014-05-07 09:55:10 -07:00
Terry Worona 6691f7a8c3 Updated comment, read me, pod spec, etc 2014-05-07 09:47:32 -07:00
terryworona c015531c85 Merge pull request #53 from skywinder/bar-color-delegate
Add delegate method barChartView:colorForBarViewAtIndex: to JBBarChartViewDataSource
2014-05-07 09:40:43 -07:00
terryworona 3d036edc96 Merge pull request #52 from skywinder/compiling-warrnings-and-typos
Compiling warrnings and typos
2014-05-07 09:36:48 -07:00
Petr Korolev 85c30351fe Add new delegate method to JBBarChartView
Implement logic to set specifed color before set the default kJBBarChartViewDefaultBarColor
Add call of this code to Example project
2014-05-07 15:33:50 +03:00
Petr Korolev d37383a352 fix typo 2014-05-07 14:59:34 +03:00
Petr Korolev 3c6cf24cf7 Cast to correct return type (NSUInteger) 2014-05-07 14:37:28 +03:00
Terry Worona 8dbb2679ee Updated log, spec and read me 2014-05-06 14:05:24 -07:00
Terry Worona 867466d1d1 More more compile error 2014-05-06 14:04:17 -07:00
Terry Worona 2046131143 Updated read me, pod spec, etc. 2014-05-06 13:40:21 -07:00
Terry Worona 208a727d88 Fixed compiler warnings 2014-05-06 13:38:24 -07:00
Terry Worona 43c6e9486f Updated version, pod spec, etc 2014-05-05 12:33:39 -07:00
Terry Worona 49206a01ed Fixed issue #48 2014-05-05 12:31:12 -07:00
Terry Worona e2b17820bf readme updates 2014-05-04 14:47:21 -07:00
Terry Worona b59904e5b9 updated for new version 2014-05-04 14:45:27 -07:00
Terry Worona 1d8f78d751 Fixed issue #48 2014-05-04 14:07:27 -07:00
Terry Worona 3cc39124b8 updated version 2014-05-04 09:48:10 -07:00
terryworona bedd7e2c71 Merge pull request #49 from simonnickel/master
fixed typo, renamed mininum -> minimum
2014-05-04 09:44:03 -07:00
Simon Nickel 786af91666 fixed typo, renamed mininum -> minimum 2014-05-03 22:18:42 +02:00
Terry Worona b7927cddb7 Fixes issue #46 2014-04-30 22:58:47 -07:00
Terry Worona 0f2d4d766c updated change log, pod spec, etc 2014-04-30 10:04:01 -07:00
terryworona 64de3e6e23 Merge pull request #45 from ktran03/smoothCurveFix
Smooth curve fix
2014-04-30 09:59:22 -07:00
ktran03 87fb8ee7b8 missing variable in condition 2014-04-29 22:03:40 -04:00
ktran03 7c0dfe3eb5 smooth curve fix for more straight line cases 2014-04-29 21:55:47 -04:00
Terry Worona 87b62ad2b1 updated change log, pod spec, read me 2014-04-28 12:06:03 -07:00
Terry Worona 9c0d788418 More style updates 2014-04-28 12:00:59 -07:00
Terry Worona de009f0236 PR #39 cleanup 2014-04-28 11:25:45 -07:00
ktran03 d46e4fe14d changed compare condition to using slope instead of vertical diff 2014-04-26 18:32:40 -04:00
ktran03 236336fdf3 added check for y-value difference if exceeds threshold 2014-04-25 15:14:16 -04:00
ktran03 9b60a1d662 Expose smooth option through delegate, fix diffs 2014-04-24 14:35:54 -04:00
ktran03 3700b4e2e2 smooth curve using bezierpath 2014-04-19 20:15:53 -04:00
Terry Worona 8c03033a1c Added screenshot to pod spec 2014-04-18 10:14:42 -07:00
Terry Worona bb084b1b89 Fixes issue #34 2014-04-17 18:32:58 -07:00
Terry Worona 1c7c8b2e52 Updated read me, pod spec etc for new version 2014-04-14 10:36:07 -07:00
Terry Worona 79a57d98e3 Clamp selection width to width of chart 2014-04-14 10:32:50 -07:00
Terry Worona 20d6b6081b Fixed comment 2014-04-14 10:30:24 -07:00
terryworona 20bbbdcc86 Merge pull request #37 from veducm/master
Added delegate method to configure the width of the vertical selection bar in a line chart.
2014-04-14 10:27:51 -07:00
Edu Caselles 51ac8a1d63 Added delegate method to configure the width of the vertical selection bar in a line chart. 2014-04-14 01:35:20 +02:00
Terry Worona 68d04a2cdb Fixes issue #36 2014-04-12 09:11:41 -07:00
Terry Worona b7734ef189 Updated for new version 2014-04-11 15:02:46 -07:00
Terry Worona f6d2fe8b62 Fixed issue #33 2014-04-11 15:00:33 -07:00
Terry Worona 5c9679f448 updated read me, etc for new version 2014-04-10 16:18:52 -07:00
Terry Worona 037225a386 Fixed issue #30 2014-04-10 16:15:28 -07:00
terryworona 0fe979bd22 Merge pull request #30 from gumbypp/master
JBChartView: needs initWithCoder initializer for inflation from a xib
2014-04-10 16:13:34 -07:00
Dale Low 31b64ed7e4 JBChartView: needs initWithCoder initializer for inflation from a xib 2014-04-10 16:00:27 -07:00
Terry Worona c30398c3ea Updated readme 2014-04-10 13:23:26 -07:00
Terry Worona bc08322a3a Updated version 2014-04-10 13:13:38 -07:00
Terry Worona 213973f4ed Fixing line chart padding calculations for custom dot radius 2014-04-10 11:20:16 -07:00
Terry Worona 28d40bcb31 Added dot radius callbacks for line charts 2014-04-10 10:58:47 -07:00
Terry Worona d4df0184a2 Updated change log, pod spec and read me 2014-04-03 14:49:36 -07:00
Terry Worona 4f313aab80 Added state force setters 2014-04-03 14:48:01 -07:00
Terry Worona b6262462c5 Updated pod spec change log and read me 2014-04-02 11:49:52 -07:00
Terry Worona 1080089753 Added dynamic padding to line chart view 2014-04-02 11:46:42 -07:00
Terry Worona 0afba01a9a Updated read me and pod spec 2014-04-02 10:26:59 -07:00
Terry Worona 63b47667ec Fixed min and max value properties 2014-04-02 09:08:12 -07:00
Terry Worona 4d6baf066f cleaned up cached constants 2014-04-02 08:50:43 -07:00
Terry Worona 359ef7d0ea Updated read me, change log and podspec 2014-03-30 21:50:00 -07:00
Terry Worona 7b1e6475f2 Clamp min and value values if supplied 2014-03-30 21:47:00 -07:00
Terry Worona 2b8853780c added optional min and max value properties to JBChartView 2014-03-30 21:27:00 -07:00
Terry Worona 0754e2e5d2 min height patches 2014-03-29 19:20:15 -07:00
Terry Worona 52b722013e updated change log 2014-03-27 16:05:00 -07:00
Terry Worona 4ef9b6442e Changelog updates 2014-03-27 14:21:15 -07:00
Terry Worona 177e076807 Readme update 2014-03-27 14:11:12 -07:00
Terry Worona 21969d759d changelog styling 2014-03-27 14:08:28 -07:00
Terry Worona 4fd6f1cb63 Added change log 2014-03-27 14:06:32 -07:00
Terry Worona 804ce2ca67 Updated line chart header comments 2014-03-27 13:02:07 -07:00
Terry Worona 485cfb9631 Fixed dot selections 2014-03-27 12:54:12 -07:00
Terry Worona 4640dede3a updated pod spec 2014-03-26 15:14:46 -07:00
Terry Worona 1b90c6e16f Updated read me 2014-03-26 15:13:53 -07:00
Terry Worona 15b53aa68e added line smooth bools 2014-03-26 15:05:37 -07:00
Terry Worona 0e277dc347 more dot selection cleanup 2014-03-26 14:12:05 -07:00
Terry Worona 6de42998c0 selection cleanups 2014-03-26 14:09:38 -07:00
Terry Worona a1e4be3a5d Dot selections 2014-03-26 14:01:29 -07:00
Terry Worona acaf6fb4dc moved dot function to datasource for line graphs 2014-03-26 12:49:35 -07:00
Terry Worona 5894610278 finished new line chart animations 2014-03-26 11:55:58 -07:00
Terry Worona e605e60f28 Line chart animation cleanup 2014-03-26 11:34:24 -07:00
Terry Worona 33b3c9518f Simplifying line chart animations 2014-03-26 10:40:44 -07:00
Terry Worona aec3d31e17 much work on dot views for lines 2014-03-25 16:56:46 -07:00
Terry Worona c99a0429b4 Implementation cleanup 2014-03-25 16:08:28 -07:00
Terry Worona f9fc90244f created custom line dot views 2014-03-25 16:07:38 -07:00
Terry Worona 6b0198f732 Created dot view class to get perfect circles 2014-03-25 15:59:47 -07:00
Terry Worona f0e52b42d7 More class naming convention changes 2014-03-25 15:47:26 -07:00
Terry Worona 381850ada4 Updated view names 2014-03-25 15:40:00 -07:00
Terry Worona 8b22d5fadd Started dot line implementation 2014-03-25 15:35:10 -07:00
Terry Worona 01171b9487 Updated read me and version 2014-03-19 13:32:27 -07:00
Terry Worona d3a1ce1c25 Fixed issue #22 2014-03-19 13:30:26 -07:00
Terry Worona 3b6863786f Updated read me 2014-03-19 13:27:00 -07:00
Terry Worona 1d39945e62 added frame and reload docs to readme 2014-03-18 17:56:17 -07:00
Terry Worona f0f1d5174e More read me work 2014-03-18 17:38:14 -07:00
Terry Worona 11e0f21e03 More read me work 2014-03-18 17:35:57 -07:00
Terry Worona 59183657e8 Center image 2014-03-18 17:35:26 -07:00
Terry Worona 47a75d4291 updated image 2014-03-18 17:34:41 -07:00
Terry Worona 32a449f460 Updated read me and pod spec 2014-03-18 17:32:42 -07:00
terryworona d9aea500bf Merge pull request #21 from Jawbone/multi_line
Multiple Line Support & Tooltips
2014-03-18 17:31:32 -07:00
Terry Worona 8c947322ae Added new line to constants file 2014-03-18 17:28:45 -07:00
Terry Worona 5b397a4f49 fixed assert comment 2014-03-18 17:28:23 -07:00
Terry Worona 44c79e8a7c Minor fix to bar chart datasource 2014-03-18 17:03:14 -07:00
Terry Worona 40db9062ce Line view assert checks 2014-03-18 17:01:07 -07:00
Terry Worona dafb0f81d4 More asserts for bar charts 2014-03-18 16:54:43 -07:00
Terry Worona f8df682b62 more asserts 2014-03-18 16:48:34 -07:00
Terry Worona 293dc29183 Added asserts 2014-03-18 16:48:12 -07:00
Terry Worona ef1b8b3414 Fixed extreme value bugs 2014-03-18 16:24:50 -07:00
Terry Worona 58bbb99c94 Updated read me 2014-03-18 16:04:18 -07:00
Terry Worona b829884008 Cleaned up strings and random chart data 2014-03-18 15:12:06 -07:00
Terry Worona e82756172b Cleaning up string constants 2014-03-18 14:08:30 -07:00
Terry Worona 58651a3325 fixed line chart out of bounds crash 2014-03-18 11:47:58 -07:00
Terry Worona 328b5775aa Changed line chart style order 2014-03-17 14:27:43 -07:00
Terry Worona 64f22aa758 more readme 2014-03-17 14:22:58 -07:00
Terry Worona bc9e9c31b5 Cleaning up read me 2014-03-17 14:21:13 -07:00
Terry Worona c4d1d2ade3 Updated read me and pod spec 2014-03-17 14:15:37 -07:00
Terry Worona 97874ce1ef Updated project settings 2014-03-17 14:15:28 -07:00
Terry Worona dcc826e8a6 Added nib init support 2014-03-17 11:28:22 -07:00
Terry Worona 31bb7a0a2b more tooltip views 2014-03-17 11:08:16 -07:00
Terry Worona d83742315f more tooltip cleanup 2014-03-17 11:06:41 -07:00
Terry Worona 7e4cbc0533 More tooltip work 2014-03-17 10:57:34 -07:00
Terry Worona 87d752c5e3 Improving chart tooltip position 2014-03-17 10:39:03 -07:00
Terry Worona 5f2de0e862 More tooltip work and tooltip tip view 2014-03-17 10:32:48 -07:00
Terry Worona 0d4f17dd25 Updated line separator size 2014-03-13 17:57:05 -07:00
Terry Worona 9ba965ecf0 added tooltip to bar chart view 2014-03-13 16:53:49 -07:00
Terry Worona 31b0ba8e28 moved tooltip functionality to base chart controller 2014-03-13 16:46:57 -07:00
Terry Worona 9edd9d562a Merge branch 'master' of https://github.com/Jawbone/JBChartView into multi_line 2014-03-13 16:21:13 -07:00
Terry Worona d30abc6a1a Fixed issue #19 2014-03-13 16:12:22 -07:00
Terry Worona 78d1bfb275 Information view cleanup 2014-03-12 19:16:10 -07:00
Terry Worona b6de13f1ac more tooltip and touch work 2014-03-12 18:42:43 -07:00
Terry Worona 1dbd52fd75 tooltip work 2014-03-12 18:27:32 -07:00
Terry Worona 0917d4b6b8 more opacity work 2014-03-12 16:47:31 -07:00
Terry Worona d10b42dc5a added line dims on selection 2014-03-12 16:45:24 -07:00
Terry Worona 78f34ecaa5 more constant cleanup 2014-03-12 16:27:48 -07:00
Terry Worona cc2d356223 cleaning up line controller 2014-03-12 16:25:09 -07:00
Terry Worona 2c8a578f92 added interface comments 2014-03-12 16:15:03 -07:00
Terry Worona 2e5b1c4d01 line chart line style work 2014-03-12 16:03:05 -07:00
Terry Worona a58ac858ab Integer cleanup and adding line customization 2014-03-12 15:17:30 -07:00
Terry Worona ebfb4c421e Added comments 2014-03-11 15:02:32 -07:00
Terry Worona b08324e6dd Fixed chart extremes 2014-03-11 14:58:39 -07:00
Terry Worona 72dda814c6 more line cleanup 2014-03-11 14:01:49 -07:00
Terry Worona e76daca899 updated datasource functions 2014-03-11 12:04:38 -07:00
Terry Worona bafcc02862 updating chart comments 2014-03-11 11:51:50 -07:00
Terry Worona 9d80750467 Internal line view cleanup 2014-03-11 11:28:06 -07:00
Terry Worona 8c93fafa37 Multiple line selections finally working. 2014-03-10 19:14:35 -07:00
Terry Worona e518246f26 line selection working 2014-03-07 15:01:16 -08:00
Terry Worona a1256c3297 single line selections 2014-03-07 14:18:14 -08:00
Terry Worona 84ca6d41ae Line selection 2014-03-05 19:31:19 -08:00
Terry Worona d94ef105cf consolidated touch code 2014-03-05 16:41:36 -08:00
Terry Worona 361985f236 More selection view cleanup 2014-03-05 16:29:27 -08:00
Terry Worona 6987b4636a more property cleanup 2014-03-05 16:04:01 -08:00
Terry Worona 18f56fa818 more property renaming for selection views 2014-03-05 15:59:05 -08:00
Terry Worona 5724b8424f Property renaming 2014-03-05 14:57:15 -08:00
Terry Worona f62b3be08e Line chart line selection logic 2014-03-05 14:52:20 -08:00
Terry Worona a4c21168ab hooking up line index logic 2014-03-04 11:56:23 -08:00
Terry Worona f1ec5add4b Updated shows selection bool naming 2014-03-04 11:53:29 -08:00
Terry Worona 62ed0c6496 Started multi line support 2014-03-04 11:36:24 -08:00
Terry Worona 3d5e5c3e1d Updated podspect 2014-03-02 17:24:33 -08:00
Terry Worona 7e33f7121a Updated read me 2014-03-02 17:23:53 -08:00
Terry Worona 09fefa292a Added assert check for line width and added hookups to demo project 2014-03-02 17:16:51 -08:00
Terry Worona 47c6d744ba added periods to comments 2014-03-02 17:14:49 -08:00
Terry Worona fc32f8282e Moved pod spec back into /Classes 2014-03-02 17:10:31 -08:00
terryworona 7ee84c24f0 Merge pull request #15 from kmcbride/line-customization
Added customization for line width
2014-03-02 17:06:44 -08:00
Terry Worona 12a15f1051 Added default init for bar and line charts. 2014-03-02 16:49:03 -08:00
Kylan McBride 6a8f927510 Moved podspec location 2014-02-14 22:36:25 -08:00
Kylan McBride 3bf16ecae9 Added line width customization 2014-02-14 22:34:23 -08:00
Kylan McBride 5a7b211f16 Fixed Typo and excess whitespace 2014-02-14 22:32:44 -08:00
terryworona 189c907bb9 Merge pull request #14 from Undo1/patch-1
fix spelling mistake
2014-02-14 09:38:35 -08:00
Undo1 6f16ae64ab fix spelling mistake 2014-02-13 20:06:11 -07:00
Terry Worona b911dfa9e2 Updated version 2014-02-11 16:47:54 -08:00
Terry Worona 2335a371b6 Fixed selection view cancelled bug 2014-02-07 10:23:48 -08:00
Terry Worona b41d7ad944 Don't clip bar chart views 2014-02-07 09:52:57 -08:00
Terry Worona 4ffb2e1e0c Fixed minor bar chart animation bugs 2014-02-07 09:39:56 -08:00
Terry Worona 9ae2adb81c Updated version and read me 2014-02-06 10:58:29 -08:00
Terry Worona 185782daab Fixed compilation warnings 2014-02-06 10:48:28 -08:00
49 changed files with 5116 additions and 1032 deletions
+588
View File
@@ -0,0 +1,588 @@
# Change Log
## [v2.9.0](https://github.com/Jawbone/JBChartView/tree/v2.9.0) (2015-12-04)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.8.19...v2.9.0)
## [v2.8.19](https://github.com/Jawbone/JBChartView/tree/v2.8.19) (2015-11-23)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.8.18...v2.8.19)
**Fixed bugs:**
- Straight lines [\#94](https://github.com/Jawbone/JBChartView/issues/94)
## [v2.8.18](https://github.com/Jawbone/JBChartView/tree/v2.8.18) (2015-11-22)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.8.17...v2.8.18)
**Implemented enhancements:**
- Vertical values should be supplied by the DataSource delegate for LineCharts [\#180](https://github.com/Jawbone/JBChartView/issues/180)
- JBLineChartDotsView reloadData performance issues [\#179](https://github.com/Jawbone/JBChartView/issues/179)
## [v2.8.17](https://github.com/Jawbone/JBChartView/tree/v2.8.17) (2015-11-21)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.8.16...v2.8.17)
**Implemented enhancements:**
- Disabling/Enabling certain functionality: line chart selection and x-axis values [\#185](https://github.com/Jawbone/JBChartView/issues/185)
- Add ability to set selection permanently. [\#153](https://github.com/Jawbone/JBChartView/issues/153)
- The line fill color doesn't match the bottom of the drawn line [\#146](https://github.com/Jawbone/JBChartView/issues/146)
**Fixed bugs:**
- Bug when quickly tapping a line chart in two different places [\#159](https://github.com/Jawbone/JBChartView/issues/159)
**Closed issues:**
- Show dot only on vertical line selection [\#190](https://github.com/Jawbone/JBChartView/issues/190)
- Needs to support negative values [\#189](https://github.com/Jawbone/JBChartView/issues/189)
## [v2.8.16](https://github.com/Jawbone/JBChartView/tree/v2.8.16) (2015-09-18)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.8.15...v2.8.16)
**Closed issues:**
- Partially filled bar [\#186](https://github.com/Jawbone/JBChartView/issues/186)
**Merged pull requests:**
- Delegate call to ignore touches on selected lines [\#188](https://github.com/Jawbone/JBChartView/pull/188) ([andrewloyola](https://github.com/andrewloyola))
## [v2.8.15](https://github.com/Jawbone/JBChartView/tree/v2.8.15) (2015-08-12)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.8.14...v2.8.15)
**Implemented enhancements:**
- Suggestion for the README.md [\#176](https://github.com/Jawbone/JBChartView/issues/176)
**Fixed bugs:**
- Line color overlap issue [\#168](https://github.com/Jawbone/JBChartView/issues/168)
**Closed issues:**
- JBLineChart reloadData problem [\#181](https://github.com/Jawbone/JBChartView/issues/181)
- JBLineChartView: wrong width on iPhone6/6+ [\#177](https://github.com/Jawbone/JBChartView/issues/177)
- Is there anyway to plot two vertical values for one horizontal index in the bar chart? [\#172](https://github.com/Jawbone/JBChartView/issues/172)
- Charts not rendering properly [\#171](https://github.com/Jawbone/JBChartView/issues/171)
- How can you set the bar chart to fill the width of a UIView? [\#170](https://github.com/Jawbone/JBChartView/issues/170)
- Adding X and Y Values [\#169](https://github.com/Jawbone/JBChartView/issues/169)
- Undefined symbols for architecture i386 [\#167](https://github.com/Jawbone/JBChartView/issues/167)
- Not All Data Points Visible in Flexible View [\#166](https://github.com/Jawbone/JBChartView/issues/166)
**Merged pull requests:**
- Return the available height instead of 0 [\#183](https://github.com/Jawbone/JBChartView/pull/183) ([0xPr0xy](https://github.com/0xPr0xy))
- Adds support for gradients to line charts [\#175](https://github.com/Jawbone/JBChartView/pull/175) ([benjaminsnorris](https://github.com/benjaminsnorris))
## [v2.8.14](https://github.com/Jawbone/JBChartView/tree/v2.8.14) (2015-04-30)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.8.13...v2.8.14)
**Closed issues:**
- Will JBChartView integrated with React Native? [\#164](https://github.com/Jawbone/JBChartView/issues/164)
- white dot+dotted lines sometimes does not appear when touched. [\#161](https://github.com/Jawbone/JBChartView/issues/161)
- Small offset when using a footer for a x-axis [\#160](https://github.com/Jawbone/JBChartView/issues/160)
- gradient for bar chart is lost / sizing problem [\#158](https://github.com/Jawbone/JBChartView/issues/158)
**Merged pull requests:**
- Nil out delegate and datasource on dealloc [\#165](https://github.com/Jawbone/JBChartView/pull/165) ([eventualbuddha](https://github.com/eventualbuddha))
## [v2.8.13](https://github.com/Jawbone/JBChartView/tree/v2.8.13) (2015-04-16)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.8.12...v2.8.13)
**Fixed bugs:**
- Wrong calculation of the lineIndex [\#157](https://github.com/Jawbone/JBChartView/issues/157)
**Closed issues:**
- Swift round up for respondsToSelector\(\) and sizeWithFont\(\) [\#156](https://github.com/Jawbone/JBChartView/issues/156)
## [v2.8.12](https://github.com/Jawbone/JBChartView/tree/v2.8.12) (2015-04-13)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.8.11...v2.8.12)
**Fixed bugs:**
- Footer and Header view Swift implementation [\#152](https://github.com/Jawbone/JBChartView/issues/152)
**Closed issues:**
- Problems with selection when JBLineChartView is within UITableView [\#155](https://github.com/Jawbone/JBChartView/issues/155)
- Show chart selection permanently [\#151](https://github.com/Jawbone/JBChartView/issues/151)
- Crash when returning NAN [\#150](https://github.com/Jawbone/JBChartView/issues/150)
**Merged pull requests:**
- Fix warnings when building w/ Xcode 6.3 [\#154](https://github.com/Jawbone/JBChartView/pull/154) ([amro](https://github.com/amro))
## [v2.8.11](https://github.com/Jawbone/JBChartView/tree/v2.8.11) (2015-03-31)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.8.10...v2.8.11)
**Implemented enhancements:**
- Pass back barView & dot instances on selection [\#118](https://github.com/Jawbone/JBChartView/issues/118)
- Add ability to have the line start or end at any given point [\#115](https://github.com/Jawbone/JBChartView/issues/115)
- Consolidate dot view selection/unselection/color calls [\#101](https://github.com/Jawbone/JBChartView/issues/101)
- Change dot radius to dot diameter [\#99](https://github.com/Jawbone/JBChartView/issues/99)
- need Swift implementation details and example [\#80](https://github.com/Jawbone/JBChartView/issues/80)
- Add bar/line caching for only visible content. [\#61](https://github.com/Jawbone/JBChartView/issues/61)
**Closed issues:**
- Pie Chart support [\#149](https://github.com/Jawbone/JBChartView/issues/149)
- hi is it possible to have x,y value because in example there is no y value and only 2 x value [\#141](https://github.com/Jawbone/JBChartView/issues/141)
- imports without pods [\#140](https://github.com/Jawbone/JBChartView/issues/140)
- How can I group Bars? [\#139](https://github.com/Jawbone/JBChartView/issues/139)
- request: AreaChart - fillColorForLineAtLineIndex - add custom color for a specific X axis range [\#137](https://github.com/Jawbone/JBChartView/issues/137)
- smallest value is shown as a blank bar [\#136](https://github.com/Jawbone/JBChartView/issues/136)
- Is there any way I can use JBBarChartView as horizontal bars? [\#135](https://github.com/Jawbone/JBChartView/issues/135)
- Multiple colors to a line graph [\#134](https://github.com/Jawbone/JBChartView/issues/134)
- Overriding - \(void\)barChartView:\(JBBarChartView \*\)barChartView didSelectBarAtIndex:\(NSUInteger\)index is not showing selection view? [\#133](https://github.com/Jawbone/JBChartView/issues/133)
- Exception thrown on setState: [\#132](https://github.com/Jawbone/JBChartView/issues/132)
- X and Y scale and reference values [\#131](https://github.com/Jawbone/JBChartView/issues/131)
- Determine x-value of a certain point by a number instead of it's index in the input array? [\#130](https://github.com/Jawbone/JBChartView/issues/130)
- How to accomplish similar didUnselectBarChartView [\#129](https://github.com/Jawbone/JBChartView/issues/129)
- Is posible - scroll chart [\#126](https://github.com/Jawbone/JBChartView/issues/126)
- Crash when vertical value for horizontal at index x less than zero [\#125](https://github.com/Jawbone/JBChartView/issues/125)
- JBBarChartView does not display all the bars [\#124](https://github.com/Jawbone/JBChartView/issues/124)
- "automatically normalized across the entire chart" [\#123](https://github.com/Jawbone/JBChartView/issues/123)
- reloadData in viewDidLayoutSubviews does not trigger didDeselectLineInLineChartView on first selection [\#122](https://github.com/Jawbone/JBChartView/issues/122)
- Question [\#121](https://github.com/Jawbone/JBChartView/issues/121)
- Sublayers not properly resized [\#120](https://github.com/Jawbone/JBChartView/issues/120)
- It will be really cool if "while on tap on line charts dots I can get the dot object do some scale animation" or something? [\#119](https://github.com/Jawbone/JBChartView/issues/119)
- Is there any way I can pass new bar view while user selects particular bar? [\#117](https://github.com/Jawbone/JBChartView/issues/117)
- Typo error in README [\#114](https://github.com/Jawbone/JBChartView/issues/114)
- Dynamic/append values [\#113](https://github.com/Jawbone/JBChartView/issues/113)
- It needs better documentation [\#112](https://github.com/Jawbone/JBChartView/issues/112)
**Merged pull requests:**
- Keep tooltip subviews above line subviews [\#144](https://github.com/Jawbone/JBChartView/pull/144) ([vocaro](https://github.com/vocaro))
- Fix crash and warnings that can occur when a chart line has no data [\#143](https://github.com/Jawbone/JBChartView/pull/143) ([vocaro](https://github.com/vocaro))
- Add automatically generated change log file. [\#142](https://github.com/Jawbone/JBChartView/pull/142) ([skywinder](https://github.com/skywinder))
- Update README.md [\#127](https://github.com/Jawbone/JBChartView/pull/127) ([paal123](https://github.com/paal123))
- Add ability to have the line start or end at any given point [\#116](https://github.com/Jawbone/JBChartView/pull/116) ([sebastianreloaded](https://github.com/sebastianreloaded))
## [v2.8.10](https://github.com/Jawbone/JBChartView/tree/v2.8.10) (2014-09-23)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.8.9...v2.8.10)
## [v2.8.9](https://github.com/Jawbone/JBChartView/tree/v2.8.9) (2014-09-22)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.8.8...v2.8.9)
**Closed issues:**
- JBLineChartView doesn't resize its subviews [\#111](https://github.com/Jawbone/JBChartView/issues/111)
## [v2.8.8](https://github.com/Jawbone/JBChartView/tree/v2.8.8) (2014-09-20)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.8.7...v2.8.8)
**Fixed bugs:**
- iOS 8 warnings [\#110](https://github.com/Jawbone/JBChartView/issues/110)
**Closed issues:**
- Noob level tutorial [\#109](https://github.com/Jawbone/JBChartView/issues/109)
- Data points with uneavenly distributed x-values? [\#108](https://github.com/Jawbone/JBChartView/issues/108)
## [v2.8.7](https://github.com/Jawbone/JBChartView/tree/v2.8.7) (2014-09-09)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.8.6...v2.8.7)
**Implemented enhancements:**
- Add hide custom dot functionality [\#100](https://github.com/Jawbone/JBChartView/issues/100)
- Add footer padding [\#98](https://github.com/Jawbone/JBChartView/issues/98)
- DotView is hidden when inside selected table view cell [\#82](https://github.com/Jawbone/JBChartView/issues/82)
**Closed issues:**
- There should be flexibility to change to touch point to nearest data point so vertical selection view just jumps from one data point to another in JBLineChartView. [\#105](https://github.com/Jawbone/JBChartView/issues/105)
- barWidth Method and barPadding property should be in JBBarChartView header file. [\#104](https://github.com/Jawbone/JBChartView/issues/104)
- Why minimum and maximum should be positive? [\#102](https://github.com/Jawbone/JBChartView/issues/102)
**Merged pull requests:**
- iOS Framework Support [\#107](https://github.com/Jawbone/JBChartView/pull/107) ([thefirstnikhil](https://github.com/thefirstnikhil))
- Only call `numberOfLinesInLineChartView:` once per loop. [\#106](https://github.com/Jawbone/JBChartView/pull/106) ([eventualbuddha](https://github.com/eventualbuddha))
## [v2.8.6](https://github.com/Jawbone/JBChartView/tree/v2.8.6) (2014-08-29)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.8.5...v2.8.6)
## [v2.8.5](https://github.com/Jawbone/JBChartView/tree/v2.8.5) (2014-08-28)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.8.4...v2.8.5)
**Implemented enhancements:**
- Invert option for bar charts [\#97](https://github.com/Jawbone/JBChartView/issues/97)
## [v2.8.4](https://github.com/Jawbone/JBChartView/tree/v2.8.4) (2014-08-27)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.8.3...v2.8.4)
## [v2.8.3](https://github.com/Jawbone/JBChartView/tree/v2.8.3) (2014-08-26)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.8.2...v2.8.3)
**Implemented enhancements:**
- return type of barPaddingForBarChartView: [\#93](https://github.com/Jawbone/JBChartView/issues/93)
- Custom dot functionality [\#92](https://github.com/Jawbone/JBChartView/issues/92)
## [v2.8.2](https://github.com/Jawbone/JBChartView/tree/v2.8.2) (2014-08-26)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.8.1...v2.8.2)
**Fixed bugs:**
- Selection view width should equal bar width [\#96](https://github.com/Jawbone/JBChartView/issues/96)
**Closed issues:**
- Changing dot radius in dotRadiusForLineAtLineIndex has no effect [\#95](https://github.com/Jawbone/JBChartView/issues/95)
## [v2.8.1](https://github.com/Jawbone/JBChartView/tree/v2.8.1) (2014-08-23)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.8.0...v2.8.1)
## [v2.8.0](https://github.com/Jawbone/JBChartView/tree/v2.8.0) (2014-08-15)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.7.4...v2.8.0)
**Closed issues:**
- Don't bring selection view to front with line view [\#89](https://github.com/Jawbone/JBChartView/issues/89)
**Merged pull requests:**
- Add per-line vertical selection color support. [\#90](https://github.com/Jawbone/JBChartView/pull/90) ([mszaro](https://github.com/mszaro))
## [v2.7.4](https://github.com/Jawbone/JBChartView/tree/v2.7.4) (2014-08-15)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.7.3...v2.7.4)
**Implemented enhancements:**
- Not able to create Y-Axis labels or background grid [\#20](https://github.com/Jawbone/JBChartView/issues/20)
**Closed issues:**
- \[Enhancement\] Provide an option to disable Y-axis normalization for line graphs [\#88](https://github.com/Jawbone/JBChartView/issues/88)
- Add left padding to the graph for y-axis labels [\#87](https://github.com/Jawbone/JBChartView/issues/87)
- Error Protocol not implemented [\#86](https://github.com/Jawbone/JBChartView/issues/86)
- What if I want to animate the LineChartView progression? [\#85](https://github.com/Jawbone/JBChartView/issues/85)
- Enabling smooth lines in line chart view results in line graph clipping \(Out of bounds\)? [\#83](https://github.com/Jawbone/JBChartView/issues/83)
## [v2.7.3](https://github.com/Jawbone/JBChartView/tree/v2.7.3) (2014-08-07)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.7.2...v2.7.3)
**Closed issues:**
- Can I animate bar charts? [\#79](https://github.com/Jawbone/JBChartView/issues/79)
- Create generic dataSource and delegate for extensibility. [\#78](https://github.com/Jawbone/JBChartView/issues/78)
## [v2.7.2](https://github.com/Jawbone/JBChartView/tree/v2.7.2) (2014-08-04)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.7.1...v2.7.2)
## [v2.7.1](https://github.com/Jawbone/JBChartView/tree/v2.7.1) (2014-08-04)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.7.0...v2.7.1)
**Closed issues:**
- Typo in JBBarChartView.h [\#77](https://github.com/Jawbone/JBChartView/issues/77)
- Refactor datasource and delegate functions [\#76](https://github.com/Jawbone/JBChartView/issues/76)
## [v2.7.0](https://github.com/Jawbone/JBChartView/tree/v2.7.0) (2014-08-02)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.6.3...v2.7.0)
**Closed issues:**
- Incorrect padding on line widths [\#75](https://github.com/Jawbone/JBChartView/issues/75)
## [v2.6.3](https://github.com/Jawbone/JBChartView/tree/v2.6.3) (2014-07-31)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.6.2...v2.6.3)
## [v2.6.2](https://github.com/Jawbone/JBChartView/tree/v2.6.2) (2014-07-25)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.6.1...v2.6.2)
## [v2.6.1](https://github.com/Jawbone/JBChartView/tree/v2.6.1) (2014-07-25)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.6.0...v2.6.1)
**Merged pull requests:**
- iOS 6 support [\#74](https://github.com/Jawbone/JBChartView/pull/74) ([luosheng](https://github.com/luosheng))
## [v2.6.0](https://github.com/Jawbone/JBChartView/tree/v2.6.0) (2014-07-24)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.5.5...v2.6.0)
**Closed issues:**
- Allow setting views for lines as well as bars [\#73](https://github.com/Jawbone/JBChartView/issues/73)
- Requires iOS 7 or later [\#72](https://github.com/Jawbone/JBChartView/issues/72)
- How to Know the x,width of each bar [\#70](https://github.com/Jawbone/JBChartView/issues/70)
- Multiple y-axis [\#69](https://github.com/Jawbone/JBChartView/issues/69)
- NSInternalInconsistencyException - JBLineChartView // dataSource must implement [\#68](https://github.com/Jawbone/JBChartView/issues/68)
- Zoom and scrolling? \(Question\) [\#65](https://github.com/Jawbone/JBChartView/issues/65)
- Support for missing data points rather than going to 0? [\#63](https://github.com/Jawbone/JBChartView/issues/63)
- Interesting behavior 'barViewAtIndex' and 'colorForBarViewAtIndex'. [\#62](https://github.com/Jawbone/JBChartView/issues/62)
- In LineChart x-axis, splits into more numbers and not able view x-axis last point [\#60](https://github.com/Jawbone/JBChartView/issues/60)
- Overlay more than 1 chart? [\#59](https://github.com/Jawbone/JBChartView/issues/59)
- Footer Views - Can they be perpendicular to the x-axis [\#58](https://github.com/Jawbone/JBChartView/issues/58)
**Merged pull requests:**
- Fill Color on Line Chart [\#71](https://github.com/Jawbone/JBChartView/pull/71) ([legranddamien](https://github.com/legranddamien))
- Added documentation for usage in a Swift project [\#67](https://github.com/Jawbone/JBChartView/pull/67) ([jonparker](https://github.com/jonparker))
## [v2.5.5](https://github.com/Jawbone/JBChartView/tree/v2.5.5) (2014-05-14)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.5.4...v2.5.5)
**Implemented enhancements:**
- Ability to draw lines with negative values [\#51](https://github.com/Jawbone/JBChartView/issues/51)
**Closed issues:**
- How to adjust selected bar height for LineChart in demo project [\#56](https://github.com/Jawbone/JBChartView/issues/56)
- Line Chart Collapse Animation Changed? [\#54](https://github.com/Jawbone/JBChartView/issues/54)
**Merged pull requests:**
- Fixed barView's frame. [\#57](https://github.com/Jawbone/JBChartView/pull/57) ([pala](https://github.com/pala))
- Update sample code in readme [\#55](https://github.com/Jawbone/JBChartView/pull/55) ([pala](https://github.com/pala))
## [v2.5.4](https://github.com/Jawbone/JBChartView/tree/v2.5.4) (2014-05-07)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.5.3...v2.5.4)
**Merged pull requests:**
- Add delegate method barChartView:colorForBarViewAtIndex: to JBBarChartViewDataSource [\#53](https://github.com/Jawbone/JBChartView/pull/53) ([skywinder](https://github.com/skywinder))
- Compiling warrnings and typos [\#52](https://github.com/Jawbone/JBChartView/pull/52) ([skywinder](https://github.com/skywinder))
## [v2.5.3](https://github.com/Jawbone/JBChartView/tree/v2.5.3) (2014-05-06)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.5.2...v2.5.3)
## [v2.5.2](https://github.com/Jawbone/JBChartView/tree/v2.5.2) (2014-05-06)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.5.1...v2.5.2)
## [v2.5.1](https://github.com/Jawbone/JBChartView/tree/v2.5.1) (2014-05-05)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.5.0...v2.5.1)
**Closed issues:**
- non-evenly distributed plots [\#50](https://github.com/Jawbone/JBChartView/issues/50)
- Using minimum of 0 as default [\#48](https://github.com/Jawbone/JBChartView/issues/48)
## [v2.5.0](https://github.com/Jawbone/JBChartView/tree/v2.5.0) (2014-05-04)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.4.3...v2.5.0)
## [v2.4.3](https://github.com/Jawbone/JBChartView/tree/v2.4.3) (2014-05-04)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.4.2...v2.4.3)
**Closed issues:**
- Bars not drawn when all have the same height [\#47](https://github.com/Jawbone/JBChartView/issues/47)
- Moving podspec to root [\#46](https://github.com/Jawbone/JBChartView/issues/46)
**Merged pull requests:**
- fixed typo, renamed mininum -\> minimum [\#49](https://github.com/Jawbone/JBChartView/pull/49) ([simonnickel](https://github.com/simonnickel))
## [v2.4.2](https://github.com/Jawbone/JBChartView/tree/v2.4.2) (2014-05-01)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.4.1...v2.4.2)
## [v2.4.1](https://github.com/Jawbone/JBChartView/tree/v2.4.1) (2014-04-30)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.4.0...v2.4.1)
**Implemented enhancements:**
- Curved line charts [\#23](https://github.com/Jawbone/JBChartView/issues/23)
**Closed issues:**
- JBChartView demo footerview problem [\#44](https://github.com/Jawbone/JBChartView/issues/44)
**Merged pull requests:**
- Smooth curve fix [\#45](https://github.com/Jawbone/JBChartView/pull/45) ([ktran03](https://github.com/ktran03))
## [v2.4.0](https://github.com/Jawbone/JBChartView/tree/v2.4.0) (2014-04-28)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.3.0...v2.4.0)
**Closed issues:**
- Aligning X-axis, padding? [\#43](https://github.com/Jawbone/JBChartView/issues/43)
- `JBLineChartFooterView` Value Marks are Inaccurate [\#41](https://github.com/Jawbone/JBChartView/issues/41)
**Merged pull requests:**
- smooth curve using bezierpath [\#39](https://github.com/Jawbone/JBChartView/pull/39) ([ktran03](https://github.com/ktran03))
## [v2.3.0](https://github.com/Jawbone/JBChartView/tree/v2.3.0) (2014-04-18)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.2.0...v2.3.0)
**Closed issues:**
- Crash, lineChartView "must implement numberOfPointsInLineChartView" ? [\#38](https://github.com/Jawbone/JBChartView/issues/38)
## [v2.2.0](https://github.com/Jawbone/JBChartView/tree/v2.2.0) (2014-04-14)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.1.6...v2.2.0)
**Closed issues:**
- Typo in readme? [\#36](https://github.com/Jawbone/JBChartView/issues/36)
- Nav bar background remains black [\#35](https://github.com/Jawbone/JBChartView/issues/35)
**Merged pull requests:**
- Added delegate method to configure the width of the vertical selection bar in a line chart. [\#37](https://github.com/Jawbone/JBChartView/pull/37) ([ghost](https://github.com/ghost))
## [v2.1.6](https://github.com/Jawbone/JBChartView/tree/v2.1.6) (2014-04-11)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.1.5...v2.1.6)
**Closed issues:**
- `showsLineSelection` Does Nothing [\#33](https://github.com/Jawbone/JBChartView/issues/33)
- cocoapods [\#31](https://github.com/Jawbone/JBChartView/issues/31)
## [v2.1.5](https://github.com/Jawbone/JBChartView/tree/v2.1.5) (2014-04-10)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.1.4...v2.1.5)
**Merged pull requests:**
- JBChartView: needs initWithCoder initializer for inflation from a xib [\#30](https://github.com/Jawbone/JBChartView/pull/30) ([gumbypp](https://github.com/gumbypp))
## [v2.1.4](https://github.com/Jawbone/JBChartView/tree/v2.1.4) (2014-04-10)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.1.3...v2.1.4)
**Closed issues:**
- Stach bars? [\#29](https://github.com/Jawbone/JBChartView/issues/29)
- Problem with Bar Height [\#28](https://github.com/Jawbone/JBChartView/issues/28)
- Selection does not work without Auto Layout in iPhone 3.5" [\#27](https://github.com/Jawbone/JBChartView/issues/27)
## [v2.1.3](https://github.com/Jawbone/JBChartView/tree/v2.1.3) (2014-04-03)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.1.2...v2.1.3)
## [v2.1.2](https://github.com/Jawbone/JBChartView/tree/v2.1.2) (2014-04-02)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.1.1...v2.1.2)
## [v2.1.1](https://github.com/Jawbone/JBChartView/tree/v2.1.1) (2014-04-02)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.1.0...v2.1.1)
**Closed issues:**
- representing negative values [\#26](https://github.com/Jawbone/JBChartView/issues/26)
- Real time [\#25](https://github.com/Jawbone/JBChartView/issues/25)
## [v2.1.0](https://github.com/Jawbone/JBChartView/tree/v2.1.0) (2014-03-31)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.0.2...v2.1.0)
## [v2.0.2](https://github.com/Jawbone/JBChartView/tree/v2.0.2) (2014-03-27)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.0.1...v2.0.2)
**Closed issues:**
- Negative Bars? [\#24](https://github.com/Jawbone/JBChartView/issues/24)
## [v2.0.1](https://github.com/Jawbone/JBChartView/tree/v2.0.1) (2014-03-19)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v2.0.0...v2.0.1)
**Closed issues:**
- NSAssert on bar height in JBBarChartView, \> 0 when it should be \>= [\#22](https://github.com/Jawbone/JBChartView/issues/22)
## [v2.0.0](https://github.com/Jawbone/JBChartView/tree/v2.0.0) (2014-03-19)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v1.1.6...v2.0.0)
**Implemented enhancements:**
- Multiple Lines on chart [\#6](https://github.com/Jawbone/JBChartView/issues/6)
**Closed issues:**
- JBBarChartView Bar Height Problem With Storyboard/Autolayout [\#19](https://github.com/Jawbone/JBChartView/issues/19)
- blank result [\#18](https://github.com/Jawbone/JBChartView/issues/18)
- Bar Highlight Offset Issue [\#17](https://github.com/Jawbone/JBChartView/issues/17)
- Following the tutorial creates an empty/blank view [\#16](https://github.com/Jawbone/JBChartView/issues/16)
**Merged pull requests:**
- Multiple Line Support & Tooltips [\#21](https://github.com/Jawbone/JBChartView/pull/21) ([terryworona](https://github.com/terryworona))
## [v1.1.6](https://github.com/Jawbone/JBChartView/tree/v1.1.6) (2014-03-03)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v1.1.5...v1.1.6)
**Merged pull requests:**
- Added customization for line width [\#15](https://github.com/Jawbone/JBChartView/pull/15) ([kmcbride](https://github.com/kmcbride))
- fix spelling mistake [\#14](https://github.com/Jawbone/JBChartView/pull/14) ([Undo1](https://github.com/Undo1))
## [v1.1.5](https://github.com/Jawbone/JBChartView/tree/v1.1.5) (2014-02-12)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v1.1.4...v1.1.5)
## [v1.1.4](https://github.com/Jawbone/JBChartView/tree/v1.1.4) (2014-02-06)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v1.1.3...v1.1.4)
**Closed issues:**
- What about ios6 [\#13](https://github.com/Jawbone/JBChartView/issues/13)
- Could the Bar Chart data be nil ? [\#12](https://github.com/Jawbone/JBChartView/issues/12)
## [v1.1.3](https://github.com/Jawbone/JBChartView/tree/v1.1.3) (2014-01-06)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v1.1.2...v1.1.3)
**Closed issues:**
- heightForIndex should return CGFloat instead of NSInteger [\#9](https://github.com/Jawbone/JBChartView/issues/9)
**Merged pull requests:**
- Fixes small typos in README [\#11](https://github.com/Jawbone/JBChartView/pull/11) ([sampage](https://github.com/sampage))
## [v1.1.2](https://github.com/Jawbone/JBChartView/tree/v1.1.2) (2014-01-03)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v1.1.1...v1.1.2)
## [v1.1.1](https://github.com/Jawbone/JBChartView/tree/v1.1.1) (2014-01-02)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v1.1.0...v1.1.1)
**Closed issues:**
- reloadData is not reducing height of other bars [\#7](https://github.com/Jawbone/JBChartView/issues/7)
- Add barViewAtIndex: to datasource [\#5](https://github.com/Jawbone/JBChartView/issues/5)
**Merged pull requests:**
- Reset cached max height on data reload Fixes \#7 [\#8](https://github.com/Jawbone/JBChartView/pull/8) ([l4u](https://github.com/l4u))
## [v1.1.0](https://github.com/Jawbone/JBChartView/tree/v1.1.0) (2013-12-26)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v1.0.3...v1.1.0)
## [v1.0.3](https://github.com/Jawbone/JBChartView/tree/v1.0.3) (2013-12-23)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v1.0.2...v1.0.3)
**Closed issues:**
- Single press on bar [\#3](https://github.com/Jawbone/JBChartView/issues/3)
## [v1.0.2](https://github.com/Jawbone/JBChartView/tree/v1.0.2) (2013-12-17)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v1.0.1...v1.0.2)
## [v1.0.1](https://github.com/Jawbone/JBChartView/tree/v1.0.1) (2013-12-15)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/v1.0...v1.0.1)
**Merged pull requests:**
- If there is no footer view, bars won't be added to the chart. [\#2](https://github.com/Jawbone/JBChartView/pull/2) ([joelkraut](https://github.com/joelkraut))
## [v1.0](https://github.com/Jawbone/JBChartView/tree/v1.0) (2013-12-11)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/0.2.0...v1.0)
**Merged pull requests:**
- JBChartViewDemo and JBChartView [\#1](https://github.com/Jawbone/JBChartView/pull/1) ([terryworona](https://github.com/terryworona))
## [0.2.0](https://github.com/Jawbone/JBChartView/tree/0.2.0) (2013-08-20)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/1.0...0.2.0)
## [1.0](https://github.com/Jawbone/JBChartView/tree/1.0) (2012-04-23)
[Full Changelog](https://github.com/Jawbone/JBChartView/compare/1.0.0...1.0)
## [1.0.0](https://github.com/Jawbone/JBChartView/tree/1.0.0) (2012-04-23)
\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*
+123 -76
View File
@@ -9,108 +9,155 @@
// Views
#import "JBChartView.h"
@protocol JBBarChartViewDelegate;
@protocol JBBarChartViewDataSource;
@class JBBarChartView;
@interface JBBarChartView : JBChartView
@property (nonatomic, weak) id<JBBarChartViewDelegate> delegate;
@property (nonatomic, weak) id<JBBarChartViewDataSource> dataSource;
/**
* If showsSelection is YES, a vertical highlight will overlayed on a bar during touch events.
*
* Default: YES
*/
@property (nonatomic, assign) BOOL showsSelection;
@end
@protocol JBBarChartViewDelegate <NSObject>
@required
/**
* Height for a bar at a given index (left to right). There is no ceiling on the the height;
* the chart will automatically normalize all values between the overal min and max heights.
*
* @param barChartView The origin chart
* @param index The 0-based index of a given bar (left to right, x-axis)
*
* @return The y-axis height of the supplied bar index (x-axis)
*/
- (CGFloat)barChartView:(JBBarChartView *)barChartView heightForBarViewAtAtIndex:(NSInteger)index;
@optional
/**
* Occurs when a touch gesture event occurs on a given bar. The chart must be expanded, showsSelection must be YES,
* and the selection must occur within the bounds of the chart.
*
* @param barChartView The origin chart
* @param index The 0-based index of a given bar (left to right, x-axis)
*/
- (void)barChartView:(JBBarChartView *)barChartView didSelectBarAtIndex:(NSInteger)index;
/**
* Occurs when selection ends by either ending a touch event or selecting an area that is outside the view's bounds.
* For selection start events, see: didSelectBarAtIndex...
*
* @param barChartView The origin chart
* @param index The 0-based index of a given bar. Index will be -1 if the touch ends outside of the view's bounds.
*/
- (void)barChartView:(JBBarChartView *)barChartView didUnselectBarAtIndex:(NSInteger)index;
@end
@protocol JBBarChartViewDataSource <NSObject>
@protocol JBBarChartViewDataSource <JBChartViewDataSource>
@required
/**
* The number of bars in a given bar chart is the number of vertical views shown along the x-axis.
*
* @param barChartView The origin chart
* @param barChartView The bar chart object requesting this information.
*
* @return Number of bars in the given chart, displayed horizontally along the chart's x-axis.
*/
- (NSInteger)numberOfBarsInBarChartView:(JBBarChartView *)barChartView;
- (NSUInteger)numberOfBarsInBarChartView:(JBBarChartView *)barChartView;
@optional
/**
* Horizontal padding between bars.
*
* Default: 'best-guess' algorithm based on the the total number of bars and width of the chart.
*
* @param barChartView The origin chart
*
* @return Horizontal width (in pixels) between each bar.
*/
- (NSInteger)barPaddingForBarChartView:(JBBarChartView *)barChartView;
/**
* A UIView subclass representing the bar at a particular index.
*
* Default: solid black UIView
* Default: solid black UIView.
*
* @param barChartView The origin chart
* @param index The 0-based index of a given bar (left to right, x-axis)
* @param barChartView The bar chart object requesting this information.
* @param index The 0-based index of a given bar (left to right, x-axis).
*
* @return A UIView subclass. The view will automatically be resized by the chart during creation (ie. no need to set the frame).
*/
- (UIView *)barViewForBarChartView:(JBBarChartView *)barChartView atIndex:(NSInteger)index;
- (UIView *)barChartView:(JBBarChartView *)barChartView barViewAtIndex:(NSUInteger)index;
@end
@protocol JBBarChartViewDelegate <JBChartViewDelegate>
@required
/**
* The selection color to be overlayed on a bar during touch events.
* The color is automically faded to transparent (vertically).
* Height for a bar at a given index (left to right). There is no ceiling on the the height;
* the chart will automatically normalize all values between the overal min and max heights.
*
* Default: white color (faded to transparent)
* @param barChartView The bar chart object requesting this information.
* @param index The 0-based index of a given bar (left to right, x-axis).
*
* @param barChartView The origin chart
* @return The y-axis height of the supplied bar index (x-axis)
*/
- (CGFloat)barChartView:(JBBarChartView *)barChartView heightForBarViewAtIndex:(NSUInteger)index;
@optional
/**
* Occurs when a touch gesture event occurs on a given bar (chart must be expanded).
* and the selection must occur within the bounds of the chart.
*
* @param barChartView A bar chart object informing the delegate about the new selection.
* @param index The 0-based index of a given bar (left to right, x-axis).
* @param touchPoint The touch point in relation to the chart's bounds (excludes footer and header).
*/
- (void)barChartView:(JBBarChartView *)barChartView didSelectBarAtIndex:(NSUInteger)index touchPoint:(CGPoint)touchPoint;
- (void)barChartView:(JBBarChartView *)barChartView didSelectBarAtIndex:(NSUInteger)index;
/**
* Occurs when selection ends by either ending a touch event or selecting an area that is outside the view's bounds.
* For selection start events, see: didSelectBarAtIndex...
*
* @param barChartView A bar chart object informing the delegate about the deselection.
*/
- (void)didDeselectBarChartView:(JBBarChartView *)barChartView;
/**
* If you already implement barChartView:barViewAtIndex: delegate - this method has no effect.
* If a custom UIView isn't supplied, a flat bar will be made automatically (default color black).
*
* Default: black color.
*
* @param barChartView The bar chart object requesting this information.
* @param index The 0-based index of a given bar (left to right, x-axis).
*
* @return The color to be used to color a bar in the chart.
*/
- (UIColor *)barChartView:(JBBarChartView *)barChartView colorForBarViewAtIndex:(NSUInteger)index;
/**
* If you already implement barChartView:barViewAtIndex: delegate - this method has no effect.
* If a custom UIView isn't supplied and barChartView:colorForBarViewAtIndex: isn't implemented, then
* a gradient layer may be supplied to be used across all bars within the chart.
*
* Default: black color.
*
* @param barChartView The bar chart object requesting this information.
*
* @return The gradient layer to be used as a mask over all bars within the chart.
*/
- (CAGradientLayer *)barGradientForBarChartView:(JBBarChartView *)barChartView;
/**
* The selection color to be overlayed on a bar during touch events.
* The color is automatically faded to transparent (vertically). The property showsVerticalSelection
* must be YES for the color to apply.
*
* Default: white color (faded to transparent).
*
* @param barChartView The bar chart object requesting this information.
*
* @return The color to be used on each bar selection.
*/
- (UIColor *)selectionBarColorForBarChartView:(JBBarChartView *)barChartView;
- (UIColor *)barSelectionColorForBarChartView:(JBBarChartView *)barChartView;
/**
* Horizontal padding between bars.
*
* Default: 'best-guess' algorithm based on the the total number of bars and width of the chart.
*
* @param barChartView The bar chart object requesting this information.
*
* @return Horizontal width (in pixels) between each bar.
*/
- (CGFloat)barPaddingForBarChartView:(JBBarChartView *)barChartView;
@end
@interface JBBarChartView : JBChartView
@property (nonatomic, weak) id<JBBarChartViewDataSource> dataSource;
@property (nonatomic, weak) id<JBBarChartViewDelegate> delegate;
/**
* Vertical highlight overlayed on bar during touch events.
*
* Default: YES.
*/
@property (nonatomic, assign) BOOL showsVerticalSelection;
/*
* Bars can be (vertically) positoned top to bottom instead of bottom up.
* If this property is set to YES, both the bar and the selection view will be inverted.
* For the inverted orientation to take effect, reloadData must be called.
*
* Default: NO.
*/
@property (nonatomic, assign, getter=isInverted) BOOL inverted;
/**
* The bar view at a particular index.
*
* Default: nil.
*
* @param index The 0-based index of a given bar (left to right, x-axis).
*
* @return The UIView representing the bar view at a given index or nil if the index is out of range.
*/
- (UIView *)barViewAtIndex:(NSUInteger)index;
@end
+507 -185
View File
@@ -9,42 +9,77 @@
#import "JBBarChartView.h"
// Numerics
CGFloat const kJBBarChartViewBarBasePaddingMutliplier = 50.0f;
CGFloat const kJBBarChartViewUndefinedMaxHeight = -1.0f;
CGFloat const kJBBarChartViewStateAnimationDuration = 0.05f;
CGFloat const kJBBarChartViewPopOffset = 10.0f; // used to offset bars for 'pop' animations
NSInteger const kJBBarChartViewUndefinedBarIndex = -1;
CGFloat static const kJBBarChartViewBarBasePaddingMutliplier = 50.0f;
CGFloat static const kJBBarChartViewUndefinedCachedHeight = -1.0f;
CGFloat static const kJBBarChartViewStateAnimationDuration = 0.05f;
CGFloat static const kJBBarChartViewStatePopOffset = 10.0f;
NSInteger static const kJBBarChartViewUndefinedBarIndex = -1;
// Colors (JBChartView)
static UIColor *kJBBarChartViewDefaultBarColor = nil;
@interface JBBarChartView ()
@interface JBChartView (Private)
- (BOOL)hasMaximumValue;
- (BOOL)hasMinimumValue;
@end
@protocol JBGradientBarViewDelegate;
@interface JBGradientBarView: UIView
@property (nonatomic, strong) CAGradientLayer *gradientLayer;
@property (nonatomic, weak) id<JBGradientBarViewDelegate> delegate;
// Initialization
- (void)construct;
@end
@protocol JBGradientBarViewDelegate <NSObject>
@optional
- (CGRect)chartViewBoundsForGradientBarView:(JBGradientBarView *)gradientBarView;
@end
@interface JBBarChartView () <JBGradientBarViewDelegate>
@property (nonatomic, strong) NSDictionary *chartDataDictionary; // key = column, value = height
@property (nonatomic, strong) NSArray *barViews;
@property (nonatomic, strong) NSArray *cachedBarViewHeights;
@property (nonatomic, assign) CGFloat barPadding;
@property (nonatomic, assign) CGFloat cachedMaxHeight;
@property (nonatomic, strong) JBChartSelectionView *selectionView;
@property (nonatomic, assign) BOOL selectionViewVisible;
@property (nonatomic, assign) CGFloat cachedMinHeight;
@property (nonatomic, strong) JBChartVerticalSelectionView *verticalSelectionView;
@property (nonatomic, assign) BOOL verticalSelectionViewVisible;
// Initialization
- (void)construct;
// View quick accessors
- (CGFloat)availableHeight;
- (CGFloat)normalizedHeightForRawHeight:(NSNumber*)rawHeight;
- (CGFloat)maxHeight;
- (CGFloat)minHeight;
- (CGFloat)normalizedHeightForRawHeight:(NSNumber *)rawHeight;
- (CGFloat)barWidth;
// Touch helpers
- (NSInteger)barViewIndexForPoint:(CGPoint)point;
- (UIView *)barViewForForPoint:(CGPoint)point;
- (void)touchesBeganOrMovedWithTouches:(NSSet *)touches;
- (void)touchesEndedOrCancelledWithTouches:(NSSet *)touches;
// Setters
- (void)setSelectionViewVisible:(BOOL)selectionViewVisible animated:(BOOL)animated;
- (void)setVerticalSelectionViewVisible:(BOOL)verticalSelectionViewVisible animated:(BOOL)animated;
@end
@implementation JBBarChartView
@dynamic dataSource;
@dynamic delegate;
#pragma mark - Alloc/Init
+ (void)initialize
@@ -55,18 +90,43 @@ static UIColor *kJBBarChartViewDefaultBarColor = nil;
}
}
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self)
{
[self construct];
}
return self;
}
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
self.clipsToBounds = YES;
_showsSelection = YES;
_cachedMaxHeight = kJBBarChartViewUndefinedMaxHeight;
[self construct];
}
return self;
}
- (id)init
{
self = [super init];
if (self)
{
[self construct];
}
return self;
}
- (void)construct
{
_showsVerticalSelection = YES;
_cachedMinHeight = kJBBarChartViewUndefinedCachedHeight;
_cachedMaxHeight = kJBBarChartViewUndefinedCachedHeight;
}
#pragma mark - Memory Management
- (void)dealloc
@@ -79,8 +139,9 @@ static UIColor *kJBBarChartViewDefaultBarColor = nil;
- (void)reloadData
{
// reset cached max height
self.cachedMaxHeight = kJBBarChartViewUndefinedMaxHeight;
self.cachedMinHeight = kJBBarChartViewUndefinedCachedHeight;
self.cachedMaxHeight = kJBBarChartViewUndefinedCachedHeight;
/*
* The data collection holds all position information:
* constructed via datasource and delegate functions
@@ -88,15 +149,17 @@ static UIColor *kJBBarChartViewDefaultBarColor = nil;
dispatch_block_t createDataDictionaries = ^{
// Grab the count
NSAssert([self.dataSource respondsToSelector:@selector(numberOfBarsInBarChartView:)], @"JBBarChartView // datasource must implement - (NSInteger)numberOfBarsInBarChartView:(JBBarChartView *)barChartView");
NSInteger dataCount = [self.dataSource numberOfBarsInBarChartView:self];
NSAssert([self.dataSource respondsToSelector:@selector(numberOfBarsInBarChartView:)], @"JBBarChartView // datasource must implement - (NSUInteger)numberOfBarsInBarChartView:(JBBarChartView *)barChartView");
NSUInteger dataCount = [self.dataSource numberOfBarsInBarChartView:self];
// Build up the data collection
NSAssert([self.delegate respondsToSelector:@selector(barChartView:heightForBarViewAtAtIndex:)], @"JBBarChartView // delegate must implement - (NSInteger)barChartView:(JBBarChartView *)barChartView heightForBarViewAtAtIndex:(NSInteger)index");
NSAssert([self.delegate respondsToSelector:@selector(barChartView:heightForBarViewAtIndex:)], @"JBBarChartView // delegate must implement - (CGFloat)barChartView:(JBBarChartView *)barChartView heightForBarViewAtIndex:(NSUInteger)index");
NSMutableDictionary *dataDictionary = [NSMutableDictionary dictionary];
for (NSInteger index=0; index<dataCount; index++)
for (NSUInteger index=0; index<dataCount; index++)
{
[dataDictionary setObject:[NSNumber numberWithFloat:[self.delegate barChartView:self heightForBarViewAtAtIndex:index]] forKey:[NSNumber numberWithInt:(int)index]];
CGFloat height = [self.delegate barChartView:self heightForBarViewAtIndex:index];
NSAssert(height >= 0, @"JBBarChartView // datasource function - (CGFloat)barChartView:(JBBarChartView *)barChartView heightForBarViewAtIndex:(NSUInteger)index must return a CGFloat >= 0");
[dataDictionary setObject:[NSNumber numberWithFloat:height] forKey:[NSNumber numberWithInt:(int)index]];
}
self.chartDataDictionary = [NSDictionary dictionaryWithDictionary:dataDictionary];
};
@@ -105,17 +168,17 @@ static UIColor *kJBBarChartViewDefaultBarColor = nil;
* Determines the padding between bars as a function of # of bars
*/
dispatch_block_t createBarPadding = ^{
if ([self.dataSource respondsToSelector:@selector(barPaddingForBarChartView:)])
if ([self.delegate respondsToSelector:@selector(barPaddingForBarChartView:)])
{
self.barPadding = [self.dataSource barPaddingForBarChartView:self];
self.barPadding = [self.delegate barPaddingForBarChartView:self];
}
else
{
NSInteger totalBars = [[self.chartDataDictionary allKeys] count];
NSUInteger totalBars = [[self.chartDataDictionary allKeys] count];
self.barPadding = (1/(float)totalBars) * kJBBarChartViewBarBasePaddingMutliplier;
}
};
/*
* Creates a new bar graph view using the previously calculated data model
*/
@@ -127,24 +190,57 @@ static UIColor *kJBBarChartViewDefaultBarColor = nil;
[barView removeFromSuperview];
}
self.cachedBarViewHeights = nil;
CGFloat xOffset = 0;
NSInteger index = 0;
NSUInteger index = 0;
NSMutableArray *mutableBarViews = [NSMutableArray array];
NSMutableArray *mutableCachedBarViewHeights = [NSMutableArray array];
for (NSNumber *key in [[self.chartDataDictionary allKeys] sortedArrayUsingSelector:@selector(compare:)])
{
UIView *barView = nil; // since all bars are visible at once, no need to cache this view
if ([self.dataSource respondsToSelector:@selector(barViewForBarChartView:atIndex:)])
{
barView = [self.dataSource barViewForBarChartView:self atIndex:index];
}
else
{
barView = [[UIView alloc] init];
barView.backgroundColor = kJBBarChartViewDefaultBarColor;
}
CGFloat height = [self normalizedHeightForRawHeight:[self.chartDataDictionary objectForKey:key]];
barView.frame = CGRectMake(xOffset, self.bounds.size.height - height - self.footerView.frame.size.height + self.headerPadding, [self barWidth], height + kJBBarChartViewPopOffset - self.headerPadding);
[mutableBarViews addObject:barView];
UIView *barView = nil;
{
// Custom bar
if ([self.dataSource respondsToSelector:@selector(barChartView:barViewAtIndex:)])
{
UIView *customBarView = [self.dataSource barChartView:self barViewAtIndex:index];
if (customBarView != nil)
{
barView = customBarView;
}
}
// Color bar
if ([self.delegate respondsToSelector:@selector(barChartView:colorForBarViewAtIndex:)] && barView == nil)
{
UIColor *backgroundColor = [self.delegate barChartView:self colorForBarViewAtIndex:index];
if (backgroundColor != nil)
{
barView = [[UIView alloc] init];
barView.backgroundColor = backgroundColor;
}
}
// Gradient
if ([self.delegate respondsToSelector:@selector(barGradientForBarChartView:)] && barView == nil)
{
CAGradientLayer *gradientLayer = [self.delegate barGradientForBarChartView:self];
if (gradientLayer != nil)
{
barView = [[JBGradientBarView alloc] init];
((JBGradientBarView *)barView).delegate = self;
((JBGradientBarView *)barView).gradientLayer = gradientLayer;
}
}
// Default
if (barView == nil)
{
barView = [[UIView alloc] init];
barView.backgroundColor = kJBBarChartViewDefaultBarColor;
}
}
barView.tag = index;
// Add new bar
if (self.footerView)
@@ -155,11 +251,17 @@ static UIColor *kJBBarChartViewDefaultBarColor = nil;
{
[self addSubview:barView];
}
CGFloat height = [self normalizedHeightForRawHeight:[self.chartDataDictionary objectForKey:key]];
barView.frame = CGRectMake(xOffset, self.bounds.size.height - height - self.footerView.frame.size.height, [self barWidth], height);
[mutableBarViews addObject:barView];
[mutableCachedBarViewHeights addObject:[NSNumber numberWithFloat:height]];
xOffset += ([self barWidth] + self.barPadding);
index++;
}
self.barViews = [NSArray arrayWithArray:mutableBarViews];
self.cachedBarViewHeights = [NSArray arrayWithArray:mutableCachedBarViewHeights];
};
/*
@@ -168,28 +270,51 @@ static UIColor *kJBBarChartViewDefaultBarColor = nil;
dispatch_block_t createSelectionView = ^{
// Remove old selection bar
if (self.selectionView)
if (self.verticalSelectionView)
{
[self.selectionView removeFromSuperview];
self.selectionView = nil;
[self.verticalSelectionView removeFromSuperview];
self.verticalSelectionView = nil;
}
self.selectionView = [[JBChartSelectionView alloc] initWithFrame:CGRectMake(0, 0, [self barWidth], self.bounds.size.height)];
self.selectionView.alpha = 0.0;
if ([self.dataSource respondsToSelector:@selector(selectionBarColorForBarChartView:)])
CGFloat verticalSelectionViewHeight = self.bounds.size.height - self.headerView.frame.size.height - self.footerView.frame.size.height - self.headerPadding - self.footerPadding;
if ([self.dataSource respondsToSelector:@selector(shouldExtendSelectionViewIntoHeaderPaddingForChartView:)])
{
self.selectionView.bgColor = [self.dataSource selectionBarColorForBarChartView:self];
if ([self.dataSource shouldExtendSelectionViewIntoHeaderPaddingForChartView:self])
{
verticalSelectionViewHeight += self.headerPadding;
}
}
if ([self.dataSource respondsToSelector:@selector(shouldExtendSelectionViewIntoFooterPaddingForChartView:)])
{
if ([self.dataSource shouldExtendSelectionViewIntoFooterPaddingForChartView:self])
{
verticalSelectionViewHeight += self.footerPadding;
}
}
self.verticalSelectionView = [[JBChartVerticalSelectionView alloc] initWithFrame:CGRectMake(0, 0, [self barWidth], verticalSelectionViewHeight)];
self.verticalSelectionView.alpha = 0.0;
self.verticalSelectionView.hidden = !self.showsVerticalSelection;
if ([self.delegate respondsToSelector:@selector(barSelectionColorForBarChartView:)])
{
UIColor *selectionViewBackgroundColor = [self.delegate barSelectionColorForBarChartView:self];
NSAssert(selectionViewBackgroundColor != nil, @"JBBarChartView // delegate function - (UIColor *)barSelectionColorForBarChartView:(JBBarChartView *)barChartView must return a non-nil UIColor");
self.verticalSelectionView.bgColor = selectionViewBackgroundColor;
}
// Add new selection bar
if (self.footerView)
{
[self insertSubview:self.selectionView belowSubview:self.footerView];
[self insertSubview:self.verticalSelectionView belowSubview:self.footerView];
}
else
{
[self addSubview:self.selectionView];
[self addSubview:self.verticalSelectionView];
}
self.verticalSelectionView.transform = self.inverted ? CGAffineTransformMakeScale(1.0, -1.0) : CGAffineTransformIdentity;
};
createDataDictionaries();
@@ -197,51 +322,38 @@ static UIColor *kJBBarChartViewDefaultBarColor = nil;
createBars();
createSelectionView();
// Position header and footer
// Position header and footer
self.headerView.frame = CGRectMake(self.bounds.origin.x, self.bounds.origin.y, self.bounds.size.width, self.headerView.frame.size.height);
self.footerView.frame = CGRectMake(self.bounds.origin.x, self.bounds.size.height - self.footerView.frame.size.height, self.bounds.size.width, self.footerView.frame.size.height);
// Refresh state
[self setState:self.state animated:NO force:YES callback:nil];
}
#pragma mark - View Quick Accessors
- (CGFloat)availableHeight
{
return self.bounds.size.height - self.headerView.frame.size.height - self.footerView.frame.size.height - self.headerPadding;
return self.bounds.size.height - self.headerView.frame.size.height - self.footerView.frame.size.height - self.headerPadding - self.footerPadding;
}
- (CGFloat)normalizedHeightForRawHeight:(NSNumber*)rawHeight
- (CGFloat)normalizedHeightForRawHeight:(NSNumber *)rawHeight
{
CGFloat minHeight = [self minHeight];
CGFloat maxHeight = [self maxHeight];
CGFloat minHeight = [self minimumValue];
CGFloat maxHeight = [self maximumValue];
CGFloat value = [rawHeight floatValue];
if ((maxHeight - minHeight) <= 0)
{
return 0;
return [self availableHeight];
}
return ((value - minHeight) / (maxHeight - minHeight)) * [self availableHeight];
}
- (CGFloat)maxHeight
{
if (self.cachedMaxHeight == kJBBarChartViewUndefinedMaxHeight)
{
// max height is max value across all goals and values
NSArray *chartValues = [[[self.chartDataDictionary allValues] arrayByAddingObjectsFromArray:[self.chartDataDictionary allValues]] sortedArrayUsingSelector:@selector(compare:)];
self.cachedMaxHeight = [[chartValues lastObject] floatValue];
}
return self.cachedMaxHeight;
}
- (CGFloat)minHeight
{
return 0;
}
- (CGFloat)barWidth
{
NSInteger barCount = [[self.chartDataDictionary allKeys] count];
NSUInteger barCount = [[self.chartDataDictionary allKeys] count];
if (barCount > 0)
{
CGFloat totalPadding = (barCount - 1) * self.barPadding;
@@ -253,57 +365,120 @@ static UIColor *kJBBarChartViewDefaultBarColor = nil;
#pragma mark - Setters
- (void)setState:(JBChartViewState)state animated:(BOOL)animated callback:(void (^)())callback
- (void)setState:(JBChartViewState)state animated:(BOOL)animated force:(BOOL)force callback:(void (^)())callback
{
[super setState:state animated:animated callback:callback];
[super setState:state animated:animated force:force callback:callback];
__weak JBBarChartView* weakSelf = self;
void (^updateBarView)(UIView *barView, BOOL popBar);
updateBarView = ^(UIView *barView, BOOL popBar) {
if (weakSelf.inverted)
{
if (weakSelf.state == JBChartViewStateExpanded)
{
if (popBar)
{
barView.frame = CGRectMake(barView.frame.origin.x, weakSelf.headerView.frame.size.height + weakSelf.headerPadding, barView.frame.size.width, [[weakSelf.cachedBarViewHeights objectAtIndex:barView.tag] floatValue] + kJBBarChartViewStatePopOffset);
}
else
{
barView.frame = CGRectMake(barView.frame.origin.x, weakSelf.headerView.frame.size.height + weakSelf.headerPadding, barView.frame.size.width, [[weakSelf.cachedBarViewHeights objectAtIndex:barView.tag] floatValue]);
}
}
else if (weakSelf.state == JBChartViewStateCollapsed)
{
if (popBar)
{
barView.frame = CGRectMake(barView.frame.origin.x, weakSelf.headerView.frame.size.height + weakSelf.headerPadding, barView.frame.size.width, [[weakSelf.cachedBarViewHeights objectAtIndex:barView.tag] floatValue] + kJBBarChartViewStatePopOffset);
}
else
{
barView.frame = CGRectMake(barView.frame.origin.x, weakSelf.headerView.frame.size.height + weakSelf.headerPadding, barView.frame.size.width, 0.0f);
}
}
}
else
{
if (weakSelf.state == JBChartViewStateExpanded)
{
if (popBar)
{
barView.frame = CGRectMake(barView.frame.origin.x, weakSelf.bounds.size.height - weakSelf.footerView.frame.size.height - weakSelf.footerPadding - [[weakSelf.cachedBarViewHeights objectAtIndex:barView.tag] floatValue] - kJBBarChartViewStatePopOffset, barView.frame.size.width, [[weakSelf.cachedBarViewHeights objectAtIndex:barView.tag] floatValue] + kJBBarChartViewStatePopOffset);
}
else
{
barView.frame = CGRectMake(barView.frame.origin.x, weakSelf.bounds.size.height - weakSelf.footerView.frame.size.height - weakSelf.footerPadding - [[weakSelf.cachedBarViewHeights objectAtIndex:barView.tag] floatValue], barView.frame.size.width, [[weakSelf.cachedBarViewHeights objectAtIndex:barView.tag] floatValue]);
}
}
else if (weakSelf.state == JBChartViewStateCollapsed)
{
if (popBar)
{
barView.frame = CGRectMake(barView.frame.origin.x, weakSelf.bounds.size.height - weakSelf.footerView.frame.size.height - weakSelf.footerPadding - [[weakSelf.cachedBarViewHeights objectAtIndex:barView.tag] floatValue] - kJBBarChartViewStatePopOffset, barView.frame.size.width, [[weakSelf.cachedBarViewHeights objectAtIndex:barView.tag] floatValue] + kJBBarChartViewStatePopOffset);
}
else
{
barView.frame = CGRectMake(barView.frame.origin.x, weakSelf.bounds.size.height, barView.frame.size.width, 0.0f);
}
}
}
};
dispatch_block_t callbackCopy = [callback copy];
if (animated)
if ([self.barViews count] > 0)
{
CGFloat popOffset = self.bounds.size.height - self.footerView.frame.size.height;
NSInteger index = 0;
for (UIView *barView in self.barViews)
if (animated)
{
[UIView animateWithDuration:kJBBarChartViewStateAnimationDuration delay:(kJBBarChartViewStateAnimationDuration * 0.5) * index options:UIViewAnimationOptionBeginFromCurrentState animations:^{
barView.frame = CGRectMake(barView.frame.origin.x, popOffset - barView.frame.size.height, barView.frame.size.width, barView.frame.size.height);
} completion:^(BOOL finished) {
[UIView animateWithDuration:kJBBarChartViewStateAnimationDuration delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
if (state == JBChartViewStateExpanded)
{
barView.frame = CGRectMake(barView.frame.origin.x, popOffset - barView.frame.size.height + kJBBarChartViewPopOffset, barView.frame.size.width, barView.frame.size.height);
}
else if (state == JBChartViewStateCollapsed)
{
barView.frame = CGRectMake(barView.frame.origin.x, self.bounds.size.height, barView.frame.size.width, barView.frame.size.height);
}
} completion:^(BOOL finished) {
if (index == [self.barViews count] - 1)
{
if (callbackCopy)
{
callbackCopy();
}
}
}];
}];
index++;
dispatch_block_t animationCompletionBlock = ^{
if (callbackCopy)
{
callbackCopy();
}
};
NSUInteger animationDelayIndex = 0;
for (UIView *barView in self.barViews)
{
BOOL lastIndex = ((NSUInteger)barView.tag == [self.barViews count] - 1);
if ([[weakSelf.cachedBarViewHeights objectAtIndex:barView.tag] floatValue] > [self minimumValue])
{
[UIView animateWithDuration:kJBBarChartViewStateAnimationDuration delay:(kJBBarChartViewStateAnimationDuration * 0.5) * animationDelayIndex options:UIViewAnimationOptionBeginFromCurrentState animations:^{
updateBarView(barView, YES);
} completion:^(BOOL finished) {
[UIView animateWithDuration:kJBBarChartViewStateAnimationDuration delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
updateBarView(barView, NO);
} completion:^(BOOL lastBarFinished) {
if (lastIndex)
{
animationCompletionBlock();
}
}];
}];
animationDelayIndex++;
}
else if (lastIndex)
{
animationCompletionBlock();
}
}
}
else
{
for (UIView *barView in self.barViews)
{
updateBarView(barView, NO);
}
if (callbackCopy)
{
callbackCopy();
}
}
}
else
{
for (UIView *barView in self.barViews)
{
if (state == JBChartViewStateExpanded)
{
barView.frame = CGRectMake(barView.frame.origin.x, (self.bounds.size.height + kJBBarChartViewPopOffset) - (barView.frame.size.height + self.footerView.frame.size.height), barView.frame.size.width, barView.frame.size.height);
}
else if (state == JBChartViewStateCollapsed)
{
barView.frame = CGRectMake(barView.frame.origin.x, self.bounds.size.height, barView.frame.size.width, barView.frame.size.height);
}
}
if (callbackCopy)
{
callbackCopy();
@@ -311,6 +486,87 @@ static UIColor *kJBBarChartViewDefaultBarColor = nil;
}
}
- (void)setState:(JBChartViewState)state animated:(BOOL)animated callback:(void (^)())callback
{
[self setState:state animated:animated force:NO callback:callback];
}
- (void)setVerticalSelectionViewVisible:(BOOL)verticalSelectionViewVisible animated:(BOOL)animated
{
_verticalSelectionViewVisible = verticalSelectionViewVisible;
if (animated)
{
[UIView animateWithDuration:kJBChartViewDefaultAnimationDuration delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
self.verticalSelectionView.alpha = self.verticalSelectionViewVisible ? 1.0 : 0.0;
} completion:nil];
}
else
{
self.verticalSelectionView.alpha = _verticalSelectionViewVisible ? 1.0 : 0.0;
}
}
- (void)setVerticalSelectionViewVisible:(BOOL)verticalSelectionViewVisible
{
[self setVerticalSelectionViewVisible:verticalSelectionViewVisible animated:NO];
}
- (void)setShowsVerticalSelection:(BOOL)showsVerticalSelection
{
_showsVerticalSelection = showsVerticalSelection;
self.verticalSelectionView.hidden = _showsVerticalSelection ? NO : YES;
}
#pragma mark - Getters
- (CGFloat)cachedMinHeight
{
if(_cachedMinHeight == kJBBarChartViewUndefinedCachedHeight)
{
NSArray *chartValues = [[NSMutableArray arrayWithArray:[self.chartDataDictionary allValues]] sortedArrayUsingSelector:@selector(compare:)];
_cachedMinHeight = [[chartValues firstObject] floatValue];
}
return _cachedMinHeight;
}
- (CGFloat)cachedMaxHeight
{
if (_cachedMaxHeight == kJBBarChartViewUndefinedCachedHeight)
{
NSArray *chartValues = [[NSMutableArray arrayWithArray:[self.chartDataDictionary allValues]] sortedArrayUsingSelector:@selector(compare:)];
_cachedMaxHeight = [[chartValues lastObject] floatValue];
}
return _cachedMaxHeight;
}
- (CGFloat)minimumValue
{
if ([self hasMinimumValue])
{
return fminf(self.cachedMinHeight, [super minimumValue]);
}
return self.cachedMinHeight;
}
- (CGFloat)maximumValue
{
if ([self hasMaximumValue])
{
return fmaxf(self.cachedMaxHeight, [super maximumValue]);
}
return self.cachedMaxHeight;
}
- (UIView *)barViewAtIndex:(NSUInteger)index
{
if (index < [self.barViews count])
{
return [self.barViews objectAtIndex:index];
}
return nil;
}
#pragma mark - Touch Helpers
- (NSInteger)barViewIndexForPoint:(CGPoint)point
@@ -344,103 +600,169 @@ static UIColor *kJBBarChartViewDefaultBarColor = nil;
NSInteger selectedIndex = [self barViewIndexForPoint:point];
if (selectedIndex >= 0)
{
barView = [self.barViews objectAtIndex:[self barViewIndexForPoint:point]];
return [self.barViews objectAtIndex:[self barViewIndexForPoint:point]];
}
return barView;
}
#pragma mark - Setters
- (void)setSelectionViewVisible:(BOOL)selectionViewVisible animated:(BOOL)animated
- (void)touchesBeganOrMovedWithTouches:(NSSet *)touches
{
_selectionViewVisible = selectionViewVisible;
if (animated)
if (self.state == JBChartViewStateCollapsed || [[self.chartDataDictionary allKeys] count] <= 0)
{
[UIView animateWithDuration:kJBChartViewDefaultAnimationDuration delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
self.selectionView.alpha = _selectionViewVisible ? 1.0 : 0.0;
} completion:nil];
return;
}
UITouch *touch = [touches anyObject];
CGPoint touchPoint = [touch locationInView:self];
UIView *barView = [self barViewForForPoint:touchPoint];
if (barView == nil)
{
[self setVerticalSelectionViewVisible:NO animated:YES];
return;
}
CGRect barViewFrame = barView.frame;
CGRect selectionViewFrame = self.verticalSelectionView.frame;
selectionViewFrame.origin.x = barViewFrame.origin.x;
selectionViewFrame.size.width = barViewFrame.size.width;
if ([self.dataSource respondsToSelector:@selector(shouldExtendSelectionViewIntoHeaderPaddingForChartView:)])
{
if ([self.dataSource shouldExtendSelectionViewIntoHeaderPaddingForChartView:self])
{
selectionViewFrame.origin.y = self.headerView.frame.size.height;
}
else
{
selectionViewFrame.origin.y = self.headerView.frame.size.height + self.headerPadding;
}
}
else
{
self.selectionView.alpha = _selectionViewVisible ? 1.0 : 0.0;
selectionViewFrame.origin.y = self.headerView.frame.size.height + self.headerPadding;
}
self.verticalSelectionView.frame = selectionViewFrame;
[self setVerticalSelectionViewVisible:YES animated:YES];
if ([self.delegate respondsToSelector:@selector(barChartView:didSelectBarAtIndex:touchPoint:)])
{
[self.delegate barChartView:self didSelectBarAtIndex:[self barViewIndexForPoint:touchPoint] touchPoint:touchPoint];
}
if ([self.delegate respondsToSelector:@selector(barChartView:didSelectBarAtIndex:)])
{
[self.delegate barChartView:self didSelectBarAtIndex:[self barViewIndexForPoint:touchPoint]];
}
}
- (void)setSelectionViewVisible:(BOOL)selectionViewVisible
- (void)touchesEndedOrCancelledWithTouches:(NSSet *)touches
{
[self setSelectionViewVisible:selectionViewVisible animated:NO];
if (self.state == JBChartViewStateCollapsed || [[self.chartDataDictionary allKeys] count] <= 0)
{
return;
}
[self setVerticalSelectionViewVisible:NO animated:YES];
if ([self.delegate respondsToSelector:@selector(didDeselectBarChartView:)])
{
[self.delegate didDeselectBarChartView:self];
}
}
#pragma mark - Touches
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if (!self.showsSelection || self.state == JBChartViewStateCollapsed)
{
return;
}
UITouch *touch = [touches anyObject];
CGPoint touchPoint = [touch locationInView:self];
UIView *barView = [self barViewForForPoint:touchPoint];
if (barView == nil)
{
[self setSelectionViewVisible:NO animated:YES];
return;
}
CGRect barViewFrame = barView.frame;
CGRect selectionViewFrame = self.selectionView.frame;
selectionViewFrame.origin.x = barViewFrame.origin.x;
self.selectionView.frame = selectionViewFrame;
[self setSelectionViewVisible:YES animated:YES];
if ([self.delegate respondsToSelector:@selector(barChartView:didSelectBarAtIndex:)])
{
[self.delegate barChartView:self didSelectBarAtIndex:[self barViewIndexForPoint:touchPoint]];
}
[self setVerticalSelectionViewVisible:NO animated:NO];
[self touchesBeganOrMovedWithTouches:touches];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
if (!self.showsSelection || self.state == JBChartViewStateCollapsed)
{
return;
}
UITouch *touch = [touches anyObject];
CGPoint touchPoint = [touch locationInView:self];
UIView *barView = [self barViewForForPoint:touchPoint];
if (barView == nil)
{
[self setSelectionViewVisible:NO animated:YES];
return;
}
CGRect barViewFrame = barView.frame;
CGRect selectionViewFrame = self.selectionView.frame;
selectionViewFrame.origin.x = barViewFrame.origin.x;
self.selectionView.frame = selectionViewFrame;
[self setSelectionViewVisible:YES animated:YES];
if ([self.delegate respondsToSelector:@selector(barChartView:didSelectBarAtIndex:)])
{
[self.delegate barChartView:self didSelectBarAtIndex:[self barViewIndexForPoint:touchPoint]];
}
[self touchesBeganOrMovedWithTouches:touches];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
if (!self.showsSelection || self.state == JBChartViewStateCollapsed)
{
return;
}
[self setSelectionViewVisible:NO animated:YES];
UITouch *touch = [touches anyObject];
CGPoint touchPoint = [touch locationInView:self];
NSInteger index = [self barViewIndexForPoint:touchPoint];
if ([self.delegate respondsToSelector:@selector(barChartView:didUnselectBarAtIndex:)])
{
[self.delegate barChartView:self didUnselectBarAtIndex:index];
}
[self touchesEndedOrCancelledWithTouches:touches];
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
[self touchesEndedOrCancelledWithTouches:touches];
}
#pragma mark - JBGradientBarViewDelegate
- (CGRect)chartViewBoundsForGradientBarView:(JBGradientBarView *)gradientBarView
{
return self.bounds;
}
@end
@implementation JBGradientBarView
#pragma mark - Alloc/Init
- (instancetype)init
{
self = [super init];
if (self)
{
[self construct];
}
return self;
}
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
[self construct];
}
return self;
}
#pragma mark - Setters
- (void)setGradientLayer:(CAGradientLayer *)gradientLayer
{
if (_gradientLayer != nil)
{
[_gradientLayer removeFromSuperlayer];
_gradientLayer = nil;
}
_gradientLayer = gradientLayer;
_gradientLayer.masksToBounds = YES;
[self.layer insertSublayer:_gradientLayer atIndex:0];
}
#pragma mark - Construction
- (void)construct
{
self.clipsToBounds = YES;
}
#pragma mark - Setters
- (void)setFrame:(CGRect)frame
{
[super setFrame:frame];
if ([self.delegate respondsToSelector:@selector(chartViewBoundsForGradientBarView:)])
{
_gradientLayer.frame = [self.delegate chartViewBoundsForGradientBarView:self]; // gradient is as large as the chart
_gradientLayer.frame = CGRectOffset(_gradientLayer.frame, -CGRectGetMinX(frame), 0);
}
else
{
_gradientLayer.frame = self.bounds;
}
}
@end
+96 -12
View File
@@ -7,9 +7,12 @@
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
extern CGFloat const kJBChartViewDefaultAnimationDuration;
@class JBChartView;
/**
* At a minimum, a chart can support two states, along with animations to-and-from.
*/
@@ -24,20 +27,90 @@ typedef NS_ENUM(NSInteger, JBChartViewState){
JBChartViewStateCollapsed
};
@protocol JBChartViewDataSource <NSObject>
@optional
/**
* Returns whether or not the chart's selection view should extend into the header padding.
*
* Default: NO
*
* @param chartView The chart object requesting this information.
*
* @return Whether or not a chart's selection view should extend into the header padding.
*/
- (BOOL)shouldExtendSelectionViewIntoHeaderPaddingForChartView:(JBChartView *)chartView;
/**
* Returns whether or not the chart's selection view should extend into the footer padding.
*
* Default: NO
*
* @param chartView The chart object requesting this information.
*
* @return Whether or not a chart's selection view should extend into the footer padding.
*/
- (BOOL)shouldExtendSelectionViewIntoFooterPaddingForChartView:(JBChartView *)chartView;
@end
@protocol JBChartViewDelegate <NSObject>
// Extend (via subclass) to add custom functionality
@end
@interface JBChartView : UIView
/*
* Base dataSource and delegate protocols.
*/
@property (nonatomic, weak) id<JBChartViewDataSource> dataSource;
@property (nonatomic, weak) id<JBChartViewDelegate> delegate;
/**
* Header and footer views are shown above and below the chart respectively.
* Each view will be stretched horizontally to fill width of chart.
* Each view's bounds are clipped to support chart state animations.
*/
@property (nonatomic, strong) UIView *footerView;
@property (nonatomic, strong) UIView *headerView;
/**
* The vertical padding between the header and highest chart point (bar, line, etc)
* The vertical padding between the header and highest chart point (bar, line, etc).
* By default, the selection view will extend into the header padding area. To modify this behaviour,
* implement the dataSource protocol - (BOOL)shouldExtendSelectionViewIntoHeaderPaddingForChartView:(JBChartView *)chartView.
*/
@property (nonatomic, assign) CGFloat headerPadding;
/**
* The vertical padding between the footer and lowest chart point (bar, line, etc).
* By default, the selection view will extend into the footer padding area. To modify this behaviour,
* implement the dataSource protocol - (BOOL)shouldExtendSelectionViewIntoFooterPaddingForChartView:(JBChartView *)chartView.
*/
@property (nonatomic, assign) CGFloat footerPadding;
/**
* The minimum and maxmimum values of the chart.
* If no value(s) are supplied:
*
* minimumValue = chart's data source min value.
* maxmimumValue = chart's data source max value.
*
* If value(s) are supplied, they must be >= 0, otherwise an assertion will be thrown.
* The min/max values are clamped to the ceiling and floor of the actual min/max values of the chart's data source;
* for example, if a maximumValue of 20 is supplied & the chart's actual max is 100, then 100 will be used.
*
* For min/max modifications to take effect, reloadData must be called.
*/
@property (nonatomic, assign) CGFloat minimumValue;
@property (nonatomic, assign) CGFloat maximumValue;
// reset to default (chart's data source min & max value)
- (void)resetMinimumValue;
- (void)resetMaximumValue;
/**
* Charts can either be expanded or contracted.
* By default, a chart should be expanded on initialization.
@@ -47,23 +120,34 @@ typedef NS_ENUM(NSInteger, JBChartViewState){
/**
* Acts similiar to a UITableView's reloadData function.
* The entire chart will be torn down and re-constructed via datasource and delegate protocls.
* If a chart's frame changes, reloadData must be called directly afterwards for the changes to take effect.
*/
- (void)reloadData;
/**
* State setter
* State setter.
*
* @param state Either collapse or expanded.
* @param animated Whether or not the state should be animated or not.
* @param callback Called once the animation is completed. If animated == NO, then callback is immediate.
* @param state Either collapse or expanded.
* @param animated Whether or not the state should be animated or not.
* @param force If current state == new state, then setting force to YES will re-configure the chart (default NO).
* @param callback Called once the animation is completed. If animated == NO, then callback is immediate.
*/
- (void)setState:(JBChartViewState)state animated:(BOOL)animated force:(BOOL)force callback:(void (^)())callback;
/**
* State setter.
*
* @param state Either collapse or expanded.
* @param animated Whether or not the state should be animated or not.
* @param callback Called once the animation is completed. If animated == NO, then callback is immediate.
*/
- (void)setState:(JBChartViewState)state animated:(BOOL)animated callback:(void (^)())callback;
/**
* State setter
* State setter.
*
* @param state Either collapse or expanded.
* @param animated Whether or not the state should be animated or not.
* @param state Either collapse or expanded.
* @param animated Whether or not the state should be animated or not.
*/
- (void)setState:(JBChartViewState)state animated:(BOOL)animated;
@@ -71,14 +155,14 @@ typedef NS_ENUM(NSInteger, JBChartViewState){
/**
* A simple UIView subclass that fades a base color from current alpha to 0.0 (vertically).
* Used as a selection ivew in JBChartView subclasses.
* Used as a vertical selection view in JBChartView subclasses.
*/
@interface JBChartSelectionView : UIView
@interface JBChartVerticalSelectionView : UIView
/**
* Base selection view color. This color will be faded to transparent vertically
* Base selection view color. This color will be faded to transparent vertically.
*
* Default: white color
* Default: white color.
*
*/
@property (nonatomic, strong) UIColor *bgColor;
+65 -9
View File
@@ -8,13 +8,21 @@
#import "JBChartView.h"
// Numerics
CGFloat const kJBChartViewDefaultAnimationDuration = 0.25f;
// Color (JBChartSelectionView)
static UIColor *kJBChartSelectionViewDefaultBgColor = nil;
static UIColor *kJBChartVerticalSelectionViewDefaultBgColor = nil;
@interface JBChartView ()
@property (nonatomic, assign) BOOL hasMaximumValue;
@property (nonatomic, assign) BOOL hasMinimumValue;
// Construction
- (void)constructChartView;
// Validation
- (void)validateHeaderAndFooterHeights;
@end
@@ -23,12 +31,22 @@ static UIColor *kJBChartSelectionViewDefaultBgColor = nil;
#pragma mark - Alloc/Init
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self)
{
[self constructChartView];
}
return self;
}
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
self.clipsToBounds = YES;
[self constructChartView];
}
return self;
}
@@ -38,6 +56,13 @@ static UIColor *kJBChartSelectionViewDefaultBgColor = nil;
return [self initWithFrame:CGRectZero];
}
#pragma mark - Construction
- (void)constructChartView
{
self.clipsToBounds = YES;
}
#pragma mark - Public
- (void)reloadData
@@ -45,7 +70,7 @@ static UIColor *kJBChartSelectionViewDefaultBgColor = nil;
// Override
}
#pragma mark - Helpers
#pragma mark - Validation
- (void)validateHeaderAndFooterHeights
{
@@ -62,6 +87,7 @@ static UIColor *kJBChartSelectionViewDefaultBgColor = nil;
_headerView = nil;
}
_headerView = headerView;
_headerView.clipsToBounds = YES;
[self validateHeaderAndFooterHeights];
@@ -77,6 +103,7 @@ static UIColor *kJBChartSelectionViewDefaultBgColor = nil;
_footerView = nil;
}
_footerView = footerView;
_footerView.clipsToBounds = YES;
[self validateHeaderAndFooterHeights];
@@ -84,9 +111,9 @@ static UIColor *kJBChartSelectionViewDefaultBgColor = nil;
[self reloadData];
}
- (void)setState:(JBChartViewState)state animated:(BOOL)animated callback:(void (^)())callback
- (void)setState:(JBChartViewState)state animated:(BOOL)animated force:(BOOL)force callback:(void (^)())callback
{
if (_state == state)
if ((_state == state) && !force)
{
return;
}
@@ -96,6 +123,11 @@ static UIColor *kJBChartSelectionViewDefaultBgColor = nil;
// Override
}
- (void)setState:(JBChartViewState)state animated:(BOOL)animated callback:(void (^)())callback
{
[self setState:state animated:animated force:NO callback:callback];
}
- (void)setState:(JBChartViewState)state animated:(BOOL)animated
{
[self setState:state animated:animated callback:nil];
@@ -106,17 +138,41 @@ static UIColor *kJBChartSelectionViewDefaultBgColor = nil;
[self setState:state animated:NO];
}
- (void)setMinimumValue:(CGFloat)minimumValue
{
NSAssert(minimumValue >= 0, @"JBChartView // the minimumValue must be >= 0.");
_minimumValue = minimumValue;
_hasMinimumValue = YES;
}
- (void)setMaximumValue:(CGFloat)maximumValue
{
NSAssert(maximumValue >= 0, @"JBChartView // the maximumValue must be >= 0.");
_maximumValue = maximumValue;
_hasMaximumValue = YES;
}
- (void)resetMinimumValue
{
_hasMinimumValue = NO; // clears min
}
- (void)resetMaximumValue
{
_hasMaximumValue = NO; // clears max
}
@end
@implementation JBChartSelectionView
@implementation JBChartVerticalSelectionView
#pragma mark - Alloc/Init
+ (void)initialize
{
if (self == [JBChartSelectionView class])
if (self == [JBChartVerticalSelectionView class])
{
kJBChartSelectionViewDefaultBgColor = [UIColor whiteColor];
kJBChartVerticalSelectionViewDefaultBgColor = [UIColor whiteColor];
}
}
@@ -148,7 +204,7 @@ static UIColor *kJBChartSelectionViewDefaultBgColor = nil;
}
else
{
colors = @[(__bridge id)kJBChartSelectionViewDefaultBgColor.CGColor, (__bridge id)[kJBChartSelectionViewDefaultBgColor colorWithAlphaComponent:0.0].CGColor];
colors = @[(__bridge id)kJBChartVerticalSelectionViewDefaultBgColor.CGColor, (__bridge id)[kJBChartVerticalSelectionViewDefaultBgColor colorWithAlphaComponent:0.0].CGColor];
}
CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef) colors, locations);
Regular → Executable
+380 -50
View File
@@ -8,96 +8,426 @@
#import "JBChartView.h"
@protocol JBLineChartViewDelegate;
@protocol JBLineChartViewDataSource;
@interface JBLineChartView : JBChartView
@property (nonatomic, weak) id<JBLineChartViewDelegate> delegate;
@property (nonatomic, weak) id<JBLineChartViewDataSource> dataSource;
@class JBLineChartView;
/**
* If showsSelection is YES, a vertical highlight will overlayed on a the line graph during touch events.
*
* Default: YES
* Current support for two line styles: solid (default) and dashed.
*/
@property (nonatomic, assign) BOOL showsSelection;
typedef NS_ENUM(NSInteger, JBLineChartViewLineStyle){
/**
* Solid line.
*/
JBLineChartViewLineStyleSolid,
/**
* Dashed line with a phase of 3:2 (3 points dashed, 2 points spaced).
*/
JBLineChartViewLineStyleDashed
};
@end
/**
* Current support for two line color styles: solid (default) and gradient.
*/
typedef NS_ENUM(NSInteger, JBLineChartViewLineColorStyle){
/**
* Solid line and fill color.
*/
JBLineChartViewLineColorStyleSolid,
/**
* Gradient line and fill color.
*/
JBLineChartViewLineColorStyleGradient
};
@protocol JBLineChartViewDelegate <NSObject>
@protocol JBLineChartViewDataSource <JBChartViewDataSource>
@required
/**
* Vertical position for line point at a given index (left to right). There is no ceiling on the the height;
* the chart will automatically normalize all values between the overal min and max heights.
* Returns the number of lines for the line chart.
*
* @param lineChartView The origin chart
* @param index The 0-based index of a given line height (left to right, x-axis)
* @param lineChartView The line chart object requesting this information.
*
* @return The number of lines in the line chart.
*/
- (NSUInteger)numberOfLinesInLineChartView:(JBLineChartView *)lineChartView;
/**
* Returns the number of vertical values for a particular line at lineIndex within the chart.
*
* @param lineChartView The line chart object requesting this information.
* @param lineIndex An index number identifying a line in the chart.
*
* @return The number of vertical values for a given line in the line chart.
*/
- (NSUInteger)lineChartView:(JBLineChartView *)lineChartView numberOfVerticalValuesAtLineIndex:(NSUInteger)lineIndex;
@optional
/**
* Returns whether or not a line should show a dot for each point.
* Dot size is relative to the line width and not adjustable.
* Dot color is equal to the line color and not adjustable.
*
* Default: NO.
*
* @param lineChartView The line chart object requesting this information.
* @param lineIndex An index number identifying a line in the chart.
*
* @return Whether or not a line should show a dot for each chart point.
*/
- (BOOL)lineChartView:(JBLineChartView *)lineChartView showsDotsForLineAtLineIndex:(NSUInteger)lineIndex;
/**
* Returns whether or not a line should be rendered with curved connections and rounded end caps.
*
* Default: NO.
*
* @param lineChartView The line chart object requesting this information.
* @param lineIndex An index number identifying a line in the chart.
*
* @return Whether or not a line should smooth it's connections and end caps.
*/
- (BOOL)lineChartView:(JBLineChartView *)lineChartView smoothLineAtLineIndex:(NSUInteger)lineIndex;
/**
* Returns the opacity value to be used for dimming the line & fill during selection events.
* This value is applied to the line or fill's opacity anytime it's not selected (but another line is).
* This applies to both solid and gradient line styles.
*
* Default: 0.2.
*
* @param lineChartView The line chart object requesting this information.
* @param lineIndex An index number identifying a line in the chart.
*
* @return A value between 0.0 and 1.0 (will be clamped accordingly).
*/
- (CGFloat)lineChartView:(JBLineChartView *)lineChartView dimmedSelectionOpacityAtLineIndex:(NSUInteger)lineIndex;
/**
* Returns a (custom) UIView instance representing a dot (x,y point) within the chart.
* For this value to apply, showsDotsForLineAtLineIndex: must return YES for the line at lineIndex.
* This protocol supercedes colorForDotAtHorizontalIndex: and dotRadiusForDotAtHorizontalIndex:.
* If nil is returned. the original dot protocols will take precedence. During selection events, a custom
* dot view will not be hidden unless lineChartView:shouldHideDotViewOnSelectionAtHorizontalIndex:atLineIndex:
* is implemented.
*
* Default: nil.
*
* @param lineChartView The line chart object requesting this information.
* @param horizontalIndex The 0-based horizontal index of a selection point (left to right, x-axis).
* @param lineIndex An index number identifying a line in the chart.
*
* @return A custom UIView instance representing a dot at a particular horizontal index within a dotted line.
*/
- (UIView *)lineChartView:(JBLineChartView *)lineChartView dotViewAtHorizontalIndex:(NSUInteger)horizontalIndex atLineIndex:(NSUInteger)lineIndex;
/**
* Returns whether or not a (custom) dot view should be hidden on selection events.
*
* Default: NO.
*
* @param lineChartView The line chart object requesting this information.
* @param horizontalIndex The 0-based horizontal index of a selection point (left to right, x-axis).
* @param lineIndex An index number identifying a line in the chart.
*
* @return Whether or not a (custom) dot view should be hidden on selection events.
*/
- (BOOL)lineChartView:(JBLineChartView *)lineChartView shouldHideDotViewOnSelectionAtHorizontalIndex:(NSUInteger)horizontalIndex atLineIndex:(NSUInteger)lineIndex;
@end
@protocol JBLineChartViewDelegate <JBChartViewDelegate>
@required
/**
* Vertical value for a line point at a given index (left to right). There is no ceiling on the the height;
* the chart will automatically normalize all values between the overal min and max heights.
* NAN may able be retuend to indicate missing values. The chart's line will begin at the first non-NAN value and end at the last non-NAN value.
* Furthermore, the line will interopolate any NAN values in between (ie. the line will not be interrupted).
*
* @param lineChartView The line chart object requesting this information.
* @param horizontalIndex The 0-based horizontal index of a selection point (left to right, x-axis).
* @param lineIndex An index number identifying the closest line in the chart to the current touch point.
*
* @return The y-axis value of the supplied line index (x-axis)
*/
- (CGFloat)lineChartView:(JBLineChartView *)lineChartView heightForIndex:(NSInteger)index;
- (CGFloat)lineChartView:(JBLineChartView *)lineChartView verticalValueForHorizontalIndex:(NSUInteger)horizontalIndex atLineIndex:(NSUInteger)lineIndex;
@optional
/**
* Occurs when a touch gesture event occurs anywhere on the chart. The chart must be expanded, showsSelection must be YES,
* and the selection must occur within the bounds of the chart.
* Occurs whenever there is a touch gesture on the chart (chart must be expanded).
* The horizontal index is the closest index to the touch point & is clamped to it's max/min value if it moves outside of the view's bounds.
* The lineIndex remains constant until the line is deselected and will be highlighted using the (optional) selectionColorForLineAtLineIndex: protocol.
* Futhermore, all other lines that aren't selected will be dimmed to 20% opacity (default) throughout the duration of the touch/move.
* Any dotted line that isn't the primary selection will have it's dots dimmed to hidden (to avoid transparency issues).
*
* @param lineChartView The origin chart
* @param index The 0-based index of a selection point (left to right, x-axis)
* @param lineChartView A line chart object informing the delegate about the new selection.
* @param lineIndex An index number identifying the closest line in the chart to the current touch
* @param horizontalIndex The 0-based horizontal index of a selection point (left to right, x-axis).
* @param touchPoint The touch point in relation to the chart's bounds (excludes footer and header).
*/
- (void)lineChartView:(JBLineChartView *)lineChartView didSelectChartAtIndex:(NSInteger)index;
- (void)lineChartView:(JBLineChartView *)lineChartView didSelectLineAtIndex:(NSUInteger)lineIndex horizontalIndex:(NSUInteger)horizontalIndex touchPoint:(CGPoint)touchPoint;
- (void)lineChartView:(JBLineChartView *)lineChartView didSelectLineAtIndex:(NSUInteger)lineIndex horizontalIndex:(NSUInteger)horizontalIndex;
/**
* Occurs when selection ends by either ending a touch event or selecting an area that is outside the view's bounds.
* For selection start events, see: didSelectChartAtIndex...
* Occurs when selection ends by ending a touch event. For selection start events, see: didSelectChartAtIndex:
*
* @param lineChartView The origin chart
* @param index The 0-based index of a selection point. Index will be -1 if the touch ends outside of the view's bounds.
* @param lineChartView A line chart object informing the delegate about the deselection.
*/
- (void)lineChartView:(JBLineChartView *)lineChartView didUnselectChartAtIndex:(NSInteger)index;
- (void)didDeselectLineInLineChartView:(JBLineChartView *)lineChartView;
/**
* Returns whether or not a line at a particular index responds to selection events.
*
* Default: YES
*
* @param lineChartView A line chart object informing the delegate about the new selection.
* @param lineIndex An index number identifying the closest line in the chart to the current touch
*/
- (BOOL)lineChartView:(JBLineChartView *)lineChartView shouldIgnoreSelectionAtIndex:(NSUInteger)lineIndex;
/**
* Returns the color of particular line at lineIndex within the chart.
*
* Default: black color.
*
* @param lineChartView The line chart object requesting this information.
* @param lineIndex An index number identifying a line in the chart.
*
* @return The color to be used to shade a line in the chart.
*/
- (UIColor *)lineChartView:(JBLineChartView *)lineChartView colorForLineAtLineIndex:(NSUInteger)lineIndex;
/**
* Returns the gradient layer to be used for a particular line at lineIndex within the chart.
*
* Default: black to light gray.
*
* @param lineChartView The line chart object requesting this information.
* @param lineIndex An index number identifying a line in the chart.
*
* @return The gradient layer to be used as a mask for the line in the chart.
*/
- (CAGradientLayer *)lineChartView:(JBLineChartView *)lineChartView gradientForLineAtLineIndex:(NSUInteger)lineIndex;
/**
* Returns the fill color of particular line at lineIndex within the chart.
*
* Default: clear color.
*
* @param lineChartView The line chart object requesting this information.
* @param lineIndex An index number identifying a line in the chart.
*
* @return The fill color to show under a line in the chart.
*/
- (UIColor *)lineChartView:(JBLineChartView *)lineChartView fillColorForLineAtLineIndex:(NSUInteger)lineIndex;
/**
* Returns the gradient layer to be used for a fill of a particular line at lineIndex within the chart.
*
* Default: white to light gray.
*
* @param lineChartView The line chart object requesting this information.
* @param lineIndex An index number identifying a line in the chart.
*
* @return The fill color to show under a line in the chart.
*/
- (CAGradientLayer *)lineChartView:(JBLineChartView *)lineChartView fillGradientForLineAtLineIndex:(NSUInteger)lineIndex;
/**
* Returns the color of a particular dot in a line at lineIndex within the chart.
* For this value to apply, showsDotsForLineAtLineIndex: must return YES for the line at lineIndex.
* Any value can be returned for lineIndex's that don't support dots, as it will never be called.
*
* Default: black color.
*
* @param lineChartView The line chart object requesting this information.
* @param horizontalIndex The 0-based horizontal index of a selection point (left to right, x-axis)
* @param lineIndex An index number identifying a line in the chart.
*
* @return The color to be used to color a dot within a dotted line in the chart.
*/
- (UIColor *)lineChartView:(JBLineChartView *)lineChartView colorForDotAtHorizontalIndex:(NSUInteger)horizontalIndex atLineIndex:(NSUInteger)lineIndex;
/**
* Returns the width of particular line at lineIndex within the chart.
*
* Default: 5 points.
*
* @param lineChartView The line chart object requesting this information.
* @param lineIndex An index number identifying a line in the chart.
*
* @return The width to be used to draw a line in the chart.
*/
- (CGFloat)lineChartView:(JBLineChartView *)lineChartView widthForLineAtLineIndex:(NSUInteger)lineIndex;
/**
* Returns the radius of all dots in a particular line at lineIndex within the chart.
* For this value to apply, showsDotsForLineAtLineIndex: must return YES for the line at lineIndex.
* Any value can be returned for lineIndex's that don't support dots, as it will never be called.
*
* Default: line width x 6.
*
* @param lineChartView The line chart object requesting this information.
* @param horizontalIndex The 0-based horizontal index of a selection point (left to right, x-axis).
* @param lineIndex An index number identifying a line in the chart.
*
* @return The radius of the dots within a dotted line in the chart.
*/
- (CGFloat)lineChartView:(JBLineChartView *)lineChartView dotRadiusForDotAtHorizontalIndex:(NSUInteger)horizontalIndex atLineIndex:(NSUInteger)lineIndex;
/**
* Returns the width of the (vertical) selection view to be overlayed on the chart during touch events.
* The property showsVerticalSelection must be YES for the width to apply. The width is clamped to the
* maxmimum width of the chart's bounds.
*
* Default: 20px.
*
* @param lineChartView The line chart object requesting this information.
*
* @return The width of the selection view used during chart selections.
*/
- (CGFloat)verticalSelectionWidthForLineChartView:(JBLineChartView *)lineChartView;
/**
* Returns the (vertical) selection color to be overlayed on the chart during touch events on a given line.
* The color is automically faded to transparent (vertically). The property showsVerticalSelection
* must be YES for the color to apply.
*
* @param lineChartView The line chart object requesting this information.
* @param lineIndex An index number identifying a line in the chart.
*
* @return The color of the selection view used during chart selections of the given line.
*/
- (UIColor *)lineChartView:(JBLineChartView *)lineChartView verticalSelectionColorForLineAtLineIndex:(NSUInteger)lineIndex;
/**
* Returns the selection color to be overlayed on a line within the chart during touch events.
* The property showsLineSelection must be YES for the color to apply.
*
* Default: white color.
*
* @param lineChartView The line chart object requesting this information.
* @param lineIndex An index number identifying a line in the chart.
*
* @return The color to be used to highlight a line during chart selections.
*/
- (UIColor *)lineChartView:(JBLineChartView *)lineChartView selectionColorForLineAtLineIndex:(NSUInteger)lineIndex;
/**
* Returns the gradient layer to be overlayed on a line during touch events.
* Alpha of gradient is controlled by the color returned from lineChartView:selectionColorForLineAtLineIndex:
*
* Default: matches lineChartView:gradientForLineAtLineIndex:.
*
* @param lineChartView The line chart object requesting this information.
* @param lineIndex An index number identifying a line in the chart.
*
* @return The gradient layer to be used as a mask for the line in the chart.
*/
- (CAGradientLayer *)lineChartView:(JBLineChartView *)lineChartView selectionGradientForLineAtLineIndex:(NSUInteger)lineIndex;
/**
* Returns the selection fill color to be overlayed under a line within the chart during touch events.
* The property showsLineSelection must be YES for the color to apply.
*
* Default: clear color.
*
* @param lineChartView The line chart object requesting this information.
* @param lineIndex An index number identifying a line in the chart.
*
* @return The color to be used to highlight under a line during chart selections.
*/
- (UIColor *)lineChartView:(JBLineChartView *)lineChartView selectionFillColorForLineAtLineIndex:(NSUInteger)lineIndex;
/**
* Returns the gradient layer to be used for the selection fill to be overlayed under a line during touch events.
* Alpha of gradient is controlled by the color returned from lineChartView:selectionFillColorForLineAtLineIndex:
*
* Default: matches lineChartView:fillGradientForLineAtLineIndex.
*
* @param lineChartView The line chart object requesting this information.
* @param lineIndex An index number identifying a line in the chart.
*
* @return The fill color to show under a line in the chart.
*/
- (CAGradientLayer *)lineChartView:(JBLineChartView *)lineChartView selectionFillGradientForLineAtLineIndex:(NSUInteger)lineIndex;
/**
* Returns the selection color to be overlayed on a line within the chart during touch events.
* The property showsLineSelection must be YES for the color to apply.
*
* Default: white color.
*
* @param lineChartView The line chart object requesting this information.
* @param horizontalIndex The 0-based horizontal index of a selection point (left to right, x-axis).
* @param lineIndex An index number identifying a line in the chart.
*
* @return The color to be used to highlight a dot within a dotted line during chart selections.
*/
- (UIColor *)lineChartView:(JBLineChartView *)lineChartView selectionColorForDotAtHorizontalIndex:(NSUInteger)horizontalIndex atLineIndex:(NSUInteger)lineIndex;
/**
* Returns the line style of a particular line at lineIndex within the chart.
* See JBLineChartViewLineStyle for line style descriptions.
*
* Default: JBLineChartViewLineStyleSolid.
*
* @param lineChartView The line chart object requesting this information.
* @param lineIndex An index number identifying a line in the chart.
*
* @return The line style to be used to draw a line in the chart.
*/
- (JBLineChartViewLineStyle)lineChartView:(JBLineChartView *)lineChartView lineStyleForLineAtLineIndex:(NSUInteger)lineIndex;
/**
* Returns the line color style of a particular line at lineIndex within the chart.
* See JBLineChartViewLineColorStyle for line color style descriptions.
*
* Default: JBLineChartViewLineColorStyleSolid.
*
* @param lineChartView The line chart object requesting this information.
* @param lineIndex An index number identifying a line in the chart.
*
* @return The line style to be used to draw a line in the chart.
*/
- (JBLineChartViewLineColorStyle)lineChartView:(JBLineChartView *)lineChartView lineColorStyleForLineAtLineIndex:(NSUInteger)lineIndex;
@end
@protocol JBLineChartViewDataSource <NSObject>
@interface JBLineChartView : JBChartView
@required
@property (nonatomic, weak) id<JBLineChartViewDataSource> dataSource;
@property (nonatomic, weak) id<JBLineChartViewDelegate> delegate;
/**
* The number of points in a given line chart equates to the number of values along the x-axis.
* Vertical highlight overlayed on a line graph during touch events.
*
* @param lineChartView The origin chart
*
* @return Number of points in the given chart.
* Default: YES.
*/
- (NSInteger)numberOfPointsInLineChartView:(JBLineChartView *)lineChartView;
@optional
@property (nonatomic, assign) BOOL showsVerticalSelection;
/**
* The color of the line within the chart.
*
* Default: black color
* A highlight shown on a line within the graph during touch events. The highlighted line
* is the closest line to the touch point and corresponds to the lineIndex delegatd back via
* didSelectChartAtHorizontalIndex:atLineIndex: and didUnSlectChartAtHorizontalIndex:atLineIndex:
*
* @param lineChartView The origin chart
*
* @return The color to be used to draw the line on the chart (alphas < 1 are supported)
* Default: YES.
*/
- (UIColor *)lineColorForLineChartView:(JBLineChartView *)lineChartView;
@property (nonatomic, assign) BOOL showsLineSelection;
/**
* The selection color to be overlayed on the chart during touch events.
* The color is automically faded to transparent (vertically).
* The dot view within a particular line at a horizontalIndex.
*
* Default: white color (faded to transparent)
* Default: nil.
*
* @param lineChartView The origin chart
* @param horizontalIndex The 0-based horizontal index of a selection point (left to right, x-axis)
* @param lineIndex An index number identifying a line in the chart.
*
* @return The color to be used on chart selections.
* @return The UIView representing the dot view at a given horizontalIndex within a line or nil if any index is out of range.
*/
- (UIColor *)selectionColorForLineChartView:(JBLineChartView *)lineChartView;
- (UIView *)dotViewAtHorizontalIndex:(NSUInteger)horizontalIndex atLineIndex:(NSUInteger)lineIndex;
@end
Regular → Executable
+1532 -314
View File
File diff suppressed because it is too large Load Diff
+196
View File
@@ -0,0 +1,196 @@
## Customization
Both the line and bar charts support a robust set of customization options.
The background of a bar or line chart can be set just like any other view:
self.barChartView.backgroundColor = ...; // UIColor
self.lineChartView.backgroundColor = ...; // UIColor
Any <i>JBChartView</i> subclass supports the use of headers and footers (similiar to that of <i>UITableView</i>):
self.barChartView.footerView = ...; // UIView
self.lineChartView.headerView = ...; // UIView
Lastly, any JBChartView subclass can be collapsed or expanded programmatically via the <i>state</i> property. If you chose to animate state changes, a callback helper can be used to notify you when the animation has completed:
- (void)setState:(JBChartViewState)state animated:(BOOL)animated callback:(void (^)())callback;
#### JBBarChartView
A bar chart can be inverted such that it's orientation is top->down (including the selection view) by setting the following property:
@property (nonatomic, assign, getter=isInverted) BOOL inverted;
By default, a chart's bars will be black and flat. They can be customized by supplying a UIView subclass through the <i>optional</i> protocol:
- (UIView *)barChartView:(JBBarChartView *)barChartView barViewAtIndex:(NSUInteger)index
{
return ...; // color of line in chart
}
If you don't require a custom UIView, simply supply a color for the bar instead:
- (UIColor *)barChartView:(JBBarChartView *)barChartView colorForBarViewAtIndex:(NSUInteger)index;
If a solid color isn't your cup of tea, you can expose a gradient to be applied across the entire chart:
- (CAGradientLayer *)barGradientForBarChartView:(JBBarChartView *)barChartView;
Furthermore, the color of the selection bar (on touch events) can be customized via the <i>optional</i> protocol:
- (UIColor *)barSelectionColorForBarChartView:(JBBarChartView *)barChartView
{
return ...; // color of selection view
}
<b>Note</b>: The delegate will request a custom UIView, followed by a color and lastly a gradient. If nothing is supplied, a plain black bar will be used.
Lastly, a bar chart's selection events are delegated back via:
- (void)barChartView:(JBBarChartView *)barChartView didSelectBarAtIndex:(NSUInteger)index touchPoint:(CGPoint)touchPoint
{
// Update view
}
- (void)didDeselectBarChartView:(JBBarChartView *)barChartView
{
// Update view
}
The <b>touchPoint</b> is especially important as it allows you to add custom elements to your chart during selection events. Refer to the demo project (<b>JBarChartViewController</b>) to see how a tooltip can be used to display additional information during selection events.
#### JBLineChartView
The color, width and style of each line in the chart can be customized via the <i>optional</i> protocol:
- (UIColor *)lineChartView:(JBLineChartView *)lineChartView colorForLineAtLineIndex:(NSUInteger)lineIndex
{
return ...; // color of line in chart
}
- (UIColor *)lineChartView:(JBLineChartView *)lineChartView fillColorForLineAtLineIndex:(NSUInteger)lineIndex
{
return ...; // color of area under line in chart
}
- (CGFloat)lineChartView:(JBLineChartView *)lineChartView widthForLineAtLineIndex:(NSUInteger)lineIndex
{
return ...; // width of line in chart
}
- (JBLineChartViewLineStyle)lineChartView:(JBLineChartView *)lineChartView lineStyleForLineAtLineIndex:(NSUInteger)lineIndex
{
return ...; // style of line in chart
}
Additionally, the line style of a line can be customzized via the <i>optional</i> protocol. If a gradient is used, the color for the line and fill of the line will control the alpha value of the gradient.
- (JBLineChartViewLineColorStyle)lineChartView:(JBLineChartView *)lineChartView lineColorStyleForLineAtLineIndex:(NSUInteger)lineIndex
{
return ...; // line style of line in chart
}
- (CAGradientLayer *)lineChartView:(JBLineChartView *)lineChartView gradientForLineAtLineIndex:(NSUInteger)lineIndex {
return ...; // gradient for line in chart
}
- (CAGradientLayer *)lineChartView:(JBLineChartView *)lineChartView fillGradientForLineAtLineIndex:(NSUInteger)lineIndex {
return ...; // gradient for area under line in chart
}
Defining a gradient to use is simple and flexible. For example, this would be a horizontal gradient from blue to green:
CAGradientLayer *gradient = [CAGradientLayer new];
gradient.startPoint = CGPointMake(0.0, 0.0);
gradient.endPoint = CGPointMake(1.0, 0.0);
gradient.colors = @[(id)[UIColor blueColor].CGColor, (id)[UIColor greenColor].CGColor];
Furthermore, the color and width of the selection view along with the color of the selected line can be customized via the <i>optional</i> protocols:
- (UIColor *)lineChartView:(JBLineChartView *)lineChartView verticalSelectionColorForLineAtLineIndex:(NSUInteger)lineIndex
{
return ...; // color of selection view
}
- (CGFloat)verticalSelectionWidthForLineChartView:(JBLineChartView *)lineChartView
{
return ...; // width of selection view
}
- (UIColor *)lineChartView:(JBLineChartView *)lineChartView selectionColorForLineAtLineIndex:(NSUInteger)lineIndex
{
return ...; // color of selected line
}
- (UIColor *)lineChartView:(JBLineChartView *)lineChartView selectionFillColorForLineAtLineIndex:(NSUInteger)lineIndex
{
return ...; // color of area under selected line
}
When using a gradient for the line or fill, a different gradient can provided for selection. If the selection gradient is not provided, it will default to the line and fill gradient provided for the line.
- (CAGradientLayer *)lineChartView:(JBLineChartView *)lineChartView selectionGradientForLineAtLineIndex:(NSUInteger)lineIndex
{
return ...; // gradient for selected line
}
- (CAGradientLayer *)lineChartView:(JBLineChartView *)lineChartView selectionFillGradientForLineAtLineIndex:(NSUInteger)lineIndex
{
return ...; // gradient for area under selected line
}
By default, each line will not show dots for each point. To enable this on a per-line basis:
- (BOOL)lineChartView:(JBLineChartView *)lineChartView showsDotsForLineAtLineIndex:(NSUInteger)lineIndex;
To the radius of each dot (default is 6x the line width, or 3x the diameter), implement:
- (CGFloat)lineChartView:(JBLineChartView *)lineChartView dotRadiusForDotAtHorizontalIndex:(NSUInteger)horizontalIndex atLineIndex:(NSUInteger)lineIndex;
To customize the color of each dot during selection and non-selection events (default is white and black respectively), implement:
- (UIColor *)lineChartView:(JBLineChartView *)lineChartView colorForDotAtHorizontalIndex:(NSUInteger)horizontalIndex atLineIndex:(NSUInteger)lineIndex;
- (UIColor *)lineChartView:(JBLineChartView *)lineChartView selectionColorForDotAtHorizontalIndex:(NSUInteger)horizontalIndex atLineIndex:(NSUInteger)lineIndex;
Alternatively, you can supply your own UIView instead of using the default impelmentation:
- (UIView *)lineChartView:(JBLineChartView *)lineChartView dotViewAtHorizontalIndex:(NSUInteger)horizontalIndex atLineIndex:(NSUInteger)lineIndex;
Custom dot views are automatically shown when selected unless the following is implemented:
- (BOOL)lineChartView:(JBLineChartView *)lineChartView shouldHideDotViewOnSelectionAtHorizontalIndex:(NSUInteger)horizontalIndex atLineIndex:(NSUInteger)lineIndex;
As well, by default, each line will have squared off end caps and connection points. To enable rounded connections and end caps:
- (BOOL)lineChartView:(JBLineChartView *)lineChartView smoothLineAtLineIndex:(NSUInteger)lineIndex;
Furthermore, a line chart's selection events are delegated back via:
- (void)lineChartView:(JBLineChartView *)lineChartView didSelectLineAtIndex:(NSUInteger)lineIndex horizontalIndex:(NSUInteger)horizontalIndex touchPoint:(CGPoint)touchPoint
{
// Update view
}
- (void)didDeselectLineInLineChartView:(JBLineChartView *)lineChartView
{
// Update view
}
Upon selection, all other lines (+ fills) will be dimmed to 20% opacity (default). To change this value, implement:
- (CGFloat)lineChartView:(JBLineChartView *)lineChartView dimmedSelectionOpacityAtLineIndex:(NSUInteger)lineIndex
{
// Return new opacity (0.0 to hide completely, and 1.0 to have no effect)
}
If you don't want a line to be selectable:
- (BOOL)lineChartView:(JBLineChartView *)lineChartView shouldIgnoreSelectionAtIndex:(NSUInteger)lineIndex
{
return NO; // Check line index
}
The <b>touchPoint</b> is especially important as it allows you to add custom elements to your chart during selection events. Refer to the demo project (<b>JBLineChartViewController</b>) to see how a tooltip can be used to display additional information during selection events.
@@ -1,17 +1,19 @@
Pod::Spec.new do |s|
s.name = "JBChartView"
s.version = "1.1.3"
s.version = "2.9.0"
s.summary = "Jawbone's iOS-based charting library for both line and bar graphs."
s.homepage = "https://github.com/Jawbone/JBChartView"
s.screenshot = "https://raw.github.com/Jawbone/JBChartView/master/Screenshots/main.jpg"
s.license = { :type => 'Apache', :file => 'LICENSE' }
s.author = { "Terry Worona" => "tworona@jawbone.com" }
s.source = {
:git => "https://github.com/Jawbone/JBChartView.git",
:tag => "v1.1.3"
:tag => "v2.9.0"
}
s.platform = :ios, '7.0'
s.source_files = 'Classes', 'Classes/**/*.{h,m}'
s.platform = :ios, '6.0'
s.source_files = 'Classes/**/*.{h,m}'
s.requires_arc = true
end
@@ -7,6 +7,8 @@
objects = {
/* Begin PBXBuildFile section */
566C73A61C026858000EC785 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 566C73A51C026858000EC785 /* Default-568h@2x.png */; };
94BDFC3419F933B2007492F6 /* JBLineChartMissingPointsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 94BDFC3319F933B2007492F6 /* JBLineChartMissingPointsViewController.m */; };
9B0725211829822A0052109B /* JBChartListViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B0725201829822A0052109B /* JBChartListViewController.m */; };
9B2E530518218CF20079B9D2 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9B2E530418218CF20079B9D2 /* Foundation.framework */; };
9B2E530718218CF20079B9D2 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9B2E530618218CF20079B9D2 /* CoreGraphics.framework */; };
@@ -15,6 +17,7 @@
9B2E531118218CF20079B9D2 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B2E531018218CF20079B9D2 /* main.m */; };
9B2E532018218CF30079B9D2 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9B2E531F18218CF30079B9D2 /* Images.xcassets */; };
9B2E533F18218D310079B9D2 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B2E533E18218D310079B9D2 /* AppDelegate.m */; };
9B4437AD18D7686800682EF0 /* JBChartTooltipTipView.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B4437AC18D7686800682EF0 /* JBChartTooltipTipView.m */; };
9B603D3E182C6E79000A76D0 /* JBBaseNavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B603D3D182C6E79000A76D0 /* JBBaseNavigationController.m */; };
9B603D47182C7002000A76D0 /* icon-jawbone-logo.png in Resources */ = {isa = PBXBuildFile; fileRef = 9B603D45182C7002000A76D0 /* icon-jawbone-logo.png */; };
9B603D48182C7002000A76D0 /* icon-jawbone-logo@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 9B603D46182C7002000A76D0 /* icon-jawbone-logo@2x.png */; };
@@ -32,13 +35,21 @@
9B6A68DB1829ADE1006DB3BF /* JBBarChartView.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B6A68DA1829ADE1006DB3BF /* JBBarChartView.m */; };
9B6A68DE1829BE63006DB3BF /* JBBarChartViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B6A68DD1829BE63006DB3BF /* JBBarChartViewController.m */; };
9B6A68E11829BED5006DB3BF /* JBLineChartViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B6A68E01829BED5006DB3BF /* JBLineChartViewController.m */; };
9B7967EC198313E30003A2B0 /* JBAreaChartViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B7967EB198313E30003A2B0 /* JBAreaChartViewController.m */; };
9B7967EF198317540003A2B0 /* icon-area-chart.png in Resources */ = {isa = PBXBuildFile; fileRef = 9B7967ED198317540003A2B0 /* icon-area-chart.png */; };
9B7967F0198317540003A2B0 /* icon-area-chart@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 9B7967EE198317540003A2B0 /* icon-area-chart@2x.png */; };
9BD57BBC18D13D1A00ACFA52 /* JBChartTooltipView.m in Sources */ = {isa = PBXBuildFile; fileRef = 9BD57BBB18D13D1A00ACFA52 /* JBChartTooltipView.m */; };
9BE0B0AD182AD26400232023 /* JBLineChartView.m in Sources */ = {isa = PBXBuildFile; fileRef = 9BE0B0AC182AD26400232023 /* JBLineChartView.m */; };
9BE0B0C7182B161000232023 /* JBChartHeaderView.m in Sources */ = {isa = PBXBuildFile; fileRef = 9BE0B0C6182B161000232023 /* JBChartHeaderView.m */; };
9BE0B0CE182B162E00232023 /* JBBarChartFooterView.m in Sources */ = {isa = PBXBuildFile; fileRef = 9BE0B0CD182B162E00232023 /* JBBarChartFooterView.m */; };
9BEBE9D2183167050046E4A8 /* JBChartInformationView.m in Sources */ = {isa = PBXBuildFile; fileRef = 9BEBE9D1183167050046E4A8 /* JBChartInformationView.m */; };
9BEE694618D2789E005D9BA7 /* JBBaseChartViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9BEE694518D2789E005D9BA7 /* JBBaseChartViewController.m */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
566C73A51C026858000EC785 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = "<group>"; };
94BDFC3219F933B2007492F6 /* JBLineChartMissingPointsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JBLineChartMissingPointsViewController.h; sourceTree = "<group>"; };
94BDFC3319F933B2007492F6 /* JBLineChartMissingPointsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JBLineChartMissingPointsViewController.m; sourceTree = "<group>"; };
9B07251F1829822A0052109B /* JBChartListViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JBChartListViewController.h; sourceTree = "<group>"; };
9B0725201829822A0052109B /* JBChartListViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JBChartListViewController.m; sourceTree = "<group>"; };
9B2E530118218CF20079B9D2 /* JBChartViewDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = JBChartViewDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -55,6 +66,8 @@
9B2E533E18218D310079B9D2 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
9B3FBA54182C3B6900CF1C5F /* JBColorConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JBColorConstants.h; sourceTree = "<group>"; };
9B3FBA57182C3BFB00CF1C5F /* JBFontConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JBFontConstants.h; sourceTree = "<group>"; };
9B4437AB18D7686800682EF0 /* JBChartTooltipTipView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JBChartTooltipTipView.h; sourceTree = "<group>"; };
9B4437AC18D7686800682EF0 /* JBChartTooltipTipView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JBChartTooltipTipView.m; sourceTree = "<group>"; };
9B603D3C182C6E79000A76D0 /* JBBaseNavigationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JBBaseNavigationController.h; sourceTree = "<group>"; };
9B603D3D182C6E79000A76D0 /* JBBaseNavigationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JBBaseNavigationController.m; sourceTree = "<group>"; };
9B603D45182C7002000A76D0 /* icon-jawbone-logo.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-jawbone-logo.png"; sourceTree = "<group>"; };
@@ -81,6 +94,12 @@
9B6A68DD1829BE63006DB3BF /* JBBarChartViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JBBarChartViewController.m; sourceTree = "<group>"; };
9B6A68DF1829BED5006DB3BF /* JBLineChartViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JBLineChartViewController.h; sourceTree = "<group>"; };
9B6A68E01829BED5006DB3BF /* JBLineChartViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JBLineChartViewController.m; sourceTree = "<group>"; };
9B7967EA198313E30003A2B0 /* JBAreaChartViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JBAreaChartViewController.h; sourceTree = "<group>"; };
9B7967EB198313E30003A2B0 /* JBAreaChartViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JBAreaChartViewController.m; sourceTree = "<group>"; };
9B7967ED198317540003A2B0 /* icon-area-chart.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-area-chart.png"; sourceTree = "<group>"; };
9B7967EE198317540003A2B0 /* icon-area-chart@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-area-chart@2x.png"; sourceTree = "<group>"; };
9BD57BBA18D13D1A00ACFA52 /* JBChartTooltipView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JBChartTooltipView.h; sourceTree = "<group>"; };
9BD57BBB18D13D1A00ACFA52 /* JBChartTooltipView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JBChartTooltipView.m; sourceTree = "<group>"; };
9BE0B0AB182AD26400232023 /* JBLineChartView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JBLineChartView.h; path = ../../Classes/JBLineChartView.h; sourceTree = "<group>"; };
9BE0B0AC182AD26400232023 /* JBLineChartView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = JBLineChartView.m; path = ../../Classes/JBLineChartView.m; sourceTree = "<group>"; };
9BE0B0C5182B161000232023 /* JBChartHeaderView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JBChartHeaderView.h; sourceTree = "<group>"; };
@@ -92,6 +111,8 @@
9BE0B0D3182B16F700232023 /* JBStringConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JBStringConstants.h; sourceTree = "<group>"; };
9BEBE9D0183167050046E4A8 /* JBChartInformationView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JBChartInformationView.h; sourceTree = "<group>"; };
9BEBE9D1183167050046E4A8 /* JBChartInformationView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JBChartInformationView.m; sourceTree = "<group>"; };
9BEE694418D2789E005D9BA7 /* JBBaseChartViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JBBaseChartViewController.h; sourceTree = "<group>"; };
9BEE694518D2789E005D9BA7 /* JBBaseChartViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JBBaseChartViewController.m; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -174,10 +195,14 @@
isa = PBXGroup;
children = (
9B603D3B182C6E79000A76D0 /* Base */,
9B7967EA198313E30003A2B0 /* JBAreaChartViewController.h */,
9B7967EB198313E30003A2B0 /* JBAreaChartViewController.m */,
9B6A68DC1829BE63006DB3BF /* JBBarChartViewController.h */,
9B6A68DD1829BE63006DB3BF /* JBBarChartViewController.m */,
9B07251F1829822A0052109B /* JBChartListViewController.h */,
9B0725201829822A0052109B /* JBChartListViewController.m */,
94BDFC3219F933B2007492F6 /* JBLineChartMissingPointsViewController.h */,
94BDFC3319F933B2007492F6 /* JBLineChartMissingPointsViewController.m */,
9B6A68DF1829BED5006DB3BF /* JBLineChartViewController.h */,
9B6A68E01829BED5006DB3BF /* JBLineChartViewController.m */,
);
@@ -187,6 +212,8 @@
9B603D3B182C6E79000A76D0 /* Base */ = {
isa = PBXGroup;
children = (
9BEE694418D2789E005D9BA7 /* JBBaseChartViewController.h */,
9BEE694518D2789E005D9BA7 /* JBBaseChartViewController.m */,
9B603D3C182C6E79000A76D0 /* JBBaseNavigationController.h */,
9B603D3D182C6E79000A76D0 /* JBBaseNavigationController.m */,
9B603D4C182C7163000A76D0 /* JBBaseTableViewController.h */,
@@ -208,6 +235,9 @@
9B603D44182C7002000A76D0 /* Images */ = {
isa = PBXGroup;
children = (
566C73A51C026858000EC785 /* Default-568h@2x.png */,
9B7967ED198317540003A2B0 /* icon-area-chart.png */,
9B7967EE198317540003A2B0 /* icon-area-chart@2x.png */,
9B698F07182D720E003C135F /* icon-arrow.png */,
9B698F08182D720E003C135F /* icon-arrow@2x.png */,
9B698F12182D7DAE003C135F /* icon-bar-chart.png */,
@@ -291,6 +321,10 @@
children = (
9BEBE9D0183167050046E4A8 /* JBChartInformationView.h */,
9BEBE9D1183167050046E4A8 /* JBChartInformationView.m */,
9B4437AB18D7686800682EF0 /* JBChartTooltipTipView.h */,
9B4437AC18D7686800682EF0 /* JBChartTooltipTipView.m */,
9BD57BBA18D13D1A00ACFA52 /* JBChartTooltipView.h */,
9BD57BBB18D13D1A00ACFA52 /* JBChartTooltipView.m */,
);
path = Misc;
sourceTree = "<group>";
@@ -321,7 +355,7 @@
9B2E52F918218CF20079B9D2 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0500;
LastUpgradeCheck = 0710;
ORGANIZATIONNAME = Jawbone;
};
buildConfigurationList = 9B2E52FC18218CF20079B9D2 /* Build configuration list for PBXProject "JBChartViewDemo" */;
@@ -353,8 +387,11 @@
9B698F18182D7DAE003C135F /* icon-line-chart.png in Resources */,
9B2E530F18218CF20079B9D2 /* InfoPlist.strings in Resources */,
9B698F17182D7DAE003C135F /* icon-bar-chart@2x.png in Resources */,
9B7967EF198317540003A2B0 /* icon-area-chart.png in Resources */,
9B603D47182C7002000A76D0 /* icon-jawbone-logo.png in Resources */,
9B603D48182C7002000A76D0 /* icon-jawbone-logo@2x.png in Resources */,
566C73A61C026858000EC785 /* Default-568h@2x.png in Resources */,
9B7967F0198317540003A2B0 /* icon-area-chart@2x.png in Resources */,
9B698F19182D7DAE003C135F /* icon-line-chart@2x.png in Resources */,
9B698F0A182D720E003C135F /* icon-arrow@2x.png in Resources */,
);
@@ -378,9 +415,14 @@
9BE0B0C7182B161000232023 /* JBChartHeaderView.m in Sources */,
9B603D4E182C7163000A76D0 /* JBBaseTableViewController.m in Sources */,
9B6A68DE1829BE63006DB3BF /* JBBarChartViewController.m in Sources */,
9B4437AD18D7686800682EF0 /* JBChartTooltipTipView.m in Sources */,
94BDFC3419F933B2007492F6 /* JBLineChartMissingPointsViewController.m in Sources */,
9BE0B0AD182AD26400232023 /* JBLineChartView.m in Sources */,
9BEE694618D2789E005D9BA7 /* JBBaseChartViewController.m in Sources */,
9B6A68E11829BED5006DB3BF /* JBLineChartViewController.m in Sources */,
9B2E533F18218D310079B9D2 /* AppDelegate.m in Sources */,
9B7967EC198313E30003A2B0 /* JBAreaChartViewController.m in Sources */,
9BD57BBC18D13D1A00ACFA52 /* JBChartTooltipView.m in Sources */,
9B603D4B182C7117000A76D0 /* JBBaseViewController.m in Sources */,
9B0725211829822A0052109B /* JBChartListViewController.m in Sources */,
);
@@ -404,7 +446,6 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)";
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
@@ -419,6 +460,7 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;
@@ -444,7 +486,6 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)";
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
@@ -482,7 +523,8 @@
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "JBChartViewDemo/JBChartViewDemo-Prefix.pch";
INFOPLIST_FILE = "JBChartViewDemo/JBChartViewDemo-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
IPHONEOS_DEPLOYMENT_TARGET = 6.0;
PRODUCT_BUNDLE_IDENTIFIER = "com.jawbone.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
};
@@ -496,7 +538,8 @@
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "JBChartViewDemo/JBChartViewDemo-Prefix.pch";
INFOPLIST_FILE = "JBChartViewDemo/JBChartViewDemo-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
IPHONEOS_DEPLOYMENT_TARGET = 6.0;
PRODUCT_BUNDLE_IDENTIFIER = "com.jawbone.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
};
@@ -10,7 +10,8 @@
typedef NS_ENUM(NSInteger, JBChartTableCellType){
JBChartTableCellTypeLineChart,
JBChartTableCellTypeBarChart
JBChartTableCellTypeBarChart,
JBChartTableCellTypeAreaChart
};
@interface JBChartTableCell : UITableViewCell
@@ -22,7 +22,21 @@
- (void)setType:(JBChartTableCellType)type
{
_type = type;
self.accessoryView = [[UIImageView alloc] initWithImage:_type == JBChartTableCellTypeBarChart ? [UIImage imageNamed:kJBImageIconBarChart] : [UIImage imageNamed:kJBImageIconLineChart]];
UIImage *image = nil;
switch (type) {
case JBChartTableCellTypeBarChart:
image = [UIImage imageNamed:kJBImageIconBarChart];
break;
case JBChartTableCellTypeLineChart:
image = [UIImage imageNamed:kJBImageIconLineChart];
break;
case JBChartTableCellTypeAreaChart:
image = [UIImage imageNamed:kJBImageIconAreaChart];
break;
default:
break;
}
self.accessoryView = [[UIImageView alloc] initWithImage:image];
}
@end
@@ -21,10 +21,39 @@
#define kJBColorBarChartBarGreen UIColorFromHex(0x34b234)
#define kJBColorBarChartHeaderSeparatorColor UIColorFromHex(0x686868)
#pragma mark - Line Char
#pragma mark - Line Chart
#define kJBColorLineChartControllerBackground UIColorFromHex(0xb7e3e4)
#define kJBColorLineChartBackground UIColorFromHex(0xb7e3e4)
#define kJBColorLineChartHeader UIColorFromHex(0x1c474e)
#define kJBColorLineChartHeaderSeparatorColor UIColorFromHex(0x8eb6b7)
#define kJBColorLineChartLineColor [UIColor colorWithWhite:1.0 alpha:0.5]
#define kJBColorLineChartDefaultSolidLineColor [UIColor colorWithWhite:1.0 alpha:0.5]
#define kJBColorLineChartDefaultSolidSelectedLineColor [UIColor colorWithWhite:1.0 alpha:1.0]
#define kJBColorLineChartDefaultDashedLineColor [UIColor colorWithRed:0.0 green:0.0 blue:1.0 alpha:1.0]
#define kJBColorLineChartDefaultDashedSelectedLineColor [UIColor colorWithWhite:1.0 alpha:1.0]
#define kJBColorLineChartDefaultSolidFillColor [UIColor clearColor]
#define kJBColorLineChartDefaultDashedFillColor [UIColor colorWithWhite:1.0 alpha:0.3]
#define kJBColorLineChartDefaultGradientStartColor UIColorFromHex(0x0000FF)
#define kJBColorLineChartDefaultGradientEndColor UIColorFromHex(0x00FF00)
#define kJBColorLineChartDefaultFillGradientStartColor UIColorFromHex(0xFFFFFF)
#define kJBColorLineChartDefaultFillGradientEndColor UIColorFromHex(0xbe0000)
#define mark - Area Chart
#define kJBColorAreaChartControllerBackground UIColorFromHex(0xb7e3e4)
#define kJBColorAreaChartBackground UIColorFromHex(0xb7e3e4)
#define kJBColorAreaChartHeader UIColorFromHex(0x1c474e)
#define kJBColorAreaChartHeaderSeparatorColor UIColorFromHex(0x8eb6b7)
#define kJBColorAreaChartDefaultSunLineColor [UIColor clearColor]
#define kJBColorAreaChartDefaultSunAreaColor [UIColorFromHex(0xfcfb3a) colorWithAlphaComponent:0.5]
#define kJBColorAreaChartDefaultSunSelectedLineColor [UIColor clearColor]
#define kJBColorAreaChartDefaultSunSelectedAreaColor UIColorFromHex(0xfcfb3a)
#define kJBColorAreaChartDefaultMoonLineColor [UIColor clearColor]
#define kJBColorAreaChartDefaultMoonAreaColor [[UIColor blackColor] colorWithAlphaComponent:0.5]
#define kJBColorAreaChartDefaultMoonSelectedLineColor [UIColor clearColor]
#define kJBColorAreaChartDefaultMoonSelectedAreaColor [UIColor blackColor]
#pragma mark - Tooltips
#define kJBColorTooltipColor [UIColor colorWithWhite:1.0 alpha:0.9]
#define kJBColorTooltipTextColor UIColorFromHex(0x313131)
@@ -21,3 +21,7 @@
#define kJBFontInformationTitle [UIFont fontWithName:@"HelveticaNeue" size:20]
#define kJBFontInformationValue [UIFont fontWithName:@"HelveticaNeue-CondensedBold" size:100]
#define kJBFontInformationUnit [UIFont fontWithName:@"HelveticaNeue" size:60]
#pragma mark - Tooltip
#define kJBFontTooltipText [UIFont fontWithName:@"HelveticaNeue-Bold" size:14]
@@ -10,11 +10,40 @@
#pragma mark - Labels
#define kJBStringLabel1987 localize(@"label.1985", @"1987")
#pragma mark - Labels (Bar Chart)
#define kJBStringLabel2012 localize(@"label.2012", @"2012")
#define kJBStringLabelAverageMonthlyTemperature localize(@"label.average.monthly.temperature", @"Average Monthly Temperature")
#define kJBStringLabelWorldwide2012 localize(@"label.worldwide.2013", @"Worldwide - 2012")
#define kJBStringLabelWorldwide2011 localize(@"label.worldwide.2013", @"Worldwide - 2011")
#define kJBStringLabelWorldwideAverage localize(@"label.worldwide.average", @"Worldwide Average")
#define kJBStringLabelDegreesFahrenheit localize(@"label.degrees.fahrenheit", @"%d%@F")
#define kJBStringLabelDegreeSymbol localize(@"label.degree.symbol", @"\u00B0")
#pragma mark - Labels (Line Chart)
#define kJBStringLabel2013 localize(@"label.2013", @"2013")
#define kJBStringLabeJanuary localize(@"label.january", @"January")
#define kJBStringLabelDecember localize(@"label.august", @"December")
#define kJBStringLabelAverageMonthlyRainfall localize(@"label.annual.monthly.rainfall", @"Average Monthly Rainfall")
#define kJBStringLabelAverageAnnualRainfall localize(@"label.average.annual.rainfall", @"Average Annual Rainfall")
#define kJBStringLabelSanFrancisco localize(@"label.san.francisco", @"San Francisco")
#define kJBStringLabelSanFrancisco2013 localize(@"label.san.francisco.2013", @"San Francisco - 2013")
#define kJBStringLabelAverageDailyRainfall localize(@"label.average.daily.rainfall", @"Average Daily Rainfall")
#define kJBStringLabelMm localize(@"label.mm", @"mm")
#define kJBStringLabelMetropolitanAverage localize(@"label.metropolitan.average", @"Metropolitan Average")
#define kJBStringLabelNationalAverage localize(@"label.national.average", @"National Average")
#pragma mark - Labels (Area Chart)
#define kJBStringLabel2011 localize(@"label.2011", @"2011")
#define kJBStringLabelSeattle2014 localize(@"label.seattle.2014", @"Seattle - 2014")
#define kJBStringLabelAverageShineHoursOfSunMoon localize(@"label.average.shine.hours.of.sun.moon", @"Average Shine Hours of Sun/Moon")
#define kJBStringLabelAverageShineHours localize(@"label.average.shine.hours", @"Average Shine Hours")
#define kJBStringLabelHours localize(@"label.hours", @"h")
#define kJBStringLabelMoon localize(@"label.moon", @"Moon")
#define kJBStringLabelSun localize(@"label.sun", @"Sun")
#pragma mark - Labels (Missing Points Line Chart)
#define kJBStringLabel2014 localize(@"label.2014", @"2014")
#define kJBStringLabelCyclingDistances localize(@"label.cycling.distances", @"Cycling Distances")
#define kJBStringLabelCyclingCurrentLastWeek2014 localize(@"label.cycling.current.last.week.2014", @"Current/Last Week - 2014")
#define kJBStringLabelKm2014 localize(@"label.km", @"Km")
#define kJBStringLabelLastWeek localize(@"label.last.week", @"Last Week")
#define kJBStringLabelCurrentWeek localize(@"label.current.week", @"Current Week")
@@ -6,14 +6,10 @@
// Copyright (c) 2013 Jawbone. All rights reserved.
//
#pragma mark - Numerics
#define kJBNumericDefaultPadding 10.0f
#define kJBNumericDefaultAnimationDuration 0.25f
#pragma mark - Images
#define kJBImageIconJawboneLogo @"icon-jawbone-logo.png"
#define kJBImageIconArrow @"icon-arrow.png"
#define kJBImageIconLineChart @"icon-line-chart.png"
#define kJBImageIconBarChart @"icon-bar-chart.png"
#define kJBImageIconAreaChart @"icon-area-chart.png"
@@ -0,0 +1,27 @@
//
// JBBaseChartViewController.h
// JBChartViewDemo
//
// Created by Terry Worona on 3/13/14.
// Copyright (c) 2014 Jawbone. All rights reserved.
//
#import "JBBaseViewController.h"
// Views
#import "JBChartTooltipView.h"
#import "JBChartView.h"
@interface JBBaseChartViewController : JBBaseViewController
@property (nonatomic, strong, readonly) JBChartTooltipView *tooltipView;
@property (nonatomic, assign) BOOL tooltipVisible;
// Settres
- (void)setTooltipVisible:(BOOL)tooltipVisible animated:(BOOL)animated atTouchPoint:(CGPoint)touchPoint;
- (void)setTooltipVisible:(BOOL)tooltipVisible animated:(BOOL)animated;
// Getters
- (JBChartView *)chartView; // subclasses to return chart instance for tooltip functionality
@end
@@ -0,0 +1,137 @@
//
// JBBaseChartViewController.m
// JBChartViewDemo
//
// Created by Terry Worona on 3/13/14.
// Copyright (c) 2014 Jawbone. All rights reserved.
//
#import "JBBaseChartViewController.h"
// Views
#import "JBChartTooltipTipView.h"
// Numerics
CGFloat const kJBBaseChartViewControllerAnimationDuration = 0.1f;
@interface JBBaseChartViewController ()
@property (nonatomic, strong) JBChartTooltipView *tooltipView;
@property (nonatomic, strong) JBChartTooltipTipView *tooltipTipView;
@end
@implementation JBBaseChartViewController
#pragma mark - Setters
- (void)setTooltipVisible:(BOOL)tooltipVisible animated:(BOOL)animated atTouchPoint:(CGPoint)touchPoint
{
_tooltipVisible = tooltipVisible;
JBChartView *chartView = [self chartView];
if (!chartView)
{
return;
}
if (!self.tooltipView)
{
self.tooltipView = [[JBChartTooltipView alloc] init];
self.tooltipView.alpha = 0.0;
[self.view addSubview:self.tooltipView];
}
[self.view bringSubviewToFront:self.tooltipView];
if (!self.tooltipTipView)
{
self.tooltipTipView = [[JBChartTooltipTipView alloc] init];
self.tooltipTipView.alpha = 0.0;
[self.view addSubview:self.tooltipTipView];
}
[self.view bringSubviewToFront:self.tooltipTipView];
dispatch_block_t adjustTooltipPosition = ^{
CGPoint originalTouchPoint = [self.view convertPoint:touchPoint fromView:chartView];
CGPoint convertedTouchPoint = originalTouchPoint; // modified
JBChartView *chartView = [self chartView];
if (chartView && !CGPointEqualToPoint(touchPoint, CGPointZero))
{
CGFloat minChartX = (chartView.frame.origin.x + ceil(self.tooltipView.frame.size.width * 0.5));
if (convertedTouchPoint.x < minChartX)
{
convertedTouchPoint.x = minChartX;
}
CGFloat maxChartX = (chartView.frame.origin.x + chartView.frame.size.width - ceil(self.tooltipView.frame.size.width * 0.5));
if (convertedTouchPoint.x > maxChartX)
{
convertedTouchPoint.x = maxChartX;
}
self.tooltipView.frame = CGRectMake(convertedTouchPoint.x - ceil(self.tooltipView.frame.size.width * 0.5), CGRectGetMaxY(chartView.headerView.frame), self.tooltipView.frame.size.width, self.tooltipView.frame.size.height);
CGFloat minTipX = (chartView.frame.origin.x + self.tooltipTipView.frame.size.width);
if (originalTouchPoint.x < minTipX)
{
originalTouchPoint.x = minTipX;
}
CGFloat maxTipX = (chartView.frame.origin.x + chartView.frame.size.width - self.tooltipTipView.frame.size.width);
if (originalTouchPoint.x > maxTipX)
{
originalTouchPoint.x = maxTipX;
}
self.tooltipTipView.frame = CGRectMake(originalTouchPoint.x - ceil(self.tooltipTipView.frame.size.width * 0.5), CGRectGetMaxY(self.tooltipView.frame), self.tooltipTipView.frame.size.width, self.tooltipTipView.frame.size.height);
}
};
dispatch_block_t adjustTooltipVisibility = ^{
self.tooltipView.alpha = _tooltipVisible ? 1.0 : 0.0;
self.tooltipTipView.alpha = _tooltipVisible ? 1.0 : 0.0;
};
if (animated)
{
if (tooltipVisible)
{
adjustTooltipPosition();
}
[UIView animateWithDuration:kJBBaseChartViewControllerAnimationDuration delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
adjustTooltipVisibility();
} completion:^(BOOL finished) {
if (!tooltipVisible)
{
adjustTooltipPosition();
}
}];
}
else
{
adjustTooltipPosition();
adjustTooltipVisibility();
}
}
- (void)setTooltipVisible:(BOOL)tooltipVisible animated:(BOOL)animated
{
[self setTooltipVisible:tooltipVisible animated:animated atTouchPoint:CGPointZero];
}
- (void)setTooltipVisible:(BOOL)tooltipVisible
{
[self setTooltipVisible:tooltipVisible animated:NO];
}
#pragma mark - Getters
- (JBChartView *)chartView
{
// Subclasses should return chart instance for tooltip functionality
return nil;
}
@end
@@ -8,6 +8,10 @@
#import "JBBaseNavigationController.h"
// Numerics
NSInteger const kJBBaseNavigationControllerBarTintColorMinSystemVersion = 7;
NSInteger const kJBBaseNavigationControllerTintColorMinSystemVersion = 7;
@implementation JBBaseNavigationController
#pragma mark - Alloc/Init
@@ -18,8 +22,23 @@
if (self)
{
self.navigationBar.translucent = NO;
[[UINavigationBar appearance] setBarTintColor:kJBColorNavigationTint];
[[UINavigationBar appearance] setTintColor:kJBColorNavigationBarTint];
// Bar tint (iOS 7)
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= kJBBaseNavigationControllerBarTintColorMinSystemVersion)
{
[[UINavigationBar appearance] setBarTintColor:kJBColorNavigationTint];
}
// Tint (iOS 7)
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= kJBBaseNavigationControllerTintColorMinSystemVersion)
{
[[UINavigationBar appearance] setTintColor:kJBColorNavigationBarTint];
}
if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)])
{
self.interactivePopGestureRecognizer.enabled = NO;
}
}
return self;
}
@@ -28,6 +28,12 @@
[self.view addSubview:self.tableView];
}
- (void)dealloc
{
self.tableView.delegate = nil;
self.tableView.dataSource = nil;
}
#pragma mark - UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
@@ -19,7 +19,9 @@
- (void)loadView
{
[super loadView];
self.edgesForExtendedLayout = UIRectEdgeTop;
if ([self respondsToSelector:@selector(setEdgesForExtendedLayout:)]) {
self.edgesForExtendedLayout = UIRectEdgeTop;
}
self.view.backgroundColor = [UIColor whiteColor];
self.navigationItem.titleView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:kJBImageIconJawboneLogo]];
}
@@ -31,7 +33,7 @@
return YES;
}
- (NSUInteger)supportedInterfaceOrientations
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
@@ -0,0 +1,13 @@
//
// JBAreaChartViewController.h
// JBChartViewDemo
//
// Created by Lars Ott on 21.04.14.
// Copyright (c) 2014 Jawbone. All rights reserved.
//
#import "JBBaseChartViewController.h"
@interface JBAreaChartViewController : JBBaseChartViewController
@end
@@ -0,0 +1,305 @@
//
// JBAreaChartViewController.m
// JBChartViewDemo
//
// Created by Lars Ott on 21.04.14.
// Copyright (c) 2014 Jawbone. All rights reserved.
//
#import "JBAreaChartViewController.h"
// Views
#import "JBLineChartView.h"
#import "JBChartHeaderView.h"
#import "JBLineChartFooterView.h"
#import "JBChartInformationView.h"
#define ARC4RANDOM_MAX 0x100000000
typedef NS_ENUM(NSInteger, JBLineChartLine){
JBLineChartLineSun,
JBLineChartLineMoon,
JBLineChartLineCount
};
// Numerics
CGFloat const kJBAreaChartViewControllerChartHeight = 250.0f;
CGFloat const kJBAreaChartViewControllerChartPadding = 10.0f;
CGFloat const kJBAreaChartViewControllerChartHeaderHeight = 75.0f;
CGFloat const kJBAreaChartViewControllerChartHeaderPadding = 20.0f;
CGFloat const kJBAreaChartViewControllerChartFooterHeight = 20.0f;
CGFloat const kJBAreaChartViewControllerChartLineWidth = 2.0f;
CGFloat const kJBAreaChartViewControllerChartSunLineDimmedOpacity = 1.0f;
CGFloat const kJBAreaChartViewControllerChartMoonLineDimmedOpacity = 0.0f;
NSInteger const kJBAreaChartViewControllerMaxNumChartPoints = 12;
// Strings
NSString * const kJBAreaChartViewControllerNavButtonViewKey = @"view";
@interface JBAreaChartViewController () <JBLineChartViewDelegate, JBLineChartViewDataSource>
@property (nonatomic, strong) JBLineChartView *lineChartView;
@property (nonatomic, strong) JBChartInformationView *informationView;
@property (nonatomic, strong) NSArray *chartData;
@property (nonatomic, strong) NSArray *monthlySymbols;
// Buttons
- (void)chartToggleButtonPressed:(id)sender;
// Helpers
- (void)initFakeData;
- (NSArray *)largestLineData; // largest collection of fake line data
@end
@implementation JBAreaChartViewController
#pragma mark - Alloc/Init
- (id)init
{
self = [super init];
if (self)
{
[self initFakeData];
}
return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self)
{
[self initFakeData];
}
return self;
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
[self initFakeData];
}
return self;
}
- (void)dealloc
{
_lineChartView.delegate = nil;
_lineChartView.dataSource = nil;
}
#pragma mark - Data
- (void)initFakeData
{
NSMutableArray *mutableLineCharts = [NSMutableArray array];
for (int lineIndex=0; lineIndex<JBLineChartLineCount; lineIndex++)
{
NSMutableArray *mutableChartData = [NSMutableArray array];
for (int i=0; i<kJBAreaChartViewControllerMaxNumChartPoints; i++)
{
[mutableChartData addObject:[NSNumber numberWithFloat:((double)arc4random() / ARC4RANDOM_MAX) * 12]]; // random number between 0 and 12
}
[mutableLineCharts addObject:mutableChartData];
}
_chartData = [NSArray arrayWithArray:mutableLineCharts];
_monthlySymbols = [[[NSDateFormatter alloc] init] shortMonthSymbols];
}
- (NSArray *)largestLineData
{
NSArray *largestLineData = nil;
for (NSArray *lineData in self.chartData)
{
if ([lineData count] > [largestLineData count])
{
largestLineData = lineData;
}
}
return largestLineData;
}
#pragma mark - View Lifecycle
- (void)loadView
{
[super loadView];
self.view.backgroundColor = kJBColorLineChartControllerBackground;
self.navigationItem.rightBarButtonItem = [self chartToggleButtonWithTarget:self action:@selector(chartToggleButtonPressed:)];
self.lineChartView = [[JBLineChartView alloc] init];
self.lineChartView.frame = CGRectMake(kJBAreaChartViewControllerChartPadding, kJBAreaChartViewControllerChartPadding, self.view.bounds.size.width - (kJBAreaChartViewControllerChartPadding * 2), kJBAreaChartViewControllerChartHeight);
self.lineChartView.delegate = self;
self.lineChartView.dataSource = self;
self.lineChartView.headerPadding =kJBAreaChartViewControllerChartHeaderPadding;
self.lineChartView.backgroundColor = kJBColorLineChartBackground;
JBChartHeaderView *headerView = [[JBChartHeaderView alloc] initWithFrame:CGRectMake(kJBAreaChartViewControllerChartPadding, ceil(self.view.bounds.size.height * 0.5) - ceil(kJBAreaChartViewControllerChartHeaderHeight * 0.5), self.view.bounds.size.width - (kJBAreaChartViewControllerChartPadding * 2), kJBAreaChartViewControllerChartHeaderHeight)];
headerView.titleLabel.text = [kJBStringLabelAverageShineHoursOfSunMoon uppercaseString];
headerView.titleLabel.textColor = kJBColorLineChartHeader;
headerView.titleLabel.shadowColor = [UIColor colorWithWhite:1.0 alpha:0.25];
headerView.titleLabel.shadowOffset = CGSizeMake(0, 1);
headerView.subtitleLabel.text = kJBStringLabel2011;
headerView.subtitleLabel.textColor = kJBColorLineChartHeader;
headerView.subtitleLabel.shadowColor = [UIColor colorWithWhite:1.0 alpha:0.25];
headerView.subtitleLabel.shadowOffset = CGSizeMake(0, 1);
headerView.separatorColor = kJBColorLineChartHeaderSeparatorColor;
self.lineChartView.headerView = headerView;
JBLineChartFooterView *footerView = [[JBLineChartFooterView alloc] initWithFrame:CGRectMake(kJBAreaChartViewControllerChartPadding, ceil(self.view.bounds.size.height * 0.5) - ceil(kJBAreaChartViewControllerChartFooterHeight * 0.5), self.view.bounds.size.width - (kJBAreaChartViewControllerChartPadding * 2), kJBAreaChartViewControllerChartFooterHeight)];
footerView.backgroundColor = [UIColor clearColor];
footerView.leftLabel.text = [[self.monthlySymbols firstObject] uppercaseString];
footerView.leftLabel.textColor = [UIColor whiteColor];
footerView.rightLabel.text = [[self.monthlySymbols lastObject] uppercaseString];;
footerView.rightLabel.textColor = [UIColor whiteColor];
footerView.sectionCount = [[self chartData] count];
self.lineChartView.footerView = footerView;
[self.view addSubview:self.lineChartView];
self.informationView = [[JBChartInformationView alloc] initWithFrame:CGRectMake(self.view.bounds.origin.x, CGRectGetMaxY(self.lineChartView.frame), self.view.bounds.size.width, self.view.bounds.size.height - CGRectGetMaxY(self.lineChartView.frame) - CGRectGetMaxY(self.navigationController.navigationBar.frame))];
[self.informationView setValueAndUnitTextColor:[UIColor colorWithWhite:1.0 alpha:0.75]];
[self.informationView setTitleTextColor:kJBColorLineChartHeader];
[self.informationView setTextShadowColor:nil];
[self.informationView setSeparatorColor:kJBColorLineChartHeaderSeparatorColor];
[self.view addSubview:self.informationView];
[self.lineChartView reloadData];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.lineChartView setState:JBChartViewStateExpanded];
}
#pragma mark - JBLineChartViewDataSource
- (NSUInteger)numberOfLinesInLineChartView:(JBLineChartView *)lineChartView
{
return [self.chartData count];
}
- (NSUInteger)lineChartView:(JBLineChartView *)lineChartView numberOfVerticalValuesAtLineIndex:(NSUInteger)lineIndex
{
return [[self.chartData objectAtIndex:lineIndex] count];
}
- (BOOL)lineChartView:(JBLineChartView *)lineChartView showsDotsForLineAtLineIndex:(NSUInteger)lineIndex
{
return NO;
}
- (BOOL)lineChartView:(JBLineChartView *)lineChartView smoothLineAtLineIndex:(NSUInteger)lineIndex
{
return YES;
}
- (CGFloat)lineChartView:(JBLineChartView *)lineChartView dimmedSelectionOpacityAtLineIndex:(NSUInteger)lineIndex
{
if (lineIndex == JBLineChartLineMoon)
{
return kJBAreaChartViewControllerChartMoonLineDimmedOpacity;
}
else
{
return kJBAreaChartViewControllerChartSunLineDimmedOpacity;
}
}
#pragma mark - JBLineChartViewDelegate
- (CGFloat)lineChartView:(JBLineChartView *)lineChartView verticalValueForHorizontalIndex:(NSUInteger)horizontalIndex atLineIndex:(NSUInteger)lineIndex
{
return [[[self.chartData objectAtIndex:lineIndex] objectAtIndex:horizontalIndex] floatValue];
}
- (void)lineChartView:(JBLineChartView *)lineChartView didSelectLineAtIndex:(NSUInteger)lineIndex horizontalIndex:(NSUInteger)horizontalIndex touchPoint:(CGPoint)touchPoint
{
NSNumber *valueNumber = [[self.chartData objectAtIndex:lineIndex] objectAtIndex:horizontalIndex];
[self.informationView setValueText:[NSString stringWithFormat:@"%.1f", [valueNumber floatValue]] unitText:kJBStringLabelHours];
[self.informationView setTitleText:lineIndex == JBLineChartLineSun ? kJBStringLabelSun : kJBStringLabelMoon];
[self.informationView setHidden:NO animated:YES];
[self setTooltipVisible:YES animated:YES atTouchPoint:touchPoint];
[self.tooltipView setText:[[self.monthlySymbols objectAtIndex:horizontalIndex] uppercaseString]];
}
- (void)didDeselectLineInLineChartView:(JBLineChartView *)lineChartView
{
[self.informationView setHidden:YES animated:YES];
[self setTooltipVisible:NO animated:YES];
}
- (UIColor *)lineChartView:(JBLineChartView *)lineChartView colorForLineAtLineIndex:(NSUInteger)lineIndex
{
return (lineIndex == JBLineChartLineSun) ? kJBColorAreaChartDefaultSunLineColor: kJBColorAreaChartDefaultMoonLineColor;
}
- (UIColor *)lineChartView:(JBLineChartView *)lineChartView fillColorForLineAtLineIndex:(NSUInteger)lineIndex
{
return (lineIndex == JBLineChartLineSun) ? kJBColorAreaChartDefaultSunAreaColor : kJBColorAreaChartDefaultMoonAreaColor;
}
- (UIColor *)lineChartView:(JBLineChartView *)lineChartView colorForDotAtHorizontalIndex:(NSUInteger)horizontalIndex atLineIndex:(NSUInteger)lineIndex
{
return (lineIndex == JBLineChartLineSun) ? kJBColorAreaChartDefaultSunLineColor: kJBColorAreaChartDefaultMoonLineColor;
}
- (CGFloat)lineChartView:(JBLineChartView *)lineChartView widthForLineAtLineIndex:(NSUInteger)lineIndex
{
return kJBAreaChartViewControllerChartLineWidth;
}
- (UIColor *)lineChartView:(JBLineChartView *)lineChartView verticalSelectionColorForLineAtLineIndex:(NSUInteger)lineIndex
{
return [UIColor whiteColor];
}
- (UIColor *)lineChartView:(JBLineChartView *)lineChartView selectionColorForLineAtLineIndex:(NSUInteger)lineIndex
{
return (lineIndex == JBLineChartLineSun) ? kJBColorAreaChartDefaultSunSelectedLineColor: kJBColorAreaChartDefaultMoonSelectedLineColor;
}
- (UIColor *)lineChartView:(JBLineChartView *)lineChartView selectionFillColorForLineAtLineIndex:(NSUInteger)lineIndex
{
return (lineIndex == JBLineChartLineSun) ? kJBColorAreaChartDefaultSunSelectedAreaColor : kJBColorAreaChartDefaultMoonSelectedAreaColor;
}
- (UIColor *)lineChartView:(JBLineChartView *)lineChartView selectionColorForDotAtHorizontalIndex:(NSUInteger)horizontalIndex atLineIndex:(NSUInteger)lineIndex
{
return (lineIndex == JBLineChartLineSun) ? kJBColorAreaChartDefaultSunSelectedLineColor: kJBColorAreaChartDefaultMoonSelectedLineColor;
}
- (JBLineChartViewLineStyle)lineChartView:(JBLineChartView *)lineChartView lineStyleForLineAtLineIndex:(NSUInteger)lineIndex
{
return JBLineChartViewLineStyleSolid;
}
#pragma mark - Buttons
- (void)chartToggleButtonPressed:(id)sender
{
UIView *buttonImageView = [self.navigationItem.rightBarButtonItem valueForKey:kJBAreaChartViewControllerNavButtonViewKey];
buttonImageView.userInteractionEnabled = NO;
CGAffineTransform transform = self.lineChartView.state == JBChartViewStateExpanded ? CGAffineTransformMakeRotation(M_PI) : CGAffineTransformMakeRotation(0);
buttonImageView.transform = transform;
[self.lineChartView setState:self.lineChartView.state == JBChartViewStateExpanded ? JBChartViewStateCollapsed : JBChartViewStateExpanded animated:YES callback:^{
buttonImageView.userInteractionEnabled = YES;
}];
}
#pragma mark - Overrides
- (JBChartView *)chartView
{
return self.lineChartView;
}
@end
@@ -6,8 +6,8 @@
// Copyright (c) 2013 Jawbone. All rights reserved.
//
#import "JBBaseViewController.h"
#import "JBBaseChartViewController.h"
@interface JBBarChartViewController : JBBaseViewController
@interface JBBarChartViewController : JBBaseChartViewController
@end
@@ -16,14 +16,15 @@
// Numerics
CGFloat const kJBBarChartViewControllerChartHeight = 250.0f;
CGFloat const kJBBarChartViewControllerChartPadding = 10.0f;
CGFloat const kJBBarChartViewControllerChartHeaderHeight = 80.0f;
CGFloat const kJBBarChartViewControllerChartHeaderPadding = 10.0f;
CGFloat const kJBBarChartViewControllerChartHeaderPadding = 20.0f;
CGFloat const kJBBarChartViewControllerChartFooterHeight = 25.0f;
CGFloat const kJBBarChartViewControllerChartFooterPadding = 5.0f;
CGFloat const kJBBarChartViewControllerBarPadding = 1;
CGFloat const kJBBarChartViewControllerBarPadding = 1.0f;
NSInteger const kJBBarChartViewControllerNumBars = 12;
NSInteger const kJBBarChartViewControllerMaxBarHeight = 100; // max random value
NSInteger const kJBBarChartViewControllerMinBarHeight = 20;
NSInteger const kJBBarChartViewControllerMaxBarHeight = 10;
NSInteger const kJBBarChartViewControllerMinBarHeight = 5;
// Strings
NSString * const kJBBarChartViewControllerNavButtonViewKey = @"view";
@@ -52,12 +53,37 @@ NSString * const kJBBarChartViewControllerNavButtonViewKey = @"view";
self = [super init];
if (self)
{
[self initFakeData]; // fake rain data
_monthlySymbols = [[[NSDateFormatter alloc] init] monthSymbols];
[self initFakeData];
}
return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self)
{
[self initFakeData];
}
return self;
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
[self initFakeData];
}
return self;
}
- (void)dealloc
{
_barChartView.delegate = nil;
_barChartView.dataSource = nil;
}
#pragma mark - Date
- (void)initFakeData
@@ -65,9 +91,12 @@ NSString * const kJBBarChartViewControllerNavButtonViewKey = @"view";
NSMutableArray *mutableChartData = [NSMutableArray array];
for (int i=0; i<kJBBarChartViewControllerNumBars; i++)
{
[mutableChartData addObject:[NSNumber numberWithFloat:MAX(kJBBarChartViewControllerMinBarHeight, arc4random() % kJBBarChartViewControllerMaxBarHeight)]]; // fake height
NSInteger delta = (kJBBarChartViewControllerNumBars - labs((kJBBarChartViewControllerNumBars - i) - i)) + 2;
[mutableChartData addObject:[NSNumber numberWithFloat:MAX((delta * kJBBarChartViewControllerMinBarHeight), arc4random() % (delta * kJBBarChartViewControllerMaxBarHeight))]];
}
_chartData = [NSArray arrayWithArray:mutableChartData];
_monthlySymbols = [[[NSDateFormatter alloc] init] shortMonthSymbols];
}
#pragma mark - View Lifecycle
@@ -79,23 +108,26 @@ NSString * const kJBBarChartViewControllerNavButtonViewKey = @"view";
self.view.backgroundColor = kJBColorBarChartControllerBackground;
self.navigationItem.rightBarButtonItem = [self chartToggleButtonWithTarget:self action:@selector(chartToggleButtonPressed:)];
self.barChartView = [[JBBarChartView alloc] initWithFrame:CGRectMake(kJBNumericDefaultPadding, kJBNumericDefaultPadding, self.view.bounds.size.width - (kJBNumericDefaultPadding * 2), kJBBarChartViewControllerChartHeight)];
self.barChartView = [[JBBarChartView alloc] init];
self.barChartView.frame = CGRectMake(kJBBarChartViewControllerChartPadding, kJBBarChartViewControllerChartPadding, self.view.bounds.size.width - (kJBBarChartViewControllerChartPadding * 2), kJBBarChartViewControllerChartHeight);
self.barChartView.delegate = self;
self.barChartView.dataSource = self;
self.barChartView.headerPadding = kJBBarChartViewControllerChartHeaderPadding;
self.barChartView.minimumValue = 0.0f;
self.barChartView.inverted = NO;
self.barChartView.backgroundColor = kJBColorBarChartBackground;
JBChartHeaderView *headerView = [[JBChartHeaderView alloc] initWithFrame:CGRectMake(kJBNumericDefaultPadding, ceil(self.view.bounds.size.height * 0.5) - ceil(kJBBarChartViewControllerChartHeaderHeight * 0.5), self.view.bounds.size.width - (kJBNumericDefaultPadding * 2), kJBBarChartViewControllerChartHeaderHeight)];
headerView.titleLabel.text = [kJBStringLabelAverageMonthlyRainfall uppercaseString];
headerView.subtitleLabel.text = [NSString stringWithFormat:@"%@ - %@", kJBStringLabelSanFrancisco, kJBStringLabel2013];
JBChartHeaderView *headerView = [[JBChartHeaderView alloc] initWithFrame:CGRectMake(kJBBarChartViewControllerChartPadding, ceil(self.view.bounds.size.height * 0.5) - ceil(kJBBarChartViewControllerChartHeaderHeight * 0.5), self.view.bounds.size.width - (kJBBarChartViewControllerChartPadding * 2), kJBBarChartViewControllerChartHeaderHeight)];
headerView.titleLabel.text = [kJBStringLabelAverageMonthlyTemperature uppercaseString];
headerView.subtitleLabel.text = kJBStringLabel2012;
headerView.separatorColor = kJBColorBarChartHeaderSeparatorColor;
self.barChartView.headerView = headerView;
JBBarChartFooterView *footerView = [[JBBarChartFooterView alloc] initWithFrame:CGRectMake(kJBNumericDefaultPadding, ceil(self.view.bounds.size.height * 0.5) - ceil(kJBBarChartViewControllerChartFooterHeight * 0.5), self.view.bounds.size.width - (kJBNumericDefaultPadding * 2), kJBBarChartViewControllerChartFooterHeight)];
JBBarChartFooterView *footerView = [[JBBarChartFooterView alloc] initWithFrame:CGRectMake(kJBBarChartViewControllerChartPadding, ceil(self.view.bounds.size.height * 0.5) - ceil(kJBBarChartViewControllerChartFooterHeight * 0.5), self.view.bounds.size.width - (kJBBarChartViewControllerChartPadding * 2), kJBBarChartViewControllerChartFooterHeight)];
footerView.padding = kJBBarChartViewControllerChartFooterPadding;
footerView.leftLabel.text = [kJBStringLabeJanuary uppercaseString];
footerView.leftLabel.text = [[self.monthlySymbols firstObject] uppercaseString];
footerView.leftLabel.textColor = [UIColor whiteColor];
footerView.rightLabel.text = [kJBStringLabelDecember uppercaseString];
footerView.rightLabel.text = [[self.monthlySymbols lastObject] uppercaseString];
footerView.rightLabel.textColor = [UIColor whiteColor];
self.barChartView.footerView = footerView;
@@ -106,60 +138,67 @@ NSString * const kJBBarChartViewControllerNavButtonViewKey = @"view";
[self.barChartView reloadData];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[self.barChartView setState:JBChartViewStateExpanded animated:YES callback:nil];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.barChartView setState:JBChartViewStateCollapsed];
[self.barChartView setState:JBChartViewStateExpanded];
}
#pragma mark - JBBarChartViewDelegate
#pragma mark - JBChartViewDataSource
- (CGFloat)barChartView:(JBBarChartView *)barChartView heightForBarViewAtAtIndex:(NSInteger)index
- (BOOL)shouldExtendSelectionViewIntoHeaderPaddingForChartView:(JBChartView *)chartView
{
return [[self.chartData objectAtIndex:index] floatValue];
return YES;
}
- (BOOL)shouldExtendSelectionViewIntoFooterPaddingForChartView:(JBChartView *)chartView
{
return NO;
}
#pragma mark - JBBarChartViewDataSource
- (NSInteger)numberOfBarsInBarChartView:(JBBarChartView *)barChartView
- (NSUInteger)numberOfBarsInBarChartView:(JBBarChartView *)barChartView
{
return kJBBarChartViewControllerNumBars;
}
- (NSInteger)barPaddingForBarChartView:(JBBarChartView *)barChartView
- (void)barChartView:(JBBarChartView *)barChartView didSelectBarAtIndex:(NSUInteger)index touchPoint:(CGPoint)touchPoint
{
return kJBBarChartViewControllerBarPadding;
NSNumber *valueNumber = [self.chartData objectAtIndex:index];
[self.informationView setValueText:[NSString stringWithFormat:kJBStringLabelDegreesFahrenheit, [valueNumber intValue], kJBStringLabelDegreeSymbol] unitText:nil];
[self.informationView setTitleText:kJBStringLabelWorldwideAverage];
[self.informationView setHidden:NO animated:YES];
[self setTooltipVisible:YES animated:YES atTouchPoint:touchPoint];
[self.tooltipView setText:[[self.monthlySymbols objectAtIndex:index] uppercaseString]];
}
- (UIView *)barViewForBarChartView:(JBBarChartView *)barChartView atIndex:(NSInteger)index
- (void)didDeselectBarChartView:(JBBarChartView *)barChartView
{
UIView *barView = [[UIView alloc] init];
barView.backgroundColor = (index % 2 == 0) ? kJBColorBarChartBarBlue : kJBColorBarChartBarGreen;
return barView;
[self.informationView setHidden:YES animated:YES];
[self setTooltipVisible:NO animated:YES];
}
- (UIColor *)selectionBarColorForBarChartView:(JBBarChartView *)barChartView
#pragma mark - JBBarChartViewDelegate
- (CGFloat)barChartView:(JBBarChartView *)barChartView heightForBarViewAtIndex:(NSUInteger)index
{
return [[self.chartData objectAtIndex:index] floatValue];
}
- (UIColor *)barChartView:(JBBarChartView *)barChartView colorForBarViewAtIndex:(NSUInteger)index
{
return (index % 2 == 0) ? kJBColorBarChartBarBlue : kJBColorBarChartBarGreen;
}
- (UIColor *)barSelectionColorForBarChartView:(JBBarChartView *)barChartView
{
return [UIColor whiteColor];
}
- (void)barChartView:(JBBarChartView *)barChartView didSelectBarAtIndex:(NSInteger)index
- (CGFloat)barPaddingForBarChartView:(JBBarChartView *)barChartView
{
NSNumber *valueNumber = [self.chartData objectAtIndex:index];
[self.informationView setValueText:[NSString stringWithFormat:@"%d", [valueNumber intValue]] unitText:kJBStringLabelMm];
[self.informationView setTitleText:[self.monthlySymbols objectAtIndex:index]];
[self.informationView setHidden:NO animated:YES];
}
- (void)barChartView:(JBBarChartView *)barChartView didUnselectBarAtIndex:(NSInteger)index
{
[self.informationView setHidden:YES animated:YES];
return kJBBarChartViewControllerBarPadding;
}
#pragma mark - Buttons
@@ -177,4 +216,11 @@ NSString * const kJBBarChartViewControllerNavButtonViewKey = @"view";
}];
}
#pragma mark - Overrides
- (JBChartView *)chartView
{
return self.barChartView;
}
@end
@@ -11,13 +11,17 @@
// Controllers
#import "JBBarChartViewController.h"
#import "JBLineChartViewController.h"
#import "JBAreaChartViewController.h"
#import "JBLineChartMissingPointsViewController.h"
// Views
#import "JBChartTableCell.h"
typedef NS_ENUM(NSInteger, JBChartListViewControllerRow){
JBChartListViewControllerRowLineChart,
JBChartListViewControllerRowBarChart,
JBChartListViewControllerRowLineChartMissingPoints,
JBChartListViewControllerRowBarChart,
JBChartListViewControllerRowAreaChart,
JBChartListViewControllerRowCount
};
@@ -50,10 +54,39 @@ NSInteger const kJBChartListViewControllerCellHeight = 100;
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
JBChartTableCell *cell = [tableView dequeueReusableCellWithIdentifier:kJBChartListViewControllerCellIdentifier forIndexPath:indexPath];
cell.textLabel.text = indexPath.row == JBChartListViewControllerRowLineChart ? kJBStringLabelAverageAnnualRainfall : kJBStringLabelAverageMonthlyRainfall;
cell.detailTextLabel.text = kJBStringLabelSanFrancisco;
cell.type = indexPath.row == JBChartListViewControllerRowLineChart ? JBChartTableCellTypeLineChart : JBChartTableCellTypeBarChart;
JBChartTableCell *cell = [tableView dequeueReusableCellWithIdentifier:kJBChartListViewControllerCellIdentifier forIndexPath:indexPath];
NSString *text = nil;
NSString *detailText = nil;
JBChartTableCellType type = -1;
switch (indexPath.row) {
case JBChartListViewControllerRowLineChart:
text = kJBStringLabelAverageDailyRainfall;
detailText = kJBStringLabelSanFrancisco2013;
type = JBChartTableCellTypeLineChart;
break;
case JBChartListViewControllerRowLineChartMissingPoints:
text = kJBStringLabelCyclingDistances;
detailText = kJBStringLabelCyclingCurrentLastWeek2014;
type = JBChartTableCellTypeLineChart;
break;
case JBChartListViewControllerRowBarChart:
text = kJBStringLabelAverageMonthlyTemperature;
detailText = kJBStringLabelWorldwide2012;
type = JBChartTableCellTypeBarChart;
break;
case JBChartListViewControllerRowAreaChart:
text = kJBStringLabelAverageShineHours;
detailText = kJBStringLabelWorldwide2011;
type = JBChartTableCellTypeAreaChart;
break;
default:
break;
}
cell.textLabel.text = text;
cell.detailTextLabel.text = detailText;
cell.type = type;
return cell;
}
@@ -73,11 +106,21 @@ NSInteger const kJBChartListViewControllerCellHeight = 100;
JBLineChartViewController *lineChartController = [[JBLineChartViewController alloc] init];
[self.navigationController pushViewController:lineChartController animated:YES];
}
else if (indexPath.row == JBChartListViewControllerRowLineChartMissingPoints)
{
JBLineChartMissingPointsViewController *lineChartController = [[JBLineChartMissingPointsViewController alloc] init];
[self.navigationController pushViewController:lineChartController animated:YES];
}
else if (indexPath.row == JBChartListViewControllerRowBarChart)
{
JBBarChartViewController *barChartController = [[JBBarChartViewController alloc] init];
[self.navigationController pushViewController:barChartController animated:YES];
}
else if (indexPath.row == JBChartListViewControllerRowAreaChart)
{
JBAreaChartViewController *areaChartController = [[JBAreaChartViewController alloc] init];
[self.navigationController pushViewController:areaChartController animated:YES];
}
}
@end
@@ -0,0 +1,13 @@
//
// JBLineChartMissingPointsViewController.h
// JBChartViewDemo
//
// Created by Sebastian Opel on 23.10.14.
// Copyright (c) 2014 Jawbone. All rights reserved.
//
#import "JBBaseChartViewController.h"
@interface JBLineChartMissingPointsViewController : JBBaseChartViewController
@end
@@ -0,0 +1,309 @@
//
// JBLineChartMissingPointsViewController.m
// JBChartViewDemo
//
// Created by Sebastian Opel on 23.10.14.
// Copyright (c) 2014 Jawbone. All rights reserved.
//
#import "JBLineChartMissingPointsViewController.h"
// Views
#import "JBLineChartView.h"
#import "JBChartHeaderView.h"
#import "JBLineChartFooterView.h"
#import "JBChartInformationView.h"
#define ARC4RANDOM_MAX 0x010000000
typedef NS_ENUM(NSInteger, JBLineChartLine){
JBLineChartLineSolid,
JBLineChartLineDashed,
JBLineChartLineCount
};
// Numerics
CGFloat const kJBLineChartMissingPointsViewControllerChartHeight = 250.0f;
CGFloat const kJBLineChartMissingPointsViewControllerChartPadding = 10.0f;
CGFloat const kJBLineChartMissingPointsViewControllerChartHeaderHeight = 75.0f;
CGFloat const kJBLineChartMissingPointsViewControllerChartHeaderPadding = 20.0f;
CGFloat const kJBLineChartMissingPointsViewControllerChartFooterHeight = 20.0f;
CGFloat const kJBLineChartMissingPointsViewControllerChartSolidLineWidth = 6.0f;
CGFloat const kJBLineChartMissingPointsViewControllerChartSolidLineDotRadius = 5.0f;
CGFloat const kJBLineChartMissingPointsViewControllerChartDashedLineWidth = 2.0f;
NSInteger const kJBLineChartMissingPointsViewControllerMaxNumChartPoints = 7;
// Strings
NSString * const kJBLineChartMissingPointsViewControllerNavButtonViewKey = @"view";
@interface JBLineChartMissingPointsViewController () <JBLineChartViewDelegate, JBLineChartViewDataSource>
@property (nonatomic, strong) JBLineChartView *lineChartView;
@property (nonatomic, strong) JBChartInformationView *informationView;
@property (nonatomic, strong) NSArray *chartData;
@property (nonatomic, strong) NSArray *daysOfWeek;
// Buttons
- (void)chartToggleButtonPressed:(id)sender;
// Helpers
- (void)initFakeData;
- (NSArray *)largestLineData; // largest collection of fake line data
@end
@implementation JBLineChartMissingPointsViewController
#pragma mark - Alloc/Init
- (id)init
{
self = [super init];
if (self)
{
[self initFakeData];
}
return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self)
{
[self initFakeData];
}
return self;
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
[self initFakeData];
}
return self;
}
- (void)dealloc
{
_lineChartView.delegate = nil;
_lineChartView.dataSource = nil;
}
#pragma mark - Data
- (void)initFakeData
{
NSMutableArray *mutableLineCharts = [NSMutableArray array];
for (int lineIndex=0; lineIndex<JBLineChartLineCount; lineIndex++)
{
NSMutableArray *mutableChartData = [NSMutableArray array];
for (int i=0; i<kJBLineChartMissingPointsViewControllerMaxNumChartPoints; i++)
{
if(i < 2 || i > 5 || i == 3)
{
[mutableChartData addObject:[NSNumber numberWithFloat:NAN]];
} else {
[mutableChartData addObject:[NSNumber numberWithFloat:((double)arc4random() / ARC4RANDOM_MAX)]]; // random number between 0 and 1
}
}
[mutableLineCharts addObject:mutableChartData];
}
_chartData = [NSArray arrayWithArray:mutableLineCharts];
_daysOfWeek = [[[NSDateFormatter alloc] init] shortWeekdaySymbols];
}
- (NSArray *)largestLineData
{
NSArray *largestLineData = nil;
for (NSArray *lineData in self.chartData)
{
if ([lineData count] > [largestLineData count])
{
largestLineData = lineData;
}
}
return largestLineData;
}
#pragma mark - View Lifecycle
- (void)loadView
{
[super loadView];
self.view.backgroundColor = kJBColorLineChartControllerBackground;
self.navigationItem.rightBarButtonItem = [self chartToggleButtonWithTarget:self action:@selector(chartToggleButtonPressed:)];
self.lineChartView = [[JBLineChartView alloc] init];
self.lineChartView.frame = CGRectMake(kJBLineChartMissingPointsViewControllerChartPadding, kJBLineChartMissingPointsViewControllerChartPadding, self.view.bounds.size.width - (kJBLineChartMissingPointsViewControllerChartPadding * 2), kJBLineChartMissingPointsViewControllerChartHeight);
self.lineChartView.delegate = self;
self.lineChartView.dataSource = self;
self.lineChartView.headerPadding = kJBLineChartMissingPointsViewControllerChartHeaderPadding;
self.lineChartView.backgroundColor = kJBColorLineChartBackground;
JBChartHeaderView *headerView = [[JBChartHeaderView alloc] initWithFrame:CGRectMake(kJBLineChartMissingPointsViewControllerChartPadding, ceil(self.view.bounds.size.height * 0.5) - ceil(kJBLineChartMissingPointsViewControllerChartHeaderHeight * 0.5), self.view.bounds.size.width - (kJBLineChartMissingPointsViewControllerChartPadding * 2), kJBLineChartMissingPointsViewControllerChartHeaderHeight)];
headerView.titleLabel.text = [kJBStringLabelCyclingDistances uppercaseString];
headerView.titleLabel.textColor = kJBColorLineChartHeader;
headerView.titleLabel.shadowColor = [UIColor colorWithWhite:1.0 alpha:0.25];
headerView.titleLabel.shadowOffset = CGSizeMake(0, 1);
headerView.subtitleLabel.text = kJBStringLabel2014;
headerView.subtitleLabel.textColor = kJBColorLineChartHeader;
headerView.subtitleLabel.shadowColor = [UIColor colorWithWhite:1.0 alpha:0.25];
headerView.subtitleLabel.shadowOffset = CGSizeMake(0, 1);
headerView.separatorColor = kJBColorLineChartHeaderSeparatorColor;
self.lineChartView.headerView = headerView;
JBLineChartFooterView *footerView = [[JBLineChartFooterView alloc] initWithFrame:CGRectMake(kJBLineChartMissingPointsViewControllerChartPadding, ceil(self.view.bounds.size.height * 0.5) - ceil(kJBLineChartMissingPointsViewControllerChartFooterHeight * 0.5), self.view.bounds.size.width - (kJBLineChartMissingPointsViewControllerChartPadding * 2), kJBLineChartMissingPointsViewControllerChartFooterHeight)];
footerView.backgroundColor = [UIColor clearColor];
footerView.leftLabel.text = [[self.daysOfWeek firstObject] uppercaseString];
footerView.leftLabel.textColor = [UIColor whiteColor];
footerView.rightLabel.text = [[self.daysOfWeek lastObject] uppercaseString];;
footerView.rightLabel.textColor = [UIColor whiteColor];
footerView.sectionCount = [[self largestLineData] count];
self.lineChartView.footerView = footerView;
[self.view addSubview:self.lineChartView];
self.informationView = [[JBChartInformationView alloc] initWithFrame:CGRectMake(self.view.bounds.origin.x, CGRectGetMaxY(self.lineChartView.frame), self.view.bounds.size.width, self.view.bounds.size.height - CGRectGetMaxY(self.lineChartView.frame) - CGRectGetMaxY(self.navigationController.navigationBar.frame))];
[self.informationView setValueAndUnitTextColor:[UIColor colorWithWhite:1.0 alpha:0.75]];
[self.informationView setTitleTextColor:kJBColorLineChartHeader];
[self.informationView setTextShadowColor:nil];
[self.informationView setSeparatorColor:kJBColorLineChartHeaderSeparatorColor];
[self.view addSubview:self.informationView];
[self.lineChartView reloadData];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.lineChartView setState:JBChartViewStateExpanded];
}
#pragma mark - JBChartViewDataSource
- (BOOL)shouldExtendSelectionViewIntoHeaderPaddingForChartView:(JBChartView *)chartView
{
return YES;
}
- (BOOL)shouldExtendSelectionViewIntoFooterPaddingForChartView:(JBChartView *)chartView
{
return NO;
}
#pragma mark - JBLineChartViewDataSource
- (NSUInteger)numberOfLinesInLineChartView:(JBLineChartView *)lineChartView
{
return [self.chartData count];
}
- (NSUInteger)lineChartView:(JBLineChartView *)lineChartView numberOfVerticalValuesAtLineIndex:(NSUInteger)lineIndex
{
return [[self.chartData objectAtIndex:lineIndex] count];
}
- (BOOL)lineChartView:(JBLineChartView *)lineChartView showsDotsForLineAtLineIndex:(NSUInteger)lineIndex
{
return lineIndex == JBLineChartViewLineStyleDashed;
}
- (BOOL)lineChartView:(JBLineChartView *)lineChartView smoothLineAtLineIndex:(NSUInteger)lineIndex
{
return lineIndex == JBLineChartViewLineStyleSolid;
}
#pragma mark - JBLineChartViewDelegate
- (CGFloat)lineChartView:(JBLineChartView *)lineChartView verticalValueForHorizontalIndex:(NSUInteger)horizontalIndex atLineIndex:(NSUInteger)lineIndex
{
return [[[self.chartData objectAtIndex:lineIndex] objectAtIndex:horizontalIndex] floatValue];
}
- (void)lineChartView:(JBLineChartView *)lineChartView didSelectLineAtIndex:(NSUInteger)lineIndex horizontalIndex:(NSUInteger)horizontalIndex touchPoint:(CGPoint)touchPoint
{
NSNumber *valueNumber = [[self.chartData objectAtIndex:lineIndex] objectAtIndex:horizontalIndex];
if(isnan([valueNumber floatValue])) {
[self.informationView setHidden:YES animated:YES];
} else {
[self.informationView setValueText:[NSString stringWithFormat:@"%.2f", [valueNumber floatValue]] unitText:kJBStringLabelKm2014];
[self.informationView setTitleText:lineIndex == JBLineChartLineSolid ? kJBStringLabelLastWeek : kJBStringLabelCurrentWeek];
[self.informationView setHidden:NO animated:YES];
}
[self setTooltipVisible:YES animated:YES atTouchPoint:touchPoint];
[self.tooltipView setText:[[self.daysOfWeek objectAtIndex:horizontalIndex] uppercaseString]];
}
- (void)didDeselectLineInLineChartView:(JBLineChartView *)lineChartView
{
[self.informationView setHidden:YES animated:YES];
[self setTooltipVisible:NO animated:YES];
}
- (UIColor *)lineChartView:(JBLineChartView *)lineChartView colorForLineAtLineIndex:(NSUInteger)lineIndex
{
return (lineIndex == JBLineChartLineSolid) ? kJBColorLineChartDefaultSolidLineColor: kJBColorLineChartDefaultDashedLineColor;
}
- (UIColor *)lineChartView:(JBLineChartView *)lineChartView colorForDotAtHorizontalIndex:(NSUInteger)horizontalIndex atLineIndex:(NSUInteger)lineIndex
{
return (lineIndex == JBLineChartLineSolid) ? kJBColorLineChartDefaultSolidLineColor: kJBColorLineChartDefaultDashedLineColor;
}
- (CGFloat)lineChartView:(JBLineChartView *)lineChartView widthForLineAtLineIndex:(NSUInteger)lineIndex
{
return (lineIndex == JBLineChartLineSolid) ? kJBLineChartMissingPointsViewControllerChartSolidLineWidth: kJBLineChartMissingPointsViewControllerChartDashedLineWidth;
}
- (CGFloat)lineChartView:(JBLineChartView *)lineChartView dotRadiusForDotAtHorizontalIndex:(NSUInteger)horizontalIndex atLineIndex:(NSUInteger)lineIndex
{
return (lineIndex == JBLineChartLineSolid) ? 0.0 : kJBLineChartMissingPointsViewControllerChartSolidLineDotRadius;
}
- (UIColor *)lineChartView:(JBLineChartView *)lineChartView verticalSelectionColorForLineAtLineIndex:(NSUInteger)lineIndex
{
return [UIColor whiteColor];
}
- (UIColor *)lineChartView:(JBLineChartView *)lineChartView selectionColorForLineAtLineIndex:(NSUInteger)lineIndex
{
return (lineIndex == JBLineChartLineSolid) ? kJBColorLineChartDefaultSolidSelectedLineColor: kJBColorLineChartDefaultDashedSelectedLineColor;
}
- (UIColor *)lineChartView:(JBLineChartView *)lineChartView selectionColorForDotAtHorizontalIndex:(NSUInteger)horizontalIndex atLineIndex:(NSUInteger)lineIndex
{
return (lineIndex == JBLineChartLineSolid) ? kJBColorLineChartDefaultSolidSelectedLineColor: kJBColorLineChartDefaultDashedSelectedLineColor;
}
- (JBLineChartViewLineStyle)lineChartView:(JBLineChartView *)lineChartView lineStyleForLineAtLineIndex:(NSUInteger)lineIndex
{
return (lineIndex == JBLineChartLineSolid) ? JBLineChartViewLineStyleSolid : JBLineChartViewLineStyleDashed;
}
#pragma mark - Buttons
- (void)chartToggleButtonPressed:(id)sender
{
UIView *buttonImageView = [self.navigationItem.rightBarButtonItem valueForKey:kJBLineChartMissingPointsViewControllerNavButtonViewKey];
buttonImageView.userInteractionEnabled = NO;
CGAffineTransform transform = self.lineChartView.state == JBChartViewStateExpanded ? CGAffineTransformMakeRotation(M_PI) : CGAffineTransformMakeRotation(0);
buttonImageView.transform = transform;
[self.lineChartView setState:self.lineChartView.state == JBChartViewStateExpanded ? JBChartViewStateCollapsed : JBChartViewStateExpanded animated:YES callback:^{
buttonImageView.userInteractionEnabled = YES;
}];
}
#pragma mark - Overrides
- (JBChartView *)chartView
{
return self.lineChartView;
}
@end
@@ -6,8 +6,8 @@
// Copyright (c) 2013 Jawbone. All rights reserved.
//
#import "JBBaseViewController.h"
#import "JBBaseChartViewController.h"
@interface JBLineChartViewController : JBBaseViewController
@interface JBLineChartViewController : JBBaseChartViewController
@end
@@ -16,12 +16,22 @@
#define ARC4RANDOM_MAX 0x100000000
typedef NS_ENUM(NSInteger, JBLineChartLine){
JBLineChartLineSolid,
JBLineChartLineDashed,
JBLineChartLineCount
};
// Numerics
CGFloat const kJBLineChartViewControllerChartHeight = 250.0f;
CGFloat const kJBLineChartViewControllerChartPadding = 10.0f;
CGFloat const kJBLineChartViewControllerChartHeaderHeight = 75.0f;
CGFloat const kJBLineChartViewControllerChartHeaderPadding = 20.0f;
CGFloat const kJBLineChartViewControllerChartFooterHeight = 20.0f;
NSInteger const kJBLineChartViewControllerNumChartPoints = 27;
CGFloat const kJBLineChartViewControllerChartSolidLineWidth = 6.0f;
CGFloat const kJBLineChartViewControllerChartSolidLineDotRadius = 5.0f;
CGFloat const kJBLineChartViewControllerChartDashedLineWidth = 2.0f;
NSInteger const kJBLineChartViewControllerMaxNumChartPoints = 7;
// Strings
NSString * const kJBLineChartViewControllerNavButtonViewKey = @"view";
@@ -31,12 +41,14 @@ NSString * const kJBLineChartViewControllerNavButtonViewKey = @"view";
@property (nonatomic, strong) JBLineChartView *lineChartView;
@property (nonatomic, strong) JBChartInformationView *informationView;
@property (nonatomic, strong) NSArray *chartData;
@property (nonatomic, strong) NSArray *daysOfWeek;
// Buttons
- (void)chartToggleButtonPressed:(id)sender;
// Helpers
- (void)initFakeData;
- (NSArray *)largestLineData; // largest collection of fake line data
@end
@@ -49,21 +61,66 @@ NSString * const kJBLineChartViewControllerNavButtonViewKey = @"view";
self = [super init];
if (self)
{
[self initFakeData]; // fake rain data
[self initFakeData];
}
return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self)
{
[self initFakeData];
}
return self;
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
[self initFakeData];
}
return self;
}
- (void)dealloc
{
_lineChartView.delegate = nil;
_lineChartView.dataSource = nil;
}
#pragma mark - Data
- (void)initFakeData
{
NSMutableArray *mutableChartData = [NSMutableArray array];
for (int i=0; i<kJBLineChartViewControllerNumChartPoints; i++)
NSMutableArray *mutableLineCharts = [NSMutableArray array];
for (int lineIndex=0; lineIndex<JBLineChartLineCount; lineIndex++)
{
[mutableChartData addObject:[NSNumber numberWithFloat:((double)arc4random() / ARC4RANDOM_MAX)]]; // random number between 0 and 1
NSMutableArray *mutableChartData = [NSMutableArray array];
for (int i=0; i<kJBLineChartViewControllerMaxNumChartPoints; i++)
{
[mutableChartData addObject:[NSNumber numberWithFloat:((double)arc4random() / ARC4RANDOM_MAX)]]; // random number between 0 and 1
}
[mutableLineCharts addObject:mutableChartData];
}
_chartData = [NSArray arrayWithArray:mutableChartData];
_chartData = [NSArray arrayWithArray:mutableLineCharts];
_daysOfWeek = [[[NSDateFormatter alloc] init] shortWeekdaySymbols];
}
- (NSArray *)largestLineData
{
NSArray *largestLineData = nil;
for (NSArray *lineData in self.chartData)
{
if ([lineData count] > [largestLineData count])
{
largestLineData = lineData;
}
}
return largestLineData;
}
#pragma mark - View Lifecycle
@@ -75,36 +132,37 @@ NSString * const kJBLineChartViewControllerNavButtonViewKey = @"view";
self.view.backgroundColor = kJBColorLineChartControllerBackground;
self.navigationItem.rightBarButtonItem = [self chartToggleButtonWithTarget:self action:@selector(chartToggleButtonPressed:)];
self.lineChartView = [[JBLineChartView alloc] initWithFrame:CGRectMake(kJBNumericDefaultPadding, kJBNumericDefaultPadding, self.view.bounds.size.width - (kJBNumericDefaultPadding * 2), kJBLineChartViewControllerChartHeight)];
self.lineChartView = [[JBLineChartView alloc] init];
self.lineChartView.frame = CGRectMake(kJBLineChartViewControllerChartPadding, kJBLineChartViewControllerChartPadding, self.view.bounds.size.width - (kJBLineChartViewControllerChartPadding * 2), kJBLineChartViewControllerChartHeight);
self.lineChartView.delegate = self;
self.lineChartView.dataSource = self;
self.lineChartView.headerPadding = kJBLineChartViewControllerChartHeaderPadding;
self.lineChartView.backgroundColor = kJBColorLineChartBackground;
JBChartHeaderView *headerView = [[JBChartHeaderView alloc] initWithFrame:CGRectMake(kJBNumericDefaultPadding, ceil(self.view.bounds.size.height * 0.5) - ceil(kJBLineChartViewControllerChartHeaderHeight * 0.5), self.view.bounds.size.width - (kJBNumericDefaultPadding * 2), kJBLineChartViewControllerChartHeaderHeight)];
headerView.titleLabel.text = [kJBStringLabelAverageAnnualRainfall uppercaseString];
JBChartHeaderView *headerView = [[JBChartHeaderView alloc] initWithFrame:CGRectMake(kJBLineChartViewControllerChartPadding, ceil(self.view.bounds.size.height * 0.5) - ceil(kJBLineChartViewControllerChartHeaderHeight * 0.5), self.view.bounds.size.width - (kJBLineChartViewControllerChartPadding * 2), kJBLineChartViewControllerChartHeaderHeight)];
headerView.titleLabel.text = [kJBStringLabelAverageDailyRainfall uppercaseString];
headerView.titleLabel.textColor = kJBColorLineChartHeader;
headerView.titleLabel.shadowColor = [UIColor colorWithWhite:1.0 alpha:0.25];
headerView.titleLabel.shadowOffset = CGSizeMake(0, 1);
headerView.subtitleLabel.text = [kJBStringLabelSanFrancisco uppercaseString];
headerView.subtitleLabel.text = kJBStringLabel2013;
headerView.subtitleLabel.textColor = kJBColorLineChartHeader;
headerView.subtitleLabel.shadowColor = [UIColor colorWithWhite:1.0 alpha:0.25];
headerView.subtitleLabel.shadowOffset = CGSizeMake(0, 1);
headerView.separatorColor = kJBColorLineChartHeaderSeparatorColor;
self.lineChartView.headerView = headerView;
JBLineChartFooterView *footerView = [[JBLineChartFooterView alloc] initWithFrame:CGRectMake(kJBNumericDefaultPadding, ceil(self.view.bounds.size.height * 0.5) - ceil(kJBLineChartViewControllerChartFooterHeight * 0.5), self.view.bounds.size.width - (kJBNumericDefaultPadding * 2), kJBLineChartViewControllerChartFooterHeight)];
JBLineChartFooterView *footerView = [[JBLineChartFooterView alloc] initWithFrame:CGRectMake(kJBLineChartViewControllerChartPadding, ceil(self.view.bounds.size.height * 0.5) - ceil(kJBLineChartViewControllerChartFooterHeight * 0.5), self.view.bounds.size.width - (kJBLineChartViewControllerChartPadding * 2), kJBLineChartViewControllerChartFooterHeight)];
footerView.backgroundColor = [UIColor clearColor];
footerView.leftLabel.text = kJBStringLabel1987;
footerView.leftLabel.text = [[self.daysOfWeek firstObject] uppercaseString];
footerView.leftLabel.textColor = [UIColor whiteColor];
footerView.rightLabel.text = kJBStringLabel2013;
footerView.rightLabel.text = [[self.daysOfWeek lastObject] uppercaseString];;
footerView.rightLabel.textColor = [UIColor whiteColor];
footerView.sectionCount = kJBLineChartViewControllerNumChartPoints;
footerView.sectionCount = [[self largestLineData] count];
self.lineChartView.footerView = footerView;
[self.view addSubview:self.lineChartView];
self.informationView = [[JBChartInformationView alloc] initWithFrame:CGRectMake(self.view.bounds.origin.x, CGRectGetMaxY(self.lineChartView.frame), self.view.bounds.size.width, self.view.bounds.size.height - CGRectGetMaxY(self.lineChartView.frame) - CGRectGetMaxY(self.navigationController.navigationBar.frame)) layout:JBChartInformationViewLayoutVertical];
self.informationView = [[JBChartInformationView alloc] initWithFrame:CGRectMake(self.view.bounds.origin.x, CGRectGetMaxY(self.lineChartView.frame), self.view.bounds.size.width, self.view.bounds.size.height - CGRectGetMaxY(self.lineChartView.frame) - CGRectGetMaxY(self.navigationController.navigationBar.frame))];
[self.informationView setValueAndUnitTextColor:[UIColor colorWithWhite:1.0 alpha:0.75]];
[self.informationView setTitleTextColor:kJBColorLineChartHeader];
[self.informationView setTextShadowColor:nil];
@@ -114,55 +172,151 @@ NSString * const kJBLineChartViewControllerNavButtonViewKey = @"view";
[self.lineChartView reloadData];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[self.lineChartView setState:JBChartViewStateExpanded animated:YES];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.lineChartView setState:JBChartViewStateCollapsed];
[self.lineChartView setState:JBChartViewStateExpanded];
}
#pragma mark - JBLineChartViewDelegate
#pragma mark - JBChartViewDataSource
- (CGFloat)lineChartView:(JBLineChartView *)lineChartView heightForIndex:(NSInteger)index
- (BOOL)shouldExtendSelectionViewIntoHeaderPaddingForChartView:(JBChartView *)chartView
{
return [[self.chartData objectAtIndex:index] floatValue];
return YES;
}
- (void)lineChartView:(JBLineChartView *)lineChartView didSelectChartAtIndex:(NSInteger)index
- (BOOL)shouldExtendSelectionViewIntoFooterPaddingForChartView:(JBChartView *)chartView
{
NSNumber *valueNumber = [self.chartData objectAtIndex:index];
[self.informationView setValueText:[NSString stringWithFormat:@"%.2f", [valueNumber floatValue]] unitText:kJBStringLabelMm];
[self.informationView setTitleText:[NSString stringWithFormat:@"%d", [kJBStringLabel1987 intValue] + (int)index]];
[self.informationView setHidden:NO animated:YES];
}
- (void)lineChartView:(JBLineChartView *)lineChartView didUnselectChartAtIndex:(NSInteger)index
{
[self.informationView setHidden:YES animated:YES];
return NO;
}
#pragma mark - JBLineChartViewDataSource
- (NSInteger)numberOfPointsInLineChartView:(JBLineChartView *)lineChartView
- (NSUInteger)numberOfLinesInLineChartView:(JBLineChartView *)lineChartView
{
return [self.chartData count];
}
- (UIColor *)lineColorForLineChartView:(JBLineChartView *)lineChartView
- (NSUInteger)lineChartView:(JBLineChartView *)lineChartView numberOfVerticalValuesAtLineIndex:(NSUInteger)lineIndex
{
return kJBColorLineChartLineColor;
return [[self.chartData objectAtIndex:lineIndex] count];
}
- (UIColor *)selectionColorForLineChartView:(JBLineChartView *)lineChartView
- (BOOL)lineChartView:(JBLineChartView *)lineChartView showsDotsForLineAtLineIndex:(NSUInteger)lineIndex
{
return lineIndex == JBLineChartViewLineStyleDashed;
}
- (BOOL)lineChartView:(JBLineChartView *)lineChartView smoothLineAtLineIndex:(NSUInteger)lineIndex
{
return lineIndex == JBLineChartViewLineStyleSolid;
}
#pragma mark - JBLineChartViewDelegate
- (CGFloat)lineChartView:(JBLineChartView *)lineChartView verticalValueForHorizontalIndex:(NSUInteger)horizontalIndex atLineIndex:(NSUInteger)lineIndex
{
return [[[self.chartData objectAtIndex:lineIndex] objectAtIndex:horizontalIndex] floatValue];
}
- (void)lineChartView:(JBLineChartView *)lineChartView didSelectLineAtIndex:(NSUInteger)lineIndex horizontalIndex:(NSUInteger)horizontalIndex touchPoint:(CGPoint)touchPoint
{
NSNumber *valueNumber = [[self.chartData objectAtIndex:lineIndex] objectAtIndex:horizontalIndex];
[self.informationView setValueText:[NSString stringWithFormat:@"%.2f", [valueNumber floatValue]] unitText:kJBStringLabelMm];
[self.informationView setTitleText:lineIndex == JBLineChartLineSolid ? kJBStringLabelMetropolitanAverage : kJBStringLabelNationalAverage];
[self.informationView setHidden:NO animated:YES];
[self setTooltipVisible:YES animated:YES atTouchPoint:touchPoint];
[self.tooltipView setText:[[self.daysOfWeek objectAtIndex:horizontalIndex] uppercaseString]];
}
- (void)didDeselectLineInLineChartView:(JBLineChartView *)lineChartView
{
[self.informationView setHidden:YES animated:YES];
[self setTooltipVisible:NO animated:YES];
}
- (UIColor *)lineChartView:(JBLineChartView *)lineChartView colorForLineAtLineIndex:(NSUInteger)lineIndex
{
return (lineIndex == JBLineChartLineSolid) ? kJBColorLineChartDefaultSolidLineColor: kJBColorLineChartDefaultDashedLineColor;
}
- (UIColor *)lineChartView:(JBLineChartView *)lineChartView fillColorForLineAtLineIndex:(NSUInteger)lineIndex
{
return (lineIndex == JBLineChartLineSolid) ? kJBColorLineChartDefaultSolidFillColor : kJBColorLineChartDefaultDashedFillColor;
}
- (CAGradientLayer *)lineChartView:(JBLineChartView *)lineChartView gradientForLineAtLineIndex:(NSUInteger)lineIndex
{
if (lineIndex == JBLineChartLineSolid)
{
return nil;
}
else
{
CAGradientLayer *gradient = [CAGradientLayer new];
gradient.startPoint = CGPointMake(0.0, 0.0);
gradient.endPoint = CGPointMake(1.0, 0.0);
gradient.colors = @[(id)kJBColorLineChartDefaultGradientStartColor.CGColor, (id)kJBColorLineChartDefaultGradientEndColor.CGColor];
return gradient;
}
}
- (CAGradientLayer *)lineChartView:(JBLineChartView *)lineChartView fillGradientForLineAtLineIndex:(NSUInteger)lineIndex
{
if (lineIndex == JBLineChartLineSolid)
{
return nil;
}
else
{
CAGradientLayer *gradient = [CAGradientLayer new];
gradient.startPoint = CGPointMake(0.0, 0.0);
gradient.endPoint = CGPointMake(1.0, 0.0);
gradient.colors = @[(id)kJBColorLineChartDefaultFillGradientStartColor.CGColor, (id)kJBColorLineChartDefaultFillGradientEndColor.CGColor];
return gradient;
}
}
- (UIColor *)lineChartView:(JBLineChartView *)lineChartView colorForDotAtHorizontalIndex:(NSUInteger)horizontalIndex atLineIndex:(NSUInteger)lineIndex
{
return (lineIndex == JBLineChartLineSolid) ? kJBColorLineChartDefaultSolidLineColor: kJBColorLineChartDefaultDashedLineColor;
}
- (CGFloat)lineChartView:(JBLineChartView *)lineChartView widthForLineAtLineIndex:(NSUInteger)lineIndex
{
return (lineIndex == JBLineChartLineSolid) ? kJBLineChartViewControllerChartSolidLineWidth: kJBLineChartViewControllerChartDashedLineWidth;
}
- (CGFloat)lineChartView:(JBLineChartView *)lineChartView dotRadiusForDotAtHorizontalIndex:(NSUInteger)horizontalIndex atLineIndex:(NSUInteger)lineIndex
{
return (lineIndex == JBLineChartLineSolid) ? 0.0: kJBLineChartViewControllerChartSolidLineDotRadius;
}
- (UIColor *)lineChartView:(JBLineChartView *)lineChartView verticalSelectionColorForLineAtLineIndex:(NSUInteger)lineIndex
{
return [UIColor whiteColor];
}
- (UIColor *)lineChartView:(JBLineChartView *)lineChartView selectionColorForLineAtLineIndex:(NSUInteger)lineIndex
{
return (lineIndex == JBLineChartLineSolid) ? kJBColorLineChartDefaultSolidSelectedLineColor: kJBColorLineChartDefaultDashedSelectedLineColor;
}
- (UIColor *)lineChartView:(JBLineChartView *)lineChartView selectionColorForDotAtHorizontalIndex:(NSUInteger)horizontalIndex atLineIndex:(NSUInteger)lineIndex
{
return (lineIndex == JBLineChartLineSolid) ? kJBColorLineChartDefaultSolidSelectedLineColor: kJBColorLineChartDefaultDashedSelectedLineColor;
}
- (JBLineChartViewLineStyle)lineChartView:(JBLineChartView *)lineChartView lineStyleForLineAtLineIndex:(NSUInteger)lineIndex
{
return (lineIndex == JBLineChartLineSolid) ? JBLineChartViewLineStyleSolid : JBLineChartViewLineStyleDashed;
}
- (JBLineChartViewLineColorStyle)lineChartView:(JBLineChartView *)lineChartView lineColorStyleForLineAtLineIndex:(NSUInteger)lineIndex
{
return (lineIndex == JBLineChartLineSolid) ? JBLineChartViewLineColorStyleSolid : JBLineChartViewLineColorStyleGradient;
}
#pragma mark - Buttons
- (void)chartToggleButtonPressed:(id)sender
@@ -178,4 +332,11 @@ NSString * const kJBLineChartViewControllerNavButtonViewKey = @"view";
}];
}
#pragma mark - Overrides
- (JBChartView *)chartView
{
return self.lineChartView;
}
@end
@@ -10,7 +10,6 @@
@interface JBBarChartFooterView : UIView
@property (nonatomic, strong) UIColor *footerBackgroundColor; // footer background (default = black)
@property (nonatomic, assign) CGFloat padding; // label left & right padding (default = 4.0)
@property (nonatomic, readonly) UILabel *leftLabel;
@property (nonatomic, readonly) UILabel *rightLabel;
@@ -10,30 +10,12 @@
// Numerics
CGFloat const kJBBarChartFooterPolygonViewDefaultPadding = 4.0f;
CGFloat const kJBBarChartFooterPolygonViewArrowHeight = 8.0f;
CGFloat const kJBBarChartFooterPolygonViewArrowWidth = 16.0f;
// Colors
static UIColor *kJBBarChartFooterPolygonViewDefaultBackgroundColor = nil;
static UIColor *kJBBarChartFooterViewDefaultBackgroundColor = nil;
@protocol JBBarChartFooterPolygonViewDelegate;
@interface JBBarChartFooterView ()
@interface JBBarChartFooterPolygonView : UIView
@property (nonatomic, weak) id<JBBarChartFooterPolygonViewDelegate> delegate;
@end
@protocol JBBarChartFooterPolygonViewDelegate <NSObject>
- (UIColor *)backgroundColorForChartFooterPolygonView:(JBBarChartFooterPolygonView *)chartFooterPolygonView;
- (CGFloat)paddingForChartFooterPolygonView:(JBBarChartFooterPolygonView *)chartFooterPolygonView;
@end
@interface JBBarChartFooterView () <JBBarChartFooterPolygonViewDelegate>
@property (nonatomic, strong) JBBarChartFooterPolygonView *polygonView;
@property (nonatomic, strong) UILabel *leftLabel;
@property (nonatomic, strong) UILabel *rightLabel;
@@ -47,7 +29,7 @@ static UIColor *kJBBarChartFooterPolygonViewDefaultBackgroundColor = nil;
{
if (self == [JBBarChartFooterView class])
{
kJBBarChartFooterPolygonViewDefaultBackgroundColor = kJBColorBarChartControllerBackground;
kJBBarChartFooterViewDefaultBackgroundColor = kJBColorBarChartControllerBackground;
}
}
@@ -56,16 +38,10 @@ static UIColor *kJBBarChartFooterPolygonViewDefaultBackgroundColor = nil;
self = [super initWithFrame:frame];
if (self)
{
self.backgroundColor = kJBBarChartFooterPolygonViewDefaultBackgroundColor;
self.clipsToBounds = NO;
self.backgroundColor = kJBBarChartFooterViewDefaultBackgroundColor;
_footerBackgroundColor = kJBBarChartFooterPolygonViewDefaultBackgroundColor;
_padding = kJBBarChartFooterPolygonViewDefaultPadding;
_polygonView = [[JBBarChartFooterPolygonView alloc] initWithFrame:CGRectMake(self.bounds.origin.x, self.bounds.origin.y - kJBBarChartFooterPolygonViewArrowHeight, self.bounds.size.width, self.bounds.size.height + kJBBarChartFooterPolygonViewArrowHeight)];
_polygonView.delegate = self;
[self addSubview:_polygonView];
_leftLabel = [[UILabel alloc] init];
_leftLabel.adjustsFontSizeToFitWidth = YES;
_leftLabel.font = kJBFontFooterLabel;
@@ -101,96 +77,4 @@ static UIColor *kJBBarChartFooterPolygonViewDefaultBackgroundColor = nil;
self.rightLabel.frame = CGRectMake(CGRectGetMaxX(_leftLabel.frame), yOffset, width, self.bounds.size.height);
}
#pragma mark - JBBarChartFooterPolygonViewDelegate
- (UIColor *)backgroundColorForChartFooterPolygonView:(JBBarChartFooterPolygonView *)chartFooterPolygonView
{
return self.footerBackgroundColor;
}
- (CGFloat)paddingForChartFooterPolygonView:(JBBarChartFooterPolygonView *)chartFooterPolygonView
{
return self.padding;
}
@end
@implementation JBBarChartFooterPolygonView
#pragma mark - Alloc/Init
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
self.clipsToBounds = NO;
self.backgroundColor = [UIColor clearColor];
}
return self;
}
#pragma mark - Drawing
- (void)drawRect:(CGRect)rect
{
[super drawRect:rect];
CGContextRef context = UIGraphicsGetCurrentContext();
// Background gradient
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGFloat locations[] = { 0.0, 1.0 };
NSAssert([self.delegate respondsToSelector:@selector(backgroundColorForChartFooterPolygonView:)], @"JBChartFooterPolygonView // delegate must implement - (UIColor *)backgroundColorForChartFooterPolygonView");
NSAssert([self.delegate respondsToSelector:@selector(paddingForChartFooterPolygonView:)], @"JBChartFooterPolygonView // delegate must implement - (CGFloat)paddingForChartFooterPolygonView");
UIColor *bgColor = [self.delegate backgroundColorForChartFooterPolygonView:self];
NSArray *colors = @[(__bridge id)bgColor.CGColor, (__bridge id)bgColor.CGColor];
CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef) colors, locations);
// Polygon shape
CGFloat xOffset = self.bounds.origin.x;
CGFloat width = self.bounds.size.width;
CGFloat height = self.bounds.size.height;
CGFloat padding = [self.delegate paddingForChartFooterPolygonView:self];
NSArray *polygonPoints = @[[NSValue valueWithCGPoint:CGPointMake(xOffset, height)],
[NSValue valueWithCGPoint:CGPointMake(xOffset, kJBBarChartFooterPolygonViewArrowHeight)],
[NSValue valueWithCGPoint:CGPointMake(xOffset + padding, kJBBarChartFooterPolygonViewArrowHeight)],
[NSValue valueWithCGPoint:CGPointMake(xOffset + padding + ceil(kJBBarChartFooterPolygonViewArrowWidth * 0.5), 0)],
[NSValue valueWithCGPoint:CGPointMake(xOffset + padding + kJBBarChartFooterPolygonViewArrowWidth, kJBBarChartFooterPolygonViewArrowHeight)],
[NSValue valueWithCGPoint:CGPointMake(width - padding - kJBBarChartFooterPolygonViewArrowWidth, kJBBarChartFooterPolygonViewArrowHeight)],
[NSValue valueWithCGPoint:CGPointMake(width - padding - ceil(kJBBarChartFooterPolygonViewArrowWidth * 0.5), 0.0)],
[NSValue valueWithCGPoint:CGPointMake(width - padding, kJBBarChartFooterPolygonViewArrowHeight)],
[NSValue valueWithCGPoint:CGPointMake(width, kJBBarChartFooterPolygonViewArrowHeight)],
[NSValue valueWithCGPoint:CGPointMake(width, height)],
[NSValue valueWithCGPoint:CGPointMake(xOffset, height)]];
// Draw polygon
NSValue *pointValue = polygonPoints[0];
CGContextSaveGState(context);
{
NSInteger index = 0;
for (pointValue in polygonPoints)
{
CGPoint point = [pointValue CGPointValue];
if (index == 0)
{
CGContextMoveToPoint(context, point.x, point.y);
}
else
{
CGContextAddLineToPoint(context, point.x, point.y);
}
index++;
}
CGContextClip(context);
CGContextDrawLinearGradient(context, gradient, CGPointMake(CGRectGetMidX(rect), CGRectGetMinY(rect)), CGPointMake(CGRectGetMidX(rect), CGRectGetMaxY(rect)), 0);
}
CGContextRestoreGState(context);
CGGradientRelease(gradient);
CGColorSpaceRelease(colorSpace);
}
@end
@@ -39,7 +39,6 @@ static UIColor *kJBLineChartFooterViewDefaultSeparatorColor = nil;
self = [super initWithFrame:frame];
if (self)
{
self.clipsToBounds = NO;
self.backgroundColor = [UIColor clearColor];
_footerSeparatorColor = kJBLineChartFooterViewDefaultSeparatorColor;
@@ -5,16 +5,31 @@
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "3x"
},
{
"idiom" : "ipad",
"size" : "29x29",
@@ -9,7 +9,7 @@
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>com.jawbone.${PRODUCT_NAME:rfc1034identifier}</string>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
@@ -8,19 +8,12 @@
#import <Foundation/Foundation.h>
typedef NS_ENUM(NSInteger, JBChartInformationViewLayout){
JBChartInformationViewLayoutHorizontal, // default
JBChartInformationViewLayoutVertical
};
@interface JBChartInformationView : UIView
/*
* View must be initialized with a layout type (default = horizontal)
*/
- (id)initWithFrame:(CGRect)frame layout:(JBChartInformationViewLayout)layout;
@property (nonatomic, assign, readonly) JBChartInformationViewLayout layout; // read-only (must be set in init..)
- (id)initWithFrame:(CGRect)frame;
// Content
- (void)setTitleText:(NSString *)titleText;
@@ -10,9 +10,10 @@
// Numerics
CGFloat const kJBChartValueViewPadding = 10.0f;
CGFloat const kJBChartValueViewSeparatorSize = 1.0f;
CGFloat const kJBChartValueViewSeparatorSize = 0.5f;
CGFloat const kJBChartValueViewTitleHeight = 50.0f;
CGFloat const kJBChartValueViewTitleWidth = 75.0f;
CGFloat const kJBChartValueViewDefaultAnimationDuration = 0.25f;
// Colors (JBChartInformationView)
static UIColor *kJBChartViewSeparatorColor = nil;
@@ -58,13 +59,12 @@ static UIColor *kJBChartInformationViewShadowColor = nil;
}
}
- (id)initWithFrame:(CGRect)frame layout:(JBChartInformationViewLayout)layout
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
self.clipsToBounds = YES;
_layout = layout;
_titleLabel = [[UILabel alloc] init];
_titleLabel.font = kJBFontInformationTitle;
@@ -74,7 +74,7 @@ static UIColor *kJBChartInformationViewShadowColor = nil;
_titleLabel.textColor = kJBChartViewTitleColor;
_titleLabel.shadowColor = kJBChartViewShadowColor;
_titleLabel.shadowOffset = CGSizeMake(0, 1);
_titleLabel.textAlignment = _layout == JBChartInformationViewLayoutHorizontal ? NSTextAlignmentLeft : NSTextAlignmentCenter;
_titleLabel.textAlignment = NSTextAlignmentLeft;
[self addSubview:_titleLabel];
_separatorView = [[UIView alloc] init];
@@ -89,20 +89,15 @@ static UIColor *kJBChartInformationViewShadowColor = nil;
return self;
}
- (id)initWithFrame:(CGRect)frame
{
return [self initWithFrame:frame layout:JBChartInformationViewLayoutHorizontal];
}
#pragma mark - Position
- (CGRect)valueViewRect
{
CGRect valueRect = CGRectZero;
valueRect.origin.x = (self.layout == JBChartInformationViewLayoutHorizontal) ? kJBChartValueViewPadding : (kJBChartValueViewPadding * 3) + kJBChartValueViewTitleWidth;
valueRect.origin.y = (self.layout == JBChartInformationViewLayoutHorizontal) ? kJBChartValueViewPadding + kJBChartValueViewTitleHeight : kJBChartValueViewPadding;
valueRect.size.width = (self.layout == JBChartInformationViewLayoutHorizontal) ? self.bounds.size.width - (kJBChartValueViewPadding * 2) : self.bounds.size.width - valueRect.origin.x - kJBChartValueViewPadding;
valueRect.size.height = (self.layout == JBChartInformationViewLayoutHorizontal) ? self.bounds.size.height - valueRect.origin.y - kJBChartValueViewPadding : self.bounds.size.height - (kJBChartValueViewPadding * 2);
valueRect.origin.x = kJBChartValueViewPadding;
valueRect.origin.y = kJBChartValueViewPadding + kJBChartValueViewTitleHeight;
valueRect.size.width = self.bounds.size.width - (kJBChartValueViewPadding * 2);
valueRect.size.height = self.bounds.size.height - valueRect.origin.y - kJBChartValueViewPadding;
return valueRect;
}
@@ -111,28 +106,21 @@ static UIColor *kJBChartInformationViewShadowColor = nil;
CGRect titleRect = CGRectZero;
titleRect.origin.x = kJBChartValueViewPadding;
titleRect.origin.y = hidden ? -kJBChartValueViewTitleHeight : kJBChartValueViewPadding;
titleRect.size.width = (self.layout == JBChartInformationViewLayoutHorizontal) ? self.bounds.size.width - (kJBChartValueViewPadding * 2) : kJBChartValueViewTitleWidth;
titleRect.size.height = (self.layout == JBChartInformationViewLayoutHorizontal) ? kJBChartValueViewTitleHeight : self.bounds.size.height - (kJBChartValueViewPadding * 2);
titleRect.size.width = self.bounds.size.width - (kJBChartValueViewPadding * 2);
titleRect.size.height = kJBChartValueViewTitleHeight;
return titleRect;
}
- (CGRect)separatorViewRectForHidden:(BOOL)hidden
{
CGRect separatorRect = CGRectZero;
separatorRect.origin.x = (self.layout == JBChartInformationViewLayoutHorizontal) ? kJBChartValueViewPadding : (kJBChartValueViewPadding * 2) + kJBChartValueViewTitleWidth;
separatorRect.origin.y = (self.layout == JBChartInformationViewLayoutHorizontal) ? kJBChartValueViewTitleHeight : kJBChartValueViewPadding;
separatorRect.size.width = (self.layout == JBChartInformationViewLayoutHorizontal) ? self.bounds.size.width - (kJBChartValueViewPadding * 2) : kJBChartValueViewSeparatorSize;
separatorRect.size.height = (self.layout == JBChartInformationViewLayoutHorizontal) ? kJBChartValueViewSeparatorSize : self.bounds.size.height - (kJBChartValueViewPadding * 2);
separatorRect.origin.x = kJBChartValueViewPadding;
separatorRect.origin.y = kJBChartValueViewTitleHeight;
separatorRect.size.width = self.bounds.size.width - (kJBChartValueViewPadding * 2);
separatorRect.size.height = kJBChartValueViewSeparatorSize;
if (hidden)
{
if (self.layout == JBChartInformationViewLayoutHorizontal)
{
separatorRect.origin.x -= self.bounds.size.width;
}
else
{
separatorRect.origin.y = self.bounds.size.height;
}
separatorRect.origin.x -= self.bounds.size.width;
}
return separatorRect;
}
@@ -185,7 +173,7 @@ static UIColor *kJBChartInformationViewShadowColor = nil;
{
if (hidden)
{
[UIView animateWithDuration:kJBNumericDefaultAnimationDuration * 0.5 delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
[UIView animateWithDuration:kJBChartValueViewDefaultAnimationDuration * 0.5 delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
self.titleLabel.alpha = 0.0;
self.separatorView.alpha = 0.0;
self.valueView.valueLabel.alpha = 0.0;
@@ -197,7 +185,7 @@ static UIColor *kJBChartInformationViewShadowColor = nil;
}
else
{
[UIView animateWithDuration:kJBNumericDefaultAnimationDuration delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
[UIView animateWithDuration:kJBChartValueViewDefaultAnimationDuration delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
self.titleLabel.frame = [self titleViewRectForHidden:NO];
self.titleLabel.alpha = 1.0;
self.valueView.valueLabel.alpha = 1.0;
@@ -273,14 +261,30 @@ static UIColor *kJBChartInformationViewShadowColor = nil;
- (void)layoutSubviews
{
CGFloat xOffset = kJBChartValueViewPadding;
CGFloat width = ceil((self.bounds.size.width - (kJBChartValueViewPadding * 2)) * 0.5);
CGSize valueLabelSize = CGSizeZero;
if ([self.valueLabel.text respondsToSelector:@selector(sizeWithAttributes:)])
{
valueLabelSize = [self.valueLabel.text sizeWithAttributes:@{NSFontAttributeName:self.valueLabel.font}];
}
else
{
valueLabelSize = [self.valueLabel.text sizeWithFont:self.valueLabel.font];
}
CGSize unitLabelSize = CGSizeZero;
if ([self.unitLabel.text respondsToSelector:@selector(sizeWithAttributes:)])
{
unitLabelSize = [self.unitLabel.text sizeWithAttributes:@{NSFontAttributeName:self.unitLabel.font}];
}
else
{
unitLabelSize = [self.unitLabel.text sizeWithFont:self.unitLabel.font];
}
CGSize valueLabelSize = [self.valueLabel.text sizeWithAttributes:@{NSFontAttributeName:self.valueLabel.font}];
self.valueLabel.frame = CGRectMake(xOffset, ceil(self.bounds.size.height * 0.5) - ceil(valueLabelSize.height * 0.5), width, valueLabelSize.height);
CGSize unitLabelSize = [self.unitLabel.text sizeWithAttributes:@{NSFontAttributeName:self.unitLabel.font}];
self.unitLabel.frame = CGRectMake(CGRectGetMaxX(self.valueLabel.frame), ceil(self.bounds.size.height * 0.5) - ceil(unitLabelSize.height * 0.5) + kJBChartValueViewPadding + 3, width, unitLabelSize.height);
CGFloat xOffset = ceil((self.bounds.size.width - (valueLabelSize.width + unitLabelSize.width)) * 0.5);
self.valueLabel.frame = CGRectMake(xOffset, ceil(self.bounds.size.height * 0.5) - ceil(valueLabelSize.height * 0.5), valueLabelSize.width, valueLabelSize.height);
self.unitLabel.frame = CGRectMake(CGRectGetMaxX(self.valueLabel.frame), ceil(self.bounds.size.height * 0.5) - ceil(unitLabelSize.height * 0.5) + kJBChartValueViewPadding + 3, unitLabelSize.width, unitLabelSize.height);
}
@end
@@ -0,0 +1,13 @@
//
// JBChartTooltipTipView.h
// JBChartViewDemo
//
// Created by Terry Worona on 3/17/14.
// Copyright (c) 2014 Jawbone. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface JBChartTooltipTipView : UIView
@end
@@ -0,0 +1,52 @@
//
// JBChartTooltipTipView.m
// JBChartViewDemo
//
// Created by Terry Worona on 3/17/14.
// Copyright (c) 2014 Jawbone. All rights reserved.
//
#import "JBChartTooltipTipView.h"
// Numerics
CGFloat const kJBChartTooltipTipViewDefaultWidth = 8.0f;
CGFloat const kJBChartTooltipTipViewDefaultHeight = 5.0f;
@implementation JBChartTooltipTipView
#pragma mark - Alloc/Init
- (id)init
{
self = [super initWithFrame:CGRectMake(0, 0, kJBChartTooltipTipViewDefaultWidth, kJBChartTooltipTipViewDefaultHeight)];
if (self)
{
self.backgroundColor = [UIColor clearColor];
}
return self;
}
#pragma mark - Drawing
- (void)drawRect:(CGRect)rect
{
[super drawRect:rect];
CGContextRef context = UIGraphicsGetCurrentContext();
[[UIColor clearColor] set];
CGContextFillRect(context, rect);
CGContextSaveGState(context);
{
CGContextBeginPath(context);
CGContextMoveToPoint(context, CGRectGetMidX(rect), CGRectGetMaxY(rect));
CGContextAddLineToPoint(context, CGRectGetMinX(rect), CGRectGetMinY(rect));
CGContextAddLineToPoint(context, CGRectGetMaxX(rect), CGRectGetMinY(rect));
CGContextClosePath(context);
CGContextSetFillColorWithColor(context, kJBColorTooltipColor.CGColor);
CGContextFillPath(context);
}
CGContextRestoreGState(context);
}
@end
@@ -0,0 +1,15 @@
//
// JBChartTooltipView.h
// JBChartViewDemo
//
// Created by Terry Worona on 3/12/14.
// Copyright (c) 2014 Jawbone. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface JBChartTooltipView : UIView
- (void)setText:(NSString *)text;
@end
@@ -0,0 +1,71 @@
//
// JBChartTooltipView.m
// JBChartViewDemo
//
// Created by Terry Worona on 3/12/14.
// Copyright (c) 2014 Jawbone. All rights reserved.
//
#import "JBChartTooltipView.h"
// Drawing
#import <QuartzCore/QuartzCore.h>
// Numerics
CGFloat static const kJBChartTooltipViewCornerRadius = 5.0;
CGFloat const kJBChartTooltipViewDefaultWidth = 50.0f;
CGFloat const kJBChartTooltipViewDefaultHeight = 25.0f;
@interface JBChartTooltipView ()
@property (nonatomic, strong) UILabel *textLabel;
@end
@implementation JBChartTooltipView
#pragma mark - Alloc/Init
- (id)init
{
self = [super initWithFrame:CGRectMake(0, 0, kJBChartTooltipViewDefaultWidth, kJBChartTooltipViewDefaultHeight)];
if (self)
{
self.backgroundColor = kJBColorTooltipColor;
self.layer.cornerRadius = kJBChartTooltipViewCornerRadius;
_textLabel = [[UILabel alloc] init];
_textLabel.font = kJBFontTooltipText;
_textLabel.backgroundColor = [UIColor clearColor];
_textLabel.textColor = kJBColorTooltipTextColor;
_textLabel.adjustsFontSizeToFitWidth = YES;
_textLabel.numberOfLines = 1;
_textLabel.textAlignment = NSTextAlignmentCenter;
[self addSubview:_textLabel];
}
return self;
}
#pragma mark - Setters
- (void)setText:(NSString *)text
{
self.textLabel.text = text;
[self setNeedsLayout];
}
- (void)setTooltipColor:(UIColor *)tooltipColor
{
self.backgroundColor = tooltipColor;
[self setNeedsDisplay];
}
#pragma mark - Layout
- (void)layoutSubviews
{
[super layoutSubviews];
_textLabel.frame = self.bounds;
}
@end
Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 650 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

+100 -101
View File
@@ -1,10 +1,10 @@
# JBChartView
<br/>
<p align="center">
<img src="https://raw.github.com/Jawbone/JBChartView/master/Screenshots/main.jpg">
</p>
<center>
<img src="https://raw.github.com/Jawbone/JBChartView/master/Screenshots/main.png">
</center>
<b>Introducing JBChartView - </b> Jawbone's iOS-based charting library for both line and bar graphs. It is easy to set-up, and highly customizable.
Introducing <b>JBChartView - </b> Jawbone's iOS-based charting library for both line and bar graphs. It is easy to set-up, and highly customizable.
## Features
@@ -14,15 +14,22 @@
- Highly customizable.
- Expand & collapse animation support.
Refer to the <a href="https://github.com/Jawbone/JBChartView/blob/master/CHANGELOG.md"">changelog</a> for an overview of JBChartView's feature history.
## Requirements
- Requires iOS 7 or later
- Requires iOS 6 or later
- Requires Automatic Reference Counting (ARC)
## Demo
## Demo Project
Build and run the <i>JBChartViewDemo</i> project in Xcode. The demo demonstrates the use of both the line and bar charts. It also outlines how a chart's appearance can be customized.
## More Demos
- <a href="https://github.com/Jawbone/anscombe-quartet-ios">Amsombe's Quartet</a>: project showcasing the use of JBChartView in the classic data visualization example known as Anscombe's Quartet.
- <a href="https://github.com/Jawbone/spark-friends-ios">Spark Friends</a>: project showcasing the use of JBChartView in the context of sparklines and (fake) user step data.
## Installation
<a href="http://cocoapods.org/" target="_blank">CocoaPods</a> is the recommended method of installing JBChartView.
@@ -31,16 +38,12 @@ Build and run the <i>JBChartViewDemo</i> project in Xcode. The demo demonstrates
Simply add the following line to your <code>Podfile</code>:
platform :ios, '6.0'
pod 'JBChartView'
Your Podfile should look something like:
platform :ios, '7.0'
pod 'JBChartView', '~> 1.1.3'
### The Old School Way
The simpliest way to use JBChartView with your application is to drag and drop the <i>/Classes</i> folder into you're Xcode 5 project. It's also recommended you rename the <i>/Classes</i> folder to something more descriptive (ie. "<i>Jawbone - JBChartView</i>").
The simplest way to use JBChartView with your application is to drag and drop the <i>/Classes</i> folder into you're Xcode 5 project. It's also recommended you rename the <i>/Classes</i> folder to something more descriptive (ie. "<i>Jawbone - JBChartView</i>").
<center>
<img src="https://raw.github.com/Jawbone/JBChartView/master/Screenshots/installation.png">
@@ -48,131 +51,127 @@ The simpliest way to use JBChartView with your application is to drag and drop t
## Usage
Both JBChartView implementations have a similiar data source and delgate pattern to <i>UITableView</i>. If you're familiar with using a <i>UITableView</i> or <i>UITableViewController</i>, using a JBChartView subclass should be a breeze!
All JBChartView implementations have a similiar data source and delgate pattern to <i>UITableView</i>. If you're familiar with using a <i>UITableView</i> or <i>UITableViewController</i>, using a JBChartView subclass should be a breeze!
#### Swift Projects
To use JBCartView in a Swift project add the following to your bridging header (JBChartView-Bridging-Header.h):
#import <UIKit/UIKit.h>
#import "JBChartView.h"
#import "JBBarChartView.h"
#import "JBLineChartView.h"
For more information about adding bridging headers see <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html" target="_blank">Swift and Objective-C in the Same Project</a>.
#### JBBarChartView
To initialize a <i>JBBarChartView</i>, you only need a few lines of code:
To initialize a <i>JBBarChartView</i>, you only need a few lines of code (see below). Bar charts can also be initialized via a <b>nib</b> or with a <b>frame</b>.
JBBarChartView *barChartView = [[JBBarChartView alloc] init];
barChartView.delegate = self;
barChartView.dataSource = self;
barChartView.delegate = self;
[self addSubview:barChartView];
Just like you would for a `UITableView`, ensure you clear these properties in your `dealloc`:
- (void)dealloc
{
JBBarChartView *barChartView = ...; // i.e. _barChartView
barChartView.delegate = nil;
barChartView.dataSource = nil;
}
At a minimum, you need to inform the data source how many bars are in the chart:
- (NSInteger)numberOfBarsInBarChartView:(JBBarChartView *)barChartView
- (NSUInteger)numberOfBarsInBarChartView:(JBBarChartView *)barChartView
{
return ...; // number of bars in chart
}
Secondly, you need to inform the delegate the height of each bar (automatically normalized across the entire chart):
- (CGFloat)barChartView:(JBBarChartView *)barChartView heightForBarViewAtAtIndex:(NSInteger)index
- (CGFloat)barChartView:(JBBarChartView *)barChartView heightForBarViewAtIndex:(NSUInteger)index
{
return ...; // height of bar at index
}
Lastly, ensure you have set the *frame* of your barChartView & call *reloadData* at least once:
barChartView.frame = CGRectMake( ... );
[barChartView reloadData];
**Note**: subsequent changes to the chart's frame will not invoke *reloadData*; it must be called directly afterwards for any changes to take effect.
#### JBLineChartView
Similiarily, to initialize a JBLineChartView, you only need a few lines of code:
Similiarily, to initialize a JBLineChartView, you only need a few lines of code (see below). Line charts can also be initialized via a <b>nib</b> or with a <b>frame</b>.
JBLineChartView *lineChartView = [[JBLineChartView alloc] init];
lineChartView.delegate = self;
lineChartView.dataSource = self;
[self addSubview:lineChartView];
lineChartView.dataSource = self;
lineChartView.delegate = self;
[self addSubview:lineChartView];
At a minimum, you need to inform the data source how many points are in the line chart:
Just like you would for a `UITableView`, ensure you clear these properties in your `dealloc`:
- (NSInteger)numberOfPointsInLineChartView:(JBLineChartView *)lineChartView
- (void)dealloc
{
return ...; // number of points in chart
JBLineChartView *lineChartView = ...; // i.e. _lineChartView
lineChartView.delegate = nil;
lineChartView.dataSource = nil;
}
Secondly, you need to inform the delegate the y-position of each point (automatically normalized across the entire chart):
- (CGFloat)lineChartView:(JBLineChartView *)lineChartView heightForIndex:(NSInteger)index
{
return ...; // y-position of poinnt at index (x-axis)
At a minimum, you need to inform the data source how many lines and vertical data points (for each line) are in the chart:
- (NSUInteger)numberOfLinesInLineChartView:(JBLineChartView *)lineChartView
{
return ...; // number of lines in chart
}
- (NSUInteger)lineChartView:(JBLineChartView *)lineChartView numberOfVerticalValuesAtLineIndex:(NSUInteger)lineIndex
{
return ...; // number of values for a line
}
Secondly, you need to inform the delegate of the y-position of each point (automatically normalized across the entire chart) for each line in the chart:
- (CGFloat)lineChartView:(JBLineChartView *)lineChartView verticalValueForHorizontalIndex:(NSUInteger)horizontalIndex atLineIndex:(NSUInteger)lineIndex
{
return ...; // y-position (y-axis) of point at horizontalIndex (x-axis)
}
**Note**: You can return NAN instead of CGFloat to indicate missing values. The chart's line will begin at the first non-NAN value and end at the last non-NAN value. The line will interopolate any NAN values in between (ie. the line will not be interrupted).
return [[NSNumber numberWithFloat:NAN] floatValue];
Lastly, ensure you have set the *frame* of your lineChartView & call *reloadData* at least once:
lineChartView.frame = CGRectMake( ... );
[lineChartView reloadData];
**Note**: subsequent changes to the chart's frame will not invoke *reloadData*; it must be called directly afterwards for any changes to take effect.
## Customization
Both the line and bar charts support a robust set of customization options.
Both the line and bar charts support a robust set of customization options. Read more about them <a href="Customization.md">here</a>.
The background of a bar or line chart can be set just like any other view:
## Minimum & Maximum Values
By default, a chart's minimum and maximum values are equal to the min and max supplied by the dataSource. You can override either value via:
- (void)setMinimumValue:(CGFloat)minimumValue;
- (void)setMaximumValue:(CGFloat)maximumValue;
If value(s) are supplied, they must be >= 0, otherwise an assertion will be thrown. To reset the values back to their original defaults:
- (void)resetMinimumValue;
- (void)resetMaximumValue;
self.barChartView.backgroundColor = ...; // UIColor
self.lineChartView.backgroundColor = ...; // UIColor
Any <i>JBChartView</i> subclass supports the use of headers and footers (similiar to that of <i>UITableView</i>):
The min/max values are clamped to the ceiling and floor of the actual min/max values of the chart's data source; for example, if a maximumValue of 20 is supplied & the chart's actual max is 100, then 100 will be used. For min/max modifications to take effect, reloadData must be called.
self.barChartView.footerView = ...; // UIView
self.lineChartView.headerView = ...; // UIView
Lastly, any JBChartView subclass can be collapsed or expanded programmatically via the <i>state</i> property. If you chose to animate state changes, a callback helper can be used to notify you when the animation has completed:
## Performance
- (void)setState:(JBChartViewState)state animated:(BOOL)animated callback:(void (^)())callback;
#### JBBarChartView
By default, a chart's bars will be black and flat. They can be customized by supplying a UIView subclass through the <i>optional</i> protocol:
- (UIView *)barViewForBarChartView:(JBBarChartView *)barChartView atIndex:(NSInteger)index
{
return ...; // color of line in chart
}
Furthermore, the color of the selection bar (on touch events) can be customized via the <i>optional</i> protocol:
- (UIColor *)selectionBarColorForBarChartView:(JBBarChartView *)barChartView
{
return ...; // color of selection view
}
Lastly, a bar chart's selection events are delegated back via:
- (void)barChartView:(JBBarChartView *)barChartView didSelectBarAtIndex:(NSInteger)index
{
// Update view
}
- (void)barChartView:(JBBarChartView *)barChartView didUnselectBarAtIndex:(NSInteger)index
{
// Update view
}
A JBBarChartView visuaul overview can be found <a href="https://raw.github.com/Jawbone/JBChartView/master/Screenshots/JBBarChartView.png" target="_blank">here</a>.
#### JBLineChartView
The color of the chart's line can be customized via the <i>optional</i> protocol:
- (UIColor *)lineColorForLineChartView:(JBLineChartView *)lineChartView
{
return ...; // color of line in chart
}
Furthermore, the color of the selection bar (on touch events) can be customized via the <i>optional</i> protocol:
- (UIColor *)selectionColorForLineChartView:(JBLineChartView *)lineChartView
{
return ...; // color of selection view
}
Lastly, a line chart's selection events are delegated back via:
- (void)lineChartView:(JBLineChartView *)lineChartView didSelectChartAtIndex:(NSInteger)index
{
// Update view
}
- (void)lineChartView:(JBLineChartView *)lineChartView didUnselectChartAtIndex:(NSInteger)index
{
// Update view
}
A JBLineChartView visuaul overview can be found <a href="https://raw.github.com/Jawbone/JBChartView/master/Screenshots/JBLineChartView.png" target="_blank">here</a>.
The nature of charting is to display all available information, unlike a UITableView, which can cache rows that are offscreen. JBChartView's performance will suffer if the number of data points exceed the resolution of the device. The same issue exists with MKMapView, when hundreds of pins are supplied within a certain geographic area. It's why Apple recommends clustering to avoid performance issues. As such, for large datasets, we recommend that your dataSource to supply a subset of points; clustering those that are close to one another.
## License
Binary file not shown.

Before

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 337 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 136 KiB