Compare commits
268 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 833f6e9080 | |||
| eb48db2e73 | |||
| 55b6dae956 | |||
| c44b276ae1 | |||
| 93f3d1862e | |||
| 19a4a0bf5c | |||
| 9d43c6dd23 | |||
| 8598ff1488 | |||
| b9d28bfd59 | |||
| dd1dce758e | |||
| 9fce2fc1c0 | |||
| ab1cf713e6 | |||
| 4363147303 | |||
| 8a1770c6df | |||
| f84f322598 | |||
| 04e1aa5b98 | |||
| ab07aa2399 | |||
| f01e11a0e2 | |||
| 76984c7c7c | |||
| d38a04a70d | |||
| 385d5b3589 | |||
| 90100c7277 | |||
| eca1c0507e | |||
| ac870e45ce | |||
| 74f588b7e6 | |||
| 406b64ae0c | |||
| 92e56d78c5 | |||
| 36ec328346 | |||
| b763ae540c | |||
| 7ffdf6d9da | |||
| 6531c68574 | |||
| ebae36bd2f | |||
| 8cdff2891c | |||
| 333200d041 | |||
| 6ad3bd7692 | |||
| 3531e593da | |||
| eeb9ca604c | |||
| b884108dbb | |||
| 00dd74f733 | |||
| c1938147d8 | |||
| e17c5419f4 | |||
| d0cb8b0307 | |||
| fe81df094e | |||
| 0dae570cc6 | |||
| c5c93cb660 | |||
| 3df69b0a9c | |||
| 30305cdde9 | |||
| 8e1cbba06f | |||
| 97e5acdb1a | |||
| 47f1f0ba8d | |||
| 0be9465049 | |||
| 7bed3dd5d0 | |||
| 4f1f6760d5 | |||
| 8103a1aea4 | |||
| dc6dc647ad | |||
| b6ea1a502a | |||
| afcf328158 | |||
| 49cf12c568 | |||
| 0d4b942b74 | |||
| 30a369796f | |||
| f2f35312e4 | |||
| d32f09a584 | |||
| 80e179df1d | |||
| 48da335f09 | |||
| 70c1fb897c | |||
| 30df02f804 | |||
| 9ba20e9e14 | |||
| d6d1dd8461 | |||
| b0de620503 | |||
| 8e81fb20cd | |||
| a303422d8e | |||
| 1aff68557f | |||
| ac3744c0c9 | |||
| a6ea0c30f8 | |||
| ea531e3cb1 | |||
| b1a3ebd4ed | |||
| 554f93f3d3 | |||
| 2ddd38fc9d | |||
| 6691f7a8c3 | |||
| c015531c85 | |||
| 3d036edc96 | |||
| 85c30351fe | |||
| d37383a352 | |||
| 3c6cf24cf7 | |||
| 8dbb2679ee | |||
| 867466d1d1 | |||
| 2046131143 | |||
| 208a727d88 | |||
| 43c6e9486f | |||
| 49206a01ed | |||
| e2b17820bf | |||
| b59904e5b9 | |||
| 1d8f78d751 | |||
| 3cc39124b8 | |||
| bedd7e2c71 | |||
| 786af91666 | |||
| b7927cddb7 | |||
| 0f2d4d766c | |||
| 64de3e6e23 | |||
| 87fb8ee7b8 | |||
| 7c0dfe3eb5 | |||
| 87b62ad2b1 | |||
| 9c0d788418 | |||
| de009f0236 | |||
| d46e4fe14d | |||
| 236336fdf3 | |||
| 9b60a1d662 | |||
| 3700b4e2e2 | |||
| 8c03033a1c | |||
| bb084b1b89 | |||
| 1c7c8b2e52 | |||
| 79a57d98e3 | |||
| 20d6b6081b | |||
| 20bbbdcc86 | |||
| 51ac8a1d63 | |||
| 68d04a2cdb | |||
| b7734ef189 | |||
| f6d2fe8b62 | |||
| 5c9679f448 | |||
| 037225a386 | |||
| 0fe979bd22 | |||
| 31b64ed7e4 | |||
| c30398c3ea | |||
| bc08322a3a | |||
| 213973f4ed | |||
| 28d40bcb31 | |||
| d4df0184a2 | |||
| 4f313aab80 | |||
| b6262462c5 | |||
| 1080089753 | |||
| 0afba01a9a | |||
| 63b47667ec | |||
| 4d6baf066f | |||
| 359ef7d0ea | |||
| 7b1e6475f2 | |||
| 2b8853780c | |||
| 0754e2e5d2 | |||
| 52b722013e | |||
| 4ef9b6442e | |||
| 177e076807 | |||
| 21969d759d | |||
| 4fd6f1cb63 | |||
| 804ce2ca67 | |||
| 485cfb9631 | |||
| 4640dede3a | |||
| 1b90c6e16f | |||
| 15b53aa68e | |||
| 0e277dc347 | |||
| 6de42998c0 | |||
| a1e4be3a5d | |||
| acaf6fb4dc | |||
| 5894610278 | |||
| e605e60f28 | |||
| 33b3c9518f | |||
| aec3d31e17 | |||
| c99a0429b4 | |||
| f9fc90244f | |||
| 6b0198f732 | |||
| f0e52b42d7 | |||
| 381850ada4 | |||
| 8b22d5fadd | |||
| 01171b9487 | |||
| d3a1ce1c25 | |||
| 3b6863786f | |||
| 1d39945e62 | |||
| f0f1d5174e | |||
| 11e0f21e03 | |||
| 59183657e8 | |||
| 47a75d4291 | |||
| 32a449f460 | |||
| d9aea500bf | |||
| 8c947322ae | |||
| 5b397a4f49 | |||
| 44c79e8a7c | |||
| 40db9062ce | |||
| dafb0f81d4 | |||
| f8df682b62 | |||
| 293dc29183 | |||
| ef1b8b3414 | |||
| 58bbb99c94 | |||
| b829884008 | |||
| e82756172b | |||
| 58651a3325 | |||
| 328b5775aa | |||
| 64f22aa758 | |||
| bc9e9c31b5 | |||
| c4d1d2ade3 | |||
| 97874ce1ef | |||
| dcc826e8a6 | |||
| 31bb7a0a2b | |||
| d83742315f | |||
| 7e4cbc0533 | |||
| 87d752c5e3 | |||
| 5f2de0e862 | |||
| 0d4f17dd25 | |||
| 9ba965ecf0 | |||
| 31b0ba8e28 | |||
| 9edd9d562a | |||
| d30abc6a1a | |||
| 78d1bfb275 | |||
| b6de13f1ac | |||
| 1dbd52fd75 | |||
| 0917d4b6b8 | |||
| d10b42dc5a | |||
| 78f34ecaa5 | |||
| cc2d356223 | |||
| 2c8a578f92 | |||
| 2e5b1c4d01 | |||
| a58ac858ab | |||
| ebfb4c421e | |||
| b08324e6dd | |||
| 72dda814c6 | |||
| e76daca899 | |||
| bafcc02862 | |||
| 9d80750467 | |||
| 8c93fafa37 | |||
| e518246f26 | |||
| a1256c3297 | |||
| 84ca6d41ae | |||
| d94ef105cf | |||
| 361985f236 | |||
| 6987b4636a | |||
| 18f56fa818 | |||
| 5724b8424f | |||
| f62b3be08e | |||
| a4c21168ab | |||
| f1ec5add4b | |||
| 62ed0c6496 | |||
| 3d5e5c3e1d | |||
| 7e33f7121a | |||
| 09fefa292a | |||
| 47c6d744ba | |||
| fc32f8282e | |||
| 7ee84c24f0 | |||
| 12a15f1051 | |||
| 6a8f927510 | |||
| 3bf16ecae9 | |||
| 5a7b211f16 | |||
| 189c907bb9 | |||
| 6f16ae64ab | |||
| b911dfa9e2 | |||
| 2335a371b6 | |||
| b41d7ad944 | |||
| 4ffb2e1e0c | |||
| 9ae2adb81c | |||
| 185782daab | |||
| 51acae13a1 | |||
| 03217243d9 | |||
| 072e45902d | |||
| 326037ce93 | |||
| f447549666 | |||
| eba1d39ba3 | |||
| 8d28b65add | |||
| e72a54356e | |||
| 86440913ba | |||
| c1ac9e4a2f | |||
| 6f185f9e53 | |||
| d142629dd3 | |||
| 84d9c0f5da | |||
| 5f400d3c91 | |||
| 409b58c53c | |||
| 0b6108dea8 | |||
| c7fe1c4114 | |||
| 318d59dadd | |||
| ffd12921a4 | |||
| ef2f02743f | |||
| 74d63d31e3 | |||
| 49c7bdee0c |
+199
@@ -0,0 +1,199 @@
|
||||
# Changelog
|
||||
|
||||
## <a href="https://github.com/Jawbone/JBChartView/tree/v2.8.4">2.8.4</a>
|
||||
#### 08/27/14
|
||||
- Fixes issue <a href="https://github.com/Jawbone/JBChartView/issues/97">#97</a>.
|
||||
|
||||
## <a href="https://github.com/Jawbone/JBChartView/tree/v2.8.3">2.8.3</a>
|
||||
#### 08/26/14
|
||||
- Fixes issue <a href="https://github.com/Jawbone/JBChartView/issues/93">#93</a>.
|
||||
|
||||
## <a href="https://github.com/Jawbone/JBChartView/tree/v2.8.2">2.8.2</a>
|
||||
#### 08/26/14
|
||||
- Fixes issue <a href="https://github.com/Jawbone/JBChartView/issues/96">#96</a>.
|
||||
- Fixes issue <a href="https://github.com/Jawbone/JBChartView/issues/95">#95</a>.
|
||||
|
||||
## <a href="https://github.com/Jawbone/JBChartView/tree/v2.8.1">2.8.1</a>
|
||||
#### 08/22/14
|
||||
- Fixes issue <a href="https://github.com/Jawbone/JBChartView/issues/92">#92</a>.
|
||||
|
||||
## <a href="https://github.com/Jawbone/JBChartView/tree/v2.8.0">2.8.0</a>
|
||||
#### 08/14/14
|
||||
- Fixes issue <a href="https://github.com/Jawbone/JBChartView/pull/90">#90</a>.
|
||||
|
||||
## <a href="https://github.com/Jawbone/JBChartView/tree/v2.7.4">2.7.4</a>
|
||||
#### 08/14/14
|
||||
- Fixes issue <a href="https://github.com/Jawbone/JBChartView/pull/89">#89</a>.
|
||||
|
||||
## <a href="https://github.com/Jawbone/JBChartView/tree/v2.7.3">2.7.3</a>
|
||||
#### 08/07/14
|
||||
- Fixes issue <a href="https://github.com/Jawbone/JBChartView/pull/83">#83</a>.
|
||||
|
||||
## <a href="https://github.com/Jawbone/JBChartView/tree/v2.7.2">2.7.2</a>
|
||||
#### 08/04/14
|
||||
- Fixes issue <a href="https://github.com/Jawbone/JBChartView/pull/78">#78</a>.
|
||||
|
||||
## <a href="https://github.com/Jawbone/JBChartView/tree/v2.7.1">2.7.1</a>
|
||||
#### 08/04/14
|
||||
- Fixes issue <a href="https://github.com/Jawbone/JBChartView/pull/77">#77</a>.
|
||||
|
||||
## <a href="https://github.com/Jawbone/JBChartView/tree/v2.7.0">2.7.0</a>
|
||||
#### 08/02/14
|
||||
- Fixes issue <a href="https://github.com/Jawbone/JBChartView/pull/76">#76</a>.
|
||||
|
||||
## <a href="https://github.com/Jawbone/JBChartView/tree/v2.6.3">2.6.3</a>
|
||||
#### 07/31/14
|
||||
- Fixes issue <a href="https://github.com/Jawbone/JBChartView/pull/75">#75</a>.
|
||||
|
||||
## <a href="https://github.com/Jawbone/JBChartView/tree/v2.6.2">2.6.2</a>
|
||||
#### 07/25/14
|
||||
- Added new controller (JBAreaChartViewController) to demonstrate area charts.
|
||||
|
||||
## <a href="https://github.com/Jawbone/JBChartView/tree/v2.6.1">2.6.1</a>
|
||||
#### 07/25/14
|
||||
- Fixes issue <a href="https://github.com/Jawbone/JBChartView/pull/74">#74</a>.
|
||||
|
||||
## <a href="https://github.com/Jawbone/JBChartView/tree/v2.6.0">2.6.0</a>
|
||||
#### 07/24/14
|
||||
- Fixes issue <a href="https://github.com/Jawbone/JBChartView/pull/71">#71</a>.
|
||||
|
||||
## <a href="https://github.com/Jawbone/JBChartView/tree/v2.5.5">2.5.5</a>
|
||||
#### 05/13/14
|
||||
- Fixes issue <a href="https://github.com/Jawbone/JBChartView/pull/57">#57</a>.
|
||||
|
||||
## <a href="https://github.com/Jawbone/JBChartView/tree/v2.5.4">2.5.4</a>
|
||||
#### 05/07/14
|
||||
- Fixes issue <a href="https://github.com/Jawbone/JBChartView/pull/53">#53</a>.
|
||||
|
||||
## <a href="https://github.com/Jawbone/JBChartView/tree/v2.5.3">2.5.3</a>
|
||||
#### 05/06/14
|
||||
- More compiler warning fixes.
|
||||
|
||||
## <a href="https://github.com/Jawbone/JBChartView/tree/v2.5.2">2.5.2</a>
|
||||
#### 05/06/14
|
||||
- Fixed compiler warnings.
|
||||
|
||||
## <a href="https://github.com/Jawbone/JBChartView/tree/v2.5.1">2.5.1</a>
|
||||
#### 05/05/14
|
||||
- Additional fixes to issue <a href="https://github.com/Jawbone/JBChartView/pull/48">#48</a>.
|
||||
|
||||
## <a href="https://github.com/Jawbone/JBChartView/tree/v2.5.0">2.5.0</a>
|
||||
#### 05/04/14
|
||||
- Fixes issue <a href="https://github.com/Jawbone/JBChartView/pull/48">#48</a>.
|
||||
|
||||
## <a href="https://github.com/Jawbone/JBChartView/tree/v2.4.3">2.4.3</a>
|
||||
#### 05/04/14
|
||||
- Fixes issue <a href="https://github.com/Jawbone/JBChartView/pull/49">#49</a>.
|
||||
|
||||
## <a href="https://github.com/Jawbone/JBChartView/tree/v2.4.2">2.4.2</a>
|
||||
#### 04/30/14
|
||||
- Fixes issue <a href="https://github.com/Jawbone/JBChartView/pull/46">#46</a>.
|
||||
|
||||
## <a href="https://github.com/Jawbone/JBChartView/tree/v2.4.1">2.4.1</a>
|
||||
#### 04/30/14
|
||||
- Fixes issue <a href="https://github.com/Jawbone/JBChartView/pull/45">#45</a>.
|
||||
|
||||
## <a href="https://github.com/Jawbone/JBChartView/tree/v2.4.0">2.4.0</a>
|
||||
#### 04/28/14
|
||||
- Fixes issue <a href="https://github.com/Jawbone/JBChartView/pull/23">#23</a>.
|
||||
|
||||
## <a href="https://github.com/Jawbone/JBChartView/tree/v2.3.0">2.3.0</a>
|
||||
#### 04/17/14
|
||||
- Fixes issue <a href="https://github.com/Jawbone/JBChartView/pull/34">#34</a>.
|
||||
|
||||
## <a href="https://github.com/Jawbone/JBChartView/tree/v2.2.0">2.2.0</a>
|
||||
#### 04/14/14
|
||||
- Fixes issue <a href="https://github.com/Jawbone/JBChartView/pull/37">#37</a>.
|
||||
|
||||
## <a href="https://github.com/Jawbone/JBChartView/tree/v2.1.6">2.1.6</a>
|
||||
#### 04/11/14
|
||||
- Fixes issue <a href="https://github.com/Jawbone/JBChartView/pull/33">#33</a>.
|
||||
|
||||
## <a href="https://github.com/Jawbone/JBChartView/tree/v2.1.5">2.1.5</a>
|
||||
#### 04/10/14
|
||||
- Fixes issue <a href="https://github.com/Jawbone/JBChartView/pull/30">#30</a>.
|
||||
|
||||
## <a href="https://github.com/Jawbone/JBChartView/tree/v2.1.4">2.1.4</a>
|
||||
#### 04/10/14
|
||||
- Added ability to specify a radius for dotted lines.
|
||||
|
||||
## <a href="https://github.com/Jawbone/JBChartView/tree/v2.1.3">2.1.3</a>
|
||||
#### 04/03/14
|
||||
- Added the ability to force a chart's state.
|
||||
|
||||
## <a href="https://github.com/Jawbone/JBChartView/tree/v2.1.2">2.1.2</a>
|
||||
#### 04/02/14
|
||||
- Added dynamic padding to JBLineChartView (based on max line width).
|
||||
|
||||
## <a href="https://github.com/Jawbone/JBChartView/tree/v2.1.1">2.1.1</a>
|
||||
#### 04/02/14
|
||||
- Fixed minimumValue and maximumValue getter functions.
|
||||
|
||||
## <a href="https://github.com/Jawbone/JBChartView/tree/v2.1.0">2.1.0</a>
|
||||
#### 03/30/14
|
||||
- Added minimumValue and maximumValue properties.
|
||||
- Changed default min value implementation from 0 to chart's actual minimum value.
|
||||
|
||||
## <a href="https://github.com/Jawbone/JBChartView/tree/v2.0.2">2.0.2</a>
|
||||
#### 03/27/14
|
||||
- Added the ability to add point dots for lines in JBLineChartView.
|
||||
- Streamlined line styling.
|
||||
|
||||
## <a href="https://github.com/Jawbone/JBChartView/tree/v2.0.1">2.0.1</a>
|
||||
#### 03/19/14
|
||||
- Fixes issue <a href="https://github.com/Jawbone/JBChartView/pull/22">#22</a>.
|
||||
|
||||
## <a href="https://github.com/Jawbone/JBChartView/tree/v2.0.0">2.0.0</a>
|
||||
#### 03/18/14
|
||||
- Fixes issue <a href="https://github.com/Jawbone/JBChartView/pull/21">#21</a>.
|
||||
- Added multi-line support for JBLineChartView.
|
||||
- Added position delegation on touch events.
|
||||
- Added tooltip views (demo-only).
|
||||
|
||||
## <a href="https://github.com/Jawbone/JBChartView/tree/v1.1.6">1.1.6</a>
|
||||
#### 03/02/14
|
||||
- Fixes issue <a href="https://github.com/Jawbone/JBChartView/pull/15">#15</a>.
|
||||
- Fixes issue <a href="https://github.com/Jawbone/JBChartView/pull/14">#14</a>.
|
||||
|
||||
## <a href="https://github.com/Jawbone/JBChartView/tree/v1.1.5">1.1.5</a>
|
||||
#### 02/11/14
|
||||
- Chart selection improvements.
|
||||
- Animation performance improvements.
|
||||
|
||||
## <a href="https://github.com/Jawbone/JBChartView/tree/v1.1.4">1.1.4</a>
|
||||
#### 02/06/14
|
||||
- Fixed compilation warnings.
|
||||
|
||||
## <a href="https://github.com/Jawbone/JBChartView/tree/v1.1.3">1.1.3</a>
|
||||
#### 01/06/14
|
||||
- Fixes issue <a href="https://github.com/Jawbone/JBChartView/pull/11">#11</a>.
|
||||
|
||||
## <a href="https://github.com/Jawbone/JBChartView/tree/v1.1.2">1.1.2</a>
|
||||
#### 01/03/14
|
||||
- Added CGFloat support for chart heights intead of integers.
|
||||
|
||||
## <a href="https://github.com/Jawbone/JBChartView/tree/v1.1.1">1.1.1</a>
|
||||
#### 01/02/14
|
||||
- Fixes issue <a href="https://github.com/Jawbone/JBChartView/pull/7">#7</a>.
|
||||
|
||||
## <a href="https://github.com/Jawbone/JBChartView/tree/v1.1.0">1.1.0</a>
|
||||
#### 12/26/13
|
||||
- Updated JBBarChartView datasource to request UIView subclasses for bars.
|
||||
|
||||
## <a href="https://github.com/Jawbone/JBChartView/tree/v1.0.3">1.0.3</a>
|
||||
#### 12/23/13
|
||||
- Fixes issue <a href="https://github.com/Jawbone/JBChartView/pull/4">#4</a>.
|
||||
|
||||
## <a href="https://github.com/Jawbone/JBChartView/tree/v1.0.2">1.0.2</a>
|
||||
#### 12/17/13
|
||||
- Additional fixes for issue <a href="https://github.com/Jawbone/JBChartView/pull/2">#2</a>.
|
||||
|
||||
## <a href="https://github.com/Jawbone/JBChartView/tree/v1.0.1">1.0.1</a>
|
||||
#### (12/14/13)
|
||||
- Fixes issue <a href="https://github.com/Jawbone/JBChartView/pull/2">#2</a>.
|
||||
|
||||
## <a href="https://github.com/Jawbone/JBChartView/tree/v1.0">1.0</a>
|
||||
#### 12/10/13
|
||||
- Initial public release.
|
||||
- Base line and bar charts.
|
||||
- Basic customization; color, positioning, selections.
|
||||
+96
-73
@@ -9,108 +9,131 @@
|
||||
// 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)
|
||||
*/
|
||||
- (NSInteger)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.
|
||||
* A UIView subclass representing the bar at a particular index.
|
||||
*
|
||||
* Default: 'best-guess' algorithm based on the the total number of bars and width of the chart.
|
||||
* Default: solid black UIView.
|
||||
*
|
||||
* @param barChartView The origin chart
|
||||
* @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 Horizontal width (in pixels) between each bar.
|
||||
* @return A UIView subclass. The view will automatically be resized by the chart during creation (ie. no need to set the frame).
|
||||
*/
|
||||
- (NSInteger)barPaddingForBarChartView:(JBBarChartView *)barChartView;
|
||||
- (UIView *)barChartView:(JBBarChartView *)barChartView barViewAtIndex:(NSUInteger)index;
|
||||
|
||||
@end
|
||||
|
||||
@protocol JBBarChartViewDelegate <JBChartViewDelegate>
|
||||
|
||||
@required
|
||||
|
||||
/**
|
||||
* The color of all bars within the chart.
|
||||
* 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: 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).
|
||||
*
|
||||
* @param barChartView The origin chart
|
||||
* @param index The 0-based index of a given bar (left to right, x-axis)
|
||||
*
|
||||
* @return The color to be used on each of the bars within the chart.
|
||||
* @return The y-axis height of the supplied bar index (x-axis)
|
||||
*/
|
||||
- (UIColor *)barColorForBarChartView:(JBBarChartView *)barChartView atIndex:(NSInteger)index;
|
||||
- (CGFloat)barChartView:(JBBarChartView *)barChartView heightForBarViewAtIndex:(NSUInteger)index;
|
||||
|
||||
@optional
|
||||
|
||||
/**
|
||||
* The selection color to be overlayed on a bar during touch events.
|
||||
* The color is automically faded to transparent (vertically).
|
||||
* 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.
|
||||
*
|
||||
* Default: white color (faded to transparent)
|
||||
* @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 The origin chart
|
||||
* @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: if none specified - calls barChartView:barViewAtIndex:.
|
||||
*
|
||||
* @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;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
@end
|
||||
|
||||
+340
-166
@@ -9,37 +9,49 @@
|
||||
#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 JBChartView (Private)
|
||||
|
||||
- (BOOL)hasMaximumValue;
|
||||
- (BOOL)hasMinimumValue;
|
||||
|
||||
@end
|
||||
|
||||
@interface JBBarChartView ()
|
||||
|
||||
@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)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
|
||||
|
||||
@@ -55,18 +67,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
|
||||
@@ -78,6 +115,10 @@ static UIColor *kJBBarChartViewDefaultBarColor = nil;
|
||||
|
||||
- (void)reloadData
|
||||
{
|
||||
// reset cached max height
|
||||
self.cachedMinHeight = kJBBarChartViewUndefinedCachedHeight;
|
||||
self.cachedMaxHeight = kJBBarChartViewUndefinedCachedHeight;
|
||||
|
||||
/*
|
||||
* The data collection holds all position information:
|
||||
* constructed via datasource and delegate functions
|
||||
@@ -85,15 +126,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 numberWithInt:(int)[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];
|
||||
};
|
||||
@@ -102,17 +145,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
|
||||
*/
|
||||
@@ -124,53 +167,95 @@ 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 = [[UIView alloc] init];
|
||||
if ([self.dataSource respondsToSelector:@selector(barColorForBarChartView:atIndex:)])
|
||||
UIView *barView = nil; // since all bars are visible at once, no need to cache this view
|
||||
if ([self.dataSource respondsToSelector:@selector(barChartView:barViewAtIndex:)])
|
||||
{
|
||||
barView.backgroundColor = [self.dataSource barColorForBarChartView:self atIndex:index];
|
||||
barView = [self.dataSource barChartView:self barViewAtIndex:index];
|
||||
NSAssert(barView != nil, @"JBBarChartView // datasource function - (UIView *)barChartView:(JBBarChartView *)barChartView barViewAtIndex:(NSUInteger)index must return a non-nil UIView subclass");
|
||||
}
|
||||
else
|
||||
{
|
||||
barView.backgroundColor = kJBBarChartViewDefaultBarColor;
|
||||
barView = [[UIView alloc] init];
|
||||
UIColor *backgroundColor = nil;
|
||||
|
||||
if ([self.delegate respondsToSelector:@selector(barChartView:colorForBarViewAtIndex:)])
|
||||
{
|
||||
backgroundColor = [self.delegate barChartView:self colorForBarViewAtIndex:index];
|
||||
NSAssert(backgroundColor != nil, @"JBBarChartView // delegate function - (UIColor *)barChartView:(JBBarChartView *)barChartView colorForBarViewAtIndex:(NSUInteger)index must return a non-nil UIColor");
|
||||
}
|
||||
else
|
||||
{
|
||||
backgroundColor = kJBBarChartViewDefaultBarColor;
|
||||
}
|
||||
|
||||
barView.backgroundColor = backgroundColor;
|
||||
}
|
||||
|
||||
barView.tag = index;
|
||||
|
||||
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);
|
||||
|
||||
barView.layer.shadowColor = [UIColor blackColor].CGColor;
|
||||
barView.layer.shadowOffset = CGSizeMake(0, 0);
|
||||
barView.layer.shadowOpacity = 0.4;
|
||||
barView.layer.shadowRadius = 1.0;
|
||||
|
||||
barView.frame = CGRectMake(xOffset, self.bounds.size.height - height - self.footerView.frame.size.height, [self barWidth], height);
|
||||
[mutableBarViews addObject:barView];
|
||||
[self insertSubview:barView belowSubview:self.footerView];
|
||||
[mutableCachedBarViewHeights addObject:[NSNumber numberWithFloat:height]];
|
||||
|
||||
// Add new bar
|
||||
if (self.footerView)
|
||||
{
|
||||
[self insertSubview:barView belowSubview:self.footerView];
|
||||
}
|
||||
else
|
||||
{
|
||||
[self addSubview:barView];
|
||||
}
|
||||
|
||||
xOffset += ([self barWidth] + self.barPadding);
|
||||
index++;
|
||||
}
|
||||
self.barViews = [NSArray arrayWithArray:mutableBarViews];
|
||||
self.cachedBarViewHeights = [NSArray arrayWithArray:mutableCachedBarViewHeights];
|
||||
};
|
||||
|
||||
/*
|
||||
* Creates a vertical selection view for touch events
|
||||
*/
|
||||
dispatch_block_t createSelectionView = ^{
|
||||
if (self.selectionView)
|
||||
|
||||
// Remove old selection bar
|
||||
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:)])
|
||||
self.verticalSelectionView = [[JBChartVerticalSelectionView alloc] initWithFrame:CGRectMake(0, 0, [self barWidth], self.bounds.size.height - self.footerView.frame.size.height - self.headerView.frame.size.height - self.headerPadding)];
|
||||
self.verticalSelectionView.alpha = 0.0;
|
||||
self.verticalSelectionView.hidden = !self.showsVerticalSelection;
|
||||
if ([self.delegate respondsToSelector:@selector(barSelectionColorForBarChartView:)])
|
||||
{
|
||||
self.selectionView.bgColor = [self.dataSource selectionBarColorForBarChartView:self];
|
||||
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;
|
||||
}
|
||||
[self insertSubview:self.selectionView belowSubview:self.footerView];
|
||||
|
||||
// Add new selection bar
|
||||
if (self.footerView)
|
||||
{
|
||||
[self insertSubview:self.verticalSelectionView belowSubview:self.footerView];
|
||||
}
|
||||
else
|
||||
{
|
||||
[self addSubview:self.verticalSelectionView];
|
||||
}
|
||||
|
||||
self.verticalSelectionView.transform = self.inverted ? CGAffineTransformMakeScale(1.0, -1.0) : CGAffineTransformIdentity;
|
||||
};
|
||||
|
||||
createDataDictionaries();
|
||||
@@ -178,9 +263,12 @@ 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
|
||||
@@ -192,8 +280,8 @@ static UIColor *kJBBarChartViewDefaultBarColor = nil;
|
||||
|
||||
- (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)
|
||||
@@ -201,28 +289,12 @@ static UIColor *kJBBarChartViewDefaultBarColor = nil;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ceil(((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;
|
||||
return ((value - minHeight) / (maxHeight - minHeight)) * [self availableHeight];
|
||||
}
|
||||
|
||||
- (CGFloat)barWidth
|
||||
{
|
||||
NSInteger barCount = [[self.chartDataDictionary allKeys] count];
|
||||
NSUInteger barCount = [[self.chartDataDictionary allKeys] count];
|
||||
if (barCount > 0)
|
||||
{
|
||||
CGFloat totalPadding = (barCount - 1) * self.barPadding;
|
||||
@@ -234,57 +306,108 @@ 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.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.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.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);
|
||||
}
|
||||
NSUInteger index = 0;
|
||||
for (UIView *barView in self.barViews)
|
||||
{
|
||||
[UIView animateWithDuration:kJBBarChartViewStateAnimationDuration delay:(kJBBarChartViewStateAnimationDuration * 0.5) * index options:UIViewAnimationOptionBeginFromCurrentState animations:^{
|
||||
updateBarView(barView, YES);
|
||||
} completion:^(BOOL finished) {
|
||||
if (index == [self.barViews count] - 1)
|
||||
{
|
||||
if (callbackCopy)
|
||||
[UIView animateWithDuration:kJBBarChartViewStateAnimationDuration delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
|
||||
updateBarView(barView, NO);
|
||||
} completion:^(BOOL lastBarFinished) {
|
||||
if (barView.tag == [self.barViews count] - 1)
|
||||
{
|
||||
callbackCopy();
|
||||
if (callbackCopy)
|
||||
{
|
||||
callbackCopy();
|
||||
}
|
||||
}
|
||||
}
|
||||
}];
|
||||
}];
|
||||
}];
|
||||
index++;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
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();
|
||||
@@ -292,6 +415,51 @@ static UIColor *kJBBarChartViewDefaultBarColor = nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setState:(JBChartViewState)state animated:(BOOL)animated callback:(void (^)())callback
|
||||
{
|
||||
[self setState:state animated:animated force:NO callback:callback];
|
||||
}
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
#pragma mark - Touch Helpers
|
||||
|
||||
- (NSInteger)barViewIndexForPoint:(CGPoint)point
|
||||
@@ -325,103 +493,109 @@ 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;
|
||||
}
|
||||
|
||||
- (void)touchesBeganOrMovedWithTouches:(NSSet *)touches
|
||||
{
|
||||
if (self.state == JBChartViewStateCollapsed || [[self.chartDataDictionary allKeys] count] <= 0)
|
||||
{
|
||||
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;
|
||||
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)touchesEndedOrCancelledWithTouches:(NSSet *)touches
|
||||
{
|
||||
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 - Setters
|
||||
|
||||
- (void)setSelectionViewVisible:(BOOL)selectionViewVisible animated:(BOOL)animated
|
||||
- (void)setVerticalSelectionViewVisible:(BOOL)verticalSelectionViewVisible animated:(BOOL)animated
|
||||
{
|
||||
_selectionViewVisible = selectionViewVisible;
|
||||
_verticalSelectionViewVisible = verticalSelectionViewVisible;
|
||||
|
||||
if (animated)
|
||||
{
|
||||
[UIView animateWithDuration:kJBChartViewDefaultAnimationDuration delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
|
||||
self.selectionView.alpha = _selectionViewVisible ? 1.0 : 0.0;
|
||||
self.verticalSelectionView.alpha = self.verticalSelectionViewVisible ? 1.0 : 0.0;
|
||||
} completion:nil];
|
||||
}
|
||||
else
|
||||
{
|
||||
self.selectionView.alpha = _selectionViewVisible ? 1.0 : 0.0;
|
||||
self.verticalSelectionView.alpha = _verticalSelectionViewVisible ? 1.0 : 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setSelectionViewVisible:(BOOL)selectionViewVisible
|
||||
- (void)setVerticalSelectionViewVisible:(BOOL)verticalSelectionViewVisible
|
||||
{
|
||||
[self setSelectionViewVisible:selectionViewVisible animated:NO];
|
||||
[self setVerticalSelectionViewVisible:verticalSelectionViewVisible animated:NO];
|
||||
}
|
||||
|
||||
- (void)setShowsVerticalSelection:(BOOL)showsVerticalSelection
|
||||
{
|
||||
_showsVerticalSelection = showsVerticalSelection;
|
||||
self.verticalSelectionView.hidden = _showsVerticalSelection ? NO : YES;
|
||||
}
|
||||
|
||||
#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 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];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
+61
-12
@@ -24,20 +24,59 @@ typedef NS_ENUM(NSInteger, JBChartViewState){
|
||||
JBChartViewStateCollapsed
|
||||
};
|
||||
|
||||
@protocol JBChartViewDataSource <NSObject>
|
||||
|
||||
// Extend (via subclass) to add custom functionality
|
||||
|
||||
@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).
|
||||
*/
|
||||
@property (nonatomic, assign) CGFloat headerPadding;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
@@ -51,19 +90,29 @@ typedef NS_ENUM(NSInteger, JBChartViewState){
|
||||
- (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 +120,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
@@ -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
+257
-56
@@ -8,96 +8,297 @@
|
||||
|
||||
#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
|
||||
|
||||
@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;
|
||||
* Returns the number of lines for the line chart.
|
||||
*
|
||||
* @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 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 is automatically hidden.
|
||||
*
|
||||
* 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;
|
||||
|
||||
@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.
|
||||
*
|
||||
* @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.
|
||||
* @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)
|
||||
*/
|
||||
- (NSInteger)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 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 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 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 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 3.
|
||||
*
|
||||
* @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 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 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;
|
||||
|
||||
@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;
|
||||
|
||||
/**
|
||||
* The selection color to be overlayed on the chart during touch events.
|
||||
* The color is automically faded to transparent (vertically).
|
||||
*
|
||||
* Default: white color (faded to transparent)
|
||||
*
|
||||
* @param lineChartView The origin chart
|
||||
*
|
||||
* @return The color to be used on chart selections.
|
||||
*/
|
||||
- (UIColor *)selectionColorForLineChartView:(JBLineChartView *)lineChartView;
|
||||
@property (nonatomic, assign) BOOL showsLineSelection;
|
||||
|
||||
@end
|
||||
|
||||
Regular → Executable
+1268
-311
File diff suppressed because it is too large
Load Diff
@@ -1,17 +1,19 @@
|
||||
Pod::Spec.new do |s|
|
||||
s.name = "JBChartView"
|
||||
s.version = "1.0"
|
||||
s.version = "2.8.4"
|
||||
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.0"
|
||||
:tag => "v2.8.4"
|
||||
}
|
||||
|
||||
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
|
||||
@@ -15,6 +15,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,10 +33,15 @@
|
||||
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 */
|
||||
@@ -55,6 +61,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 +89,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 +106,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,6 +190,8 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9B603D3B182C6E79000A76D0 /* Base */,
|
||||
9B7967EA198313E30003A2B0 /* JBAreaChartViewController.h */,
|
||||
9B7967EB198313E30003A2B0 /* JBAreaChartViewController.m */,
|
||||
9B6A68DC1829BE63006DB3BF /* JBBarChartViewController.h */,
|
||||
9B6A68DD1829BE63006DB3BF /* JBBarChartViewController.m */,
|
||||
9B07251F1829822A0052109B /* JBChartListViewController.h */,
|
||||
@@ -187,6 +205,8 @@
|
||||
9B603D3B182C6E79000A76D0 /* Base */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9BEE694418D2789E005D9BA7 /* JBBaseChartViewController.h */,
|
||||
9BEE694518D2789E005D9BA7 /* JBBaseChartViewController.m */,
|
||||
9B603D3C182C6E79000A76D0 /* JBBaseNavigationController.h */,
|
||||
9B603D3D182C6E79000A76D0 /* JBBaseNavigationController.m */,
|
||||
9B603D4C182C7163000A76D0 /* JBBaseTableViewController.h */,
|
||||
@@ -208,6 +228,8 @@
|
||||
9B603D44182C7002000A76D0 /* Images */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
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 +313,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 +347,7 @@
|
||||
9B2E52F918218CF20079B9D2 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0500;
|
||||
LastUpgradeCheck = 0510;
|
||||
ORGANIZATIONNAME = Jawbone;
|
||||
};
|
||||
buildConfigurationList = 9B2E52FC18218CF20079B9D2 /* Build configuration list for PBXProject "JBChartViewDemo" */;
|
||||
@@ -353,8 +379,10 @@
|
||||
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 */,
|
||||
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 +406,13 @@
|
||||
9BE0B0C7182B161000232023 /* JBChartHeaderView.m in Sources */,
|
||||
9B603D4E182C7163000A76D0 /* JBBaseTableViewController.m in Sources */,
|
||||
9B6A68DE1829BE63006DB3BF /* JBBarChartViewController.m in Sources */,
|
||||
9B4437AD18D7686800682EF0 /* JBChartTooltipTipView.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 +436,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;
|
||||
@@ -444,7 +475,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 +512,7 @@
|
||||
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_NAME = "$(TARGET_NAME)";
|
||||
WRAPPER_EXTENSION = app;
|
||||
};
|
||||
@@ -496,7 +526,7 @@
|
||||
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_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,33 @@
|
||||
#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:1.0 green:0.0 blue:0.0 alpha:1.0]
|
||||
#define kJBColorLineChartDefaultDashedSelectedLineColor [UIColor colorWithWhite:1.0 alpha:1.0]
|
||||
|
||||
#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,31 @@
|
||||
|
||||
#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")
|
||||
|
||||
@@ -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,130 @@
|
||||
//
|
||||
// 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.25f;
|
||||
|
||||
@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];
|
||||
}
|
||||
|
||||
if (!self.tooltipTipView)
|
||||
{
|
||||
self.tooltipTipView = [[JBChartTooltipTipView alloc] init];
|
||||
self.tooltipTipView.alpha = 0.0;
|
||||
[self.view addSubview:self.tooltipTipView];
|
||||
}
|
||||
|
||||
dispatch_block_t adjustTooltipPosition = ^{
|
||||
CGPoint originalTouchPoint = [self.view convertPoint:touchPoint fromView:chartView];
|
||||
CGPoint convertedTouchPoint = originalTouchPoint; // modified
|
||||
JBChartView *chartView = [self chartView];
|
||||
if (chartView)
|
||||
{
|
||||
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 (tooltipVisible)
|
||||
{
|
||||
adjustTooltipPosition();
|
||||
}
|
||||
|
||||
if (animated)
|
||||
{
|
||||
[UIView animateWithDuration:kJBBaseChartViewControllerAnimationDuration animations:^{
|
||||
adjustTooltipVisibility();
|
||||
} completion:^(BOOL finished) {
|
||||
if (!tooltipVisible)
|
||||
{
|
||||
adjustTooltipPosition();
|
||||
}
|
||||
}];
|
||||
}
|
||||
else
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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]];
|
||||
}
|
||||
|
||||
@@ -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,285 @@
|
||||
//
|
||||
// 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;
|
||||
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;
|
||||
}
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
#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,8 +53,27 @@ 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;
|
||||
}
|
||||
@@ -65,9 +85,12 @@ NSString * const kJBBarChartViewControllerNavButtonViewKey = @"view";
|
||||
NSMutableArray *mutableChartData = [NSMutableArray array];
|
||||
for (int i=0; i<kJBBarChartViewControllerNumBars; i++)
|
||||
{
|
||||
[mutableChartData addObject:[NSNumber numberWithInteger:MAX(kJBBarChartViewControllerMinBarHeight, arc4random() % kJBBarChartViewControllerMaxBarHeight)]]; // fake height
|
||||
NSInteger delta = (kJBBarChartViewControllerNumBars - abs((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 +102,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,58 +132,55 @@ 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];
|
||||
}
|
||||
|
||||
#pragma mark - JBBarChartViewDelegate
|
||||
|
||||
- (NSInteger)barChartView:(JBBarChartView *)barChartView heightForBarViewAtAtIndex:(NSInteger)index
|
||||
{
|
||||
return [[self.chartData objectAtIndex:index] intValue];
|
||||
[self.barChartView setState:JBChartViewStateExpanded];
|
||||
}
|
||||
|
||||
#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]];
|
||||
}
|
||||
|
||||
- (UIColor *)barColorForBarChartView:(JBBarChartView *)barChartView atIndex:(NSInteger)index
|
||||
- (void)didDeselectBarChartView:(JBBarChartView *)barChartView
|
||||
{
|
||||
[self.informationView setHidden:YES animated:YES];
|
||||
[self setTooltipVisible:NO animated:YES];
|
||||
}
|
||||
|
||||
#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 *)selectionBarColorForBarChartView:(JBBarChartView *)barChartView
|
||||
- (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
|
||||
@@ -175,4 +198,11 @@ NSString * const kJBBarChartViewControllerNavButtonViewKey = @"view";
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma mark - Overrides
|
||||
|
||||
- (JBChartView *)chartView
|
||||
{
|
||||
return self.barChartView;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
// Controllers
|
||||
#import "JBBarChartViewController.h"
|
||||
#import "JBLineChartViewController.h"
|
||||
#import "JBAreaChartViewController.h"
|
||||
|
||||
// Views
|
||||
#import "JBChartTableCell.h"
|
||||
@@ -18,6 +19,7 @@
|
||||
typedef NS_ENUM(NSInteger, JBChartListViewControllerRow){
|
||||
JBChartListViewControllerRowLineChart,
|
||||
JBChartListViewControllerRowBarChart,
|
||||
JBChartListViewControllerRowAreaChart,
|
||||
JBChartListViewControllerRowCount
|
||||
};
|
||||
|
||||
@@ -50,10 +52,34 @@ 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 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;
|
||||
}
|
||||
|
||||
@@ -78,6 +104,11 @@ NSInteger const kJBChartListViewControllerCellHeight = 100;
|
||||
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
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
// Copyright (c) 2013 Jawbone. All rights reserved.
|
||||
//
|
||||
|
||||
#import "JBBaseViewController.h"
|
||||
#import "JBBaseChartViewController.h"
|
||||
|
||||
@interface JBLineChartViewController : JBBaseViewController
|
||||
@interface JBLineChartViewController : JBBaseChartViewController
|
||||
|
||||
@end
|
||||
|
||||
@@ -14,13 +14,23 @@
|
||||
#import "JBLineChartFooterView.h"
|
||||
#import "JBChartInformationView.h"
|
||||
|
||||
#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;
|
||||
NSInteger const kJBLineChartViewControllerMaxPointValue = 100; // max random value
|
||||
CGFloat const kJBLineChartViewControllerChartSolidLineWidth = 6.0f;
|
||||
CGFloat const kJBLineChartViewControllerChartDashedLineWidth = 2.0f;
|
||||
NSInteger const kJBLineChartViewControllerMaxNumChartPoints = 7;
|
||||
|
||||
// Strings
|
||||
NSString * const kJBLineChartViewControllerNavButtonViewKey = @"view";
|
||||
@@ -30,12 +40,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
|
||||
|
||||
@@ -48,7 +60,27 @@ 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;
|
||||
}
|
||||
@@ -57,12 +89,31 @@ NSString * const kJBLineChartViewControllerNavButtonViewKey = @"view";
|
||||
|
||||
- (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 numberWithInteger:arc4random() % kJBLineChartViewControllerMaxPointValue]];
|
||||
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
|
||||
@@ -74,36 +125,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];
|
||||
@@ -113,55 +165,97 @@ 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];
|
||||
}
|
||||
|
||||
#pragma mark - JBLineChartViewDelegate
|
||||
|
||||
- (NSInteger)lineChartView:(JBLineChartView *)lineChartView heightForIndex:(NSInteger)index
|
||||
{
|
||||
return [[self.chartData objectAtIndex:index] intValue];
|
||||
}
|
||||
|
||||
- (void)lineChartView:(JBLineChartView *)lineChartView didSelectChartAtIndex:(NSInteger)index
|
||||
{
|
||||
NSNumber *valueNumber = [self.chartData objectAtIndex:index];
|
||||
[self.informationView setValueText:[NSString stringWithFormat:@"%d", [valueNumber intValue]] 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];
|
||||
[self.lineChartView setState:JBChartViewStateExpanded];
|
||||
}
|
||||
|
||||
#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 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: (kJBLineChartViewControllerChartDashedLineWidth * 4);
|
||||
}
|
||||
|
||||
- (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
|
||||
@@ -177,4 +271,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;
|
||||
|
||||
@@ -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 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,17 +185,14 @@ static UIColor *kJBChartInformationViewShadowColor = nil;
|
||||
}
|
||||
else
|
||||
{
|
||||
[UIView animateWithDuration:kJBNumericDefaultAnimationDuration animations:^{
|
||||
[UIView animateWithDuration:kJBChartValueViewDefaultAnimationDuration delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
|
||||
self.titleLabel.frame = [self titleViewRectForHidden:NO];
|
||||
self.titleLabel.alpha = hidden ? 0.0 : 1.0;
|
||||
self.titleLabel.alpha = 1.0;
|
||||
self.valueView.valueLabel.alpha = 1.0;
|
||||
self.valueView.unitLabel.alpha = 1.0;
|
||||
self.separatorView.frame = [self separatorViewRectForHidden:NO];
|
||||
self.separatorView.alpha = hidden ? 0.0 : 1.0;
|
||||
} completion:^(BOOL finished) {
|
||||
[UIView animateWithDuration:kJBNumericDefaultAnimationDuration animations:^{
|
||||
self.valueView.valueLabel.alpha = hidden ? 0.0 : 1.0;
|
||||
self.valueView.unitLabel.alpha = hidden ? 0.0 : 1.0;
|
||||
}];
|
||||
}];
|
||||
self.separatorView.alpha = 1.0;
|
||||
} completion:nil];
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -276,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: 650 B |
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
@@ -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.
|
||||
@@ -35,8 +42,8 @@ Simply add the following line to your <code>Podfile</code>:
|
||||
|
||||
Your Podfile should look something like:
|
||||
|
||||
platform :ios, '7.0'
|
||||
pod 'JBChartView', '~> 1.0'
|
||||
platform :ios, '6.0'
|
||||
pod 'JBChartView', '~> 2.8.4'
|
||||
|
||||
### The Old School Way
|
||||
|
||||
@@ -48,53 +55,80 @@ 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/JBChartView.h"
|
||||
#import "JBChartView/JBBarChartView.h"
|
||||
#import "JBChartView/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 initialze 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];
|
||||
|
||||
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 nee to inform the delegate the height of each bar (automatically normalized across the entire chart):
|
||||
Secondly, you need to inform the delegate the height of each bar (automatically normalized across the entire chart):
|
||||
|
||||
- (NSInteger)barChartView:(JBBarChartView *)barChartView heightForBarViewAtAtIndex:(NSInteger)index
|
||||
- (CGFloat)barChartView:(JBBarChartView *)barChartView heightForBarViewAtAtIndex:(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];
|
||||
|
||||
#### JBLineChartView
|
||||
|
||||
Similiarily, to initialze 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;
|
||||
lineChartView.delegate = self;
|
||||
[self addSubview:lineChartView];
|
||||
|
||||
At a minimum, you need to inform the data source how many points are in the line chart:
|
||||
At a minimum, you need to inform the data source how many lines and vertical data points (for each line) are in the chart:
|
||||
|
||||
- (NSInteger)numberOfPointsInLineChartView:(JBLineChartView *)lineChartView
|
||||
- (NSUInteger)numberOfLinesInLineChartView:(JBLineChartView *)lineChartView
|
||||
{
|
||||
return ...; // number of points in chart
|
||||
return ...; // number of lines in chart
|
||||
}
|
||||
|
||||
- (NSUInteger)lineChartView:(JBLineChartView *)lineChartView numberOfVerticalValuesAtLineIndex:(NSUInteger)lineIndex
|
||||
{
|
||||
return ...; // number of values for a line
|
||||
}
|
||||
|
||||
Secondly, you nee to inform the delegate the y-position of each point (automatically normalized across the entire chart):
|
||||
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:
|
||||
|
||||
- (NSInteger)lineChartView:(JBLineChartView *)lineChartView heightForIndex:(NSInteger)index
|
||||
- (CGFloat)lineChartView:(JBLineChartView *)lineChartView verticalValueForHorizontalIndex:(NSUInteger)horizontalIndex atLineIndex:(NSUInteger)lineIndex
|
||||
{
|
||||
return ...; // y-position of poinnt at index (x-axis)
|
||||
return ...; // y-position (y-axis) of point at horizontalIndex (x-axis)
|
||||
}
|
||||
|
||||
Lastly, ensure you have set the *frame* of your lineChartView & call *reloadData* at least once:
|
||||
|
||||
lineChartView.frame = CGRectMake( ... );
|
||||
[lineChartView reloadData];
|
||||
|
||||
|
||||
## Customization
|
||||
|
||||
@@ -116,64 +150,139 @@ Lastly, any JBChartView subclass can be collapsed or expanded programmatically v
|
||||
|
||||
#### JBBarChartView
|
||||
|
||||
The color of a chart's bar can be customized via the <i>optional</i> protocol:
|
||||
By default, a bar chart will orient all bars from the bottom up. Setting the following invert proprery to YES will cause both the selection view and bars to orient themselves top down.
|
||||
|
||||
- (UIColor *)barColorForBarChartView:(JBBarChartView *)barChartView atIndex:(NSInteger)index
|
||||
@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;
|
||||
|
||||
Furthermore, the color of the selection bar (on touch events) can be customized via the <i>optional</i> protocol:
|
||||
|
||||
- (UIColor *)selectionBarColorForBarChartView:(JBBarChartView *)barChartView
|
||||
- (UIColor *)barSelectionColorForBarChartView:(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
|
||||
- (void)barChartView:(JBBarChartView *)barChartView didSelectBarAtIndex:(NSUInteger)index touchPoint:(CGPoint)touchPoint
|
||||
{
|
||||
// Update view
|
||||
}
|
||||
|
||||
- (void)barChartView:(JBBarChartView *)barChartView didUnselectBarAtIndex:(NSInteger)index
|
||||
- (void)didDeselectBarChartView:(JBBarChartView *)barChartView
|
||||
{
|
||||
// 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>.
|
||||
|
||||
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 of the chart's line can be customized via the <i>optional</i> protocol:
|
||||
The color, width and style of each line in the chart can be customized via the <i>optional</i> protocol:
|
||||
|
||||
- (UIColor *)lineColorForLineChartView:(JBLineChartView *)lineChartView
|
||||
- (UIColor *)lineChartView:(JBLineChartView *)lineChartView colorForLineAtLineIndex:(NSUInteger)lineIndex
|
||||
{
|
||||
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 *)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
|
||||
}
|
||||
|
||||
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 *)selectionColorForLineChartView:(JBLineChartView *)lineChartView
|
||||
- (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
|
||||
}
|
||||
|
||||
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 customize the size of each dot (default 3x the line width), 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 (note: custom dot views are automatically hidden when selected):
|
||||
|
||||
- (UIView *)lineChartView:(JBLineChartView *)lineChartView dotViewAtHorizontalIndex:(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;
|
||||
|
||||
Lastly, a line chart's selection events are delegated back via:
|
||||
|
||||
- (void)lineChartView:(JBLineChartView *)lineChartView didSelectChartAtIndex:(NSInteger)index
|
||||
- (void)lineChartView:(JBLineChartView *)lineChartView didSelectLineAtIndex:(NSUInteger)lineIndex horizontalIndex:(NSUInteger)horizontalIndex touchPoint:(CGPoint)touchPoint
|
||||
{
|
||||
// Update view
|
||||
}
|
||||
|
||||
- (void)lineChartView:(JBLineChartView *)lineChartView didUnselectChartAtIndex:(NSInteger)index
|
||||
- (void)didDeselectLineInLineChartView:(JBLineChartView *)lineChartView
|
||||
{
|
||||
// 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 <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.
|
||||
|
||||
## 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;
|
||||
|
||||
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.
|
||||
|
||||
|
||||
## License
|
||||
|
||||
Usage is provided under the <a href="http://www.apache.org/licenses/LICENSE-2.0" target="_blank">Apache License</a> (v2.0). See <a href="https://github.com/Jawbone/JBChartView/blob/master/LICENSE">LICENSE</a> for full details.
|
||||
Usage is provided under the <a href="http://www.apache.org/licenses/LICENSE-2.0" target="_blank">Apache License</a> (v2.0). See <a href="https://github.com/Jawbone/JBChartView/blob/master/LICENSE">LICENSE</a> for full details.
|
||||
|
||||
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 |
Reference in New Issue
Block a user