Showing
5 changed files
with
127 additions
and
1 deletions
| @@ -27,6 +27,14 @@ typedef NS_ENUM(NSUInteger, PNLegendItemStyle) { | @@ -27,6 +27,14 @@ typedef NS_ENUM(NSUInteger, PNLegendItemStyle) { | ||
| 27 | @property (assign, nonatomic) PNLegendItemStyle legendStyle; | 27 | @property (assign, nonatomic) PNLegendItemStyle legendStyle; |
| 28 | @property (assign, nonatomic) CGFloat legendFontSize; | 28 | @property (assign, nonatomic) CGFloat legendFontSize; |
| 29 | 29 | ||
| 30 | -- (UIView*) drawLegend; | 30 | +/** |
| 31 | + * returns the Legend View, or nil if no chart data is present. | ||
| 32 | + * The origin of the legend frame is 0,0 but you can set it with setFrame:(CGRect) | ||
| 33 | + * | ||
| 34 | + * @param mWidth Maximum width of legend. Height will depend on this and font size | ||
| 35 | + * | ||
| 36 | + * @return UIView of Legend | ||
| 37 | + */ | ||
| 38 | +- (UIView*) getLegendWithMaxWidth:(CGFloat)mWidth; | ||
| 31 | 39 | ||
| 32 | @end | 40 | @end |
| @@ -57,4 +57,16 @@ | @@ -57,4 +57,16 @@ | ||
| 57 | self.legendStyle = PNLegendItemStyleStacked; | 57 | self.legendStyle = PNLegendItemStyleStacked; |
| 58 | } | 58 | } |
| 59 | 59 | ||
| 60 | + | ||
| 61 | + | ||
| 62 | +/** | ||
| 63 | + * to be implemented in subclass | ||
| 64 | + */ | ||
| 65 | +- (UIView*) getLegendWithMaxWidth:(CGFloat)mWidth{ | ||
| 66 | + [self doesNotRecognizeSelector:_cmd]; | ||
| 67 | + return nil; | ||
| 68 | +} | ||
| 69 | + | ||
| 70 | + | ||
| 71 | + | ||
| 60 | @end | 72 | @end |
| @@ -81,4 +81,7 @@ | @@ -81,4 +81,7 @@ | ||
| 81 | * @return UIView of Legend | 81 | * @return UIView of Legend |
| 82 | */ | 82 | */ |
| 83 | - (UIView*) getLegendWithMaxWidth:(CGFloat)mWidth; | 83 | - (UIView*) getLegendWithMaxWidth:(CGFloat)mWidth; |
| 84 | + | ||
| 85 | + | ||
| 86 | ++ (CGSize)sizeOfString:(NSString *)text withWidth:(float)width font:(UIFont *)font; | ||
| 84 | @end | 87 | @end |
| @@ -7,6 +7,8 @@ | @@ -7,6 +7,8 @@ | ||
| 7 | // | 7 | // |
| 8 | 8 | ||
| 9 | #import "PNPieChart.h" | 9 | #import "PNPieChart.h" |
| 10 | +//needed for the expected label size | ||
| 11 | +#import "PNLineChart.h" | ||
| 10 | 12 | ||
| 11 | @interface PNPieChart() | 13 | @interface PNPieChart() |
| 12 | 14 | ||
| @@ -224,4 +226,98 @@ | @@ -224,4 +226,98 @@ | ||
| 224 | }]; | 226 | }]; |
| 225 | }]; | 227 | }]; |
| 226 | } | 228 | } |
| 229 | + | ||
| 230 | +- (UIView*) getLegendWithMaxWidth:(CGFloat)mWidth{ | ||
| 231 | + if ([self.items count] < 1) { | ||
| 232 | + return nil; | ||
| 233 | + } | ||
| 234 | + | ||
| 235 | + /* This is a small circle that refers to the chart data */ | ||
| 236 | + CGFloat legendCircle = 10; | ||
| 237 | + | ||
| 238 | + /* x and y are the coordinates of the starting point of each legend item */ | ||
| 239 | + CGFloat x = 0; | ||
| 240 | + CGFloat y = 0; | ||
| 241 | + | ||
| 242 | + /* accumulated width and height */ | ||
| 243 | + CGFloat totalWidth = 0; | ||
| 244 | + CGFloat totalHeight = 0; | ||
| 245 | + | ||
| 246 | + NSMutableArray *legendViews = [[NSMutableArray alloc] init]; | ||
| 247 | + | ||
| 248 | + | ||
| 249 | + /* Determine the max width of each legend item */ | ||
| 250 | + CGFloat maxLabelWidth = self.legendStyle == PNLegendItemStyleStacked ? (mWidth - legendCircle) : (mWidth / [self.items count] - legendCircle); | ||
| 251 | + | ||
| 252 | + /* this is used when labels wrap text and the line | ||
| 253 | + * should be in the middle of the first row */ | ||
| 254 | + CGFloat singleRowHeight = [PNLineChart sizeOfString:@"Test" | ||
| 255 | + withWidth:MAXFLOAT | ||
| 256 | + font:[UIFont systemFontOfSize:self.legendFontSize]].height; | ||
| 257 | + | ||
| 258 | + for (PNPieChartDataItem *pdata in self.items) { | ||
| 259 | + /* Expected label size*/ | ||
| 260 | + CGSize labelsize = [PNLineChart sizeOfString:pdata.textDescription | ||
| 261 | + withWidth:maxLabelWidth | ||
| 262 | + font:[UIFont systemFontOfSize:self.legendFontSize]]; | ||
| 263 | + | ||
| 264 | + | ||
| 265 | + // Add inflexion type | ||
| 266 | + [legendViews addObject:[self drawInflexion:legendCircle * .8 | ||
| 267 | + center:CGPointMake(x + legendCircle / 2, y + singleRowHeight / 2) | ||
| 268 | + andColor:pdata.color]]; | ||
| 269 | + | ||
| 270 | + UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(x + legendCircle, y, maxLabelWidth, labelsize.height)]; | ||
| 271 | + label.text = pdata.textDescription; | ||
| 272 | + label.font = [UIFont systemFontOfSize:self.legendFontSize]; | ||
| 273 | + label.lineBreakMode = NSLineBreakByWordWrapping; | ||
| 274 | + label.numberOfLines = 0; | ||
| 275 | + x += self.legendStyle == PNLegendItemStyleStacked ? 0 : labelsize.width + legendCircle; | ||
| 276 | + y += self.legendStyle == PNLegendItemStyleStacked ? labelsize.height : 0; | ||
| 277 | + | ||
| 278 | + totalWidth = self.legendStyle == PNLegendItemStyleStacked ? fmaxf(totalWidth, labelsize.width + legendCircle) : totalWidth + labelsize.width + legendCircle; | ||
| 279 | + totalHeight = self.legendStyle == PNLegendItemStyleStacked ? fmaxf(totalHeight, labelsize.height) : totalHeight + labelsize.height; | ||
| 280 | + [legendViews addObject:label]; | ||
| 281 | + } | ||
| 282 | + | ||
| 283 | + UIView *legend = [[UIView alloc] initWithFrame:CGRectMake(0, 0, totalWidth, totalHeight)]; | ||
| 284 | + | ||
| 285 | + for (UIView* v in legendViews) { | ||
| 286 | + [legend addSubview:v]; | ||
| 287 | + } | ||
| 288 | + return legend; | ||
| 289 | +} | ||
| 290 | + | ||
| 291 | + | ||
| 292 | +- (UIImageView*)drawInflexion:(CGFloat)size center:(CGPoint)center andColor:(UIColor*)color | ||
| 293 | +{ | ||
| 294 | + //Make the size a little bigger so it includes also border stroke | ||
| 295 | + CGSize aSize = CGSizeMake(size, size); | ||
| 296 | + | ||
| 297 | + | ||
| 298 | + UIGraphicsBeginImageContextWithOptions(aSize, NO, 0.0); | ||
| 299 | + CGContextRef context = UIGraphicsGetCurrentContext(); | ||
| 300 | + | ||
| 301 | + CGContextAddArc(context, size/2, size/ 2, size/2, 0, M_PI*2, YES); | ||
| 302 | + | ||
| 303 | + | ||
| 304 | + //Set some fill color | ||
| 305 | + CGContextSetFillColorWithColor(context, color.CGColor); | ||
| 306 | + | ||
| 307 | + //Finally draw | ||
| 308 | + CGContextDrawPath(context, kCGPathFill); | ||
| 309 | + | ||
| 310 | + //now get the image from the context | ||
| 311 | + UIImage *squareImage = UIGraphicsGetImageFromCurrentImageContext(); | ||
| 312 | + | ||
| 313 | + UIGraphicsEndImageContext(); | ||
| 314 | + | ||
| 315 | + //// Translate origin | ||
| 316 | + CGFloat originX = center.x - (size) / 2.0; | ||
| 317 | + CGFloat originY = center.y - (size) / 2.0; | ||
| 318 | + | ||
| 319 | + UIImageView *squareImageView = [[UIImageView alloc]initWithImage:squareImage]; | ||
| 320 | + [squareImageView setFrame:CGRectMake(originX, originY, size, size)]; | ||
| 321 | + return squareImageView; | ||
| 322 | +} | ||
| 227 | @end | 323 | @end |
| @@ -128,6 +128,13 @@ | @@ -128,6 +128,13 @@ | ||
| 128 | self.pieChart.descriptionTextShadowColor = [UIColor clearColor]; | 128 | self.pieChart.descriptionTextShadowColor = [UIColor clearColor]; |
| 129 | [self.pieChart strokeChart]; | 129 | [self.pieChart strokeChart]; |
| 130 | 130 | ||
| 131 | + | ||
| 132 | + self.pieChart.legendStyle = PNLegendItemStyleStacked; | ||
| 133 | + self.pieChart.legendFontSize = 12.0; | ||
| 134 | + | ||
| 135 | + UIView *legend = [self.pieChart getLegendWithMaxWidth:200]; | ||
| 136 | + [legend setFrame:CGRectMake(100, 400, legend.frame.size.width, legend.frame.size.width)]; | ||
| 137 | + [self.view addSubview:legend]; | ||
| 131 | 138 | ||
| 132 | [self.view addSubview:self.pieChart]; | 139 | [self.view addSubview:self.pieChart]; |
| 133 | self.changeValueButton.hidden = YES; | 140 | self.changeValueButton.hidden = YES; |
-
Please register or login to post a comment