Showing
3 changed files
with
73 additions
and
45 deletions
| @@ -71,5 +71,14 @@ | @@ -71,5 +71,14 @@ | ||
| 71 | 71 | ||
| 72 | - (void)updateChartData:(NSArray *)data; | 72 | - (void)updateChartData:(NSArray *)data; |
| 73 | 73 | ||
| 74 | + | ||
| 75 | +/** | ||
| 76 | + * returns the Legend View, or nil if no chart data is present. | ||
| 77 | + * The origin of the legend frame is 0,0 but you can set it with setFrame:(CGRect) | ||
| 78 | + * | ||
| 79 | + * @param mWidth Maximum width of legend. Height will depend on this and font size | ||
| 80 | + * | ||
| 81 | + * @return UIView of Legend | ||
| 82 | + */ | ||
| 74 | - (UIView*) getLegendWithMaxWidth:(CGFloat)mWidth; | 83 | - (UIView*) getLegendWithMaxWidth:(CGFloat)mWidth; |
| 75 | @end | 84 | @end |
| @@ -736,91 +736,108 @@ | @@ -736,91 +736,108 @@ | ||
| 736 | if ([self.chartData count] < 1) { | 736 | if ([self.chartData count] < 1) { |
| 737 | return nil; | 737 | return nil; |
| 738 | } | 738 | } |
| 739 | + | ||
| 740 | + /* This is a short line that refers to the chart data */ | ||
| 739 | CGFloat legendLineWidth = 40; | 741 | CGFloat legendLineWidth = 40; |
| 742 | + | ||
| 743 | + /* x and y are the coordinates of the starting point of each legend item */ | ||
| 740 | CGFloat x = 0; | 744 | CGFloat x = 0; |
| 741 | CGFloat y = 0; | 745 | CGFloat y = 0; |
| 746 | + | ||
| 747 | + /* accumulated width and height */ | ||
| 742 | CGFloat totalWidth = 0; | 748 | CGFloat totalWidth = 0; |
| 743 | CGFloat totalHeight = 0; | 749 | CGFloat totalHeight = 0; |
| 744 | 750 | ||
| 745 | - NSMutableArray *legendLabels = [[NSMutableArray alloc] init]; | 751 | + NSMutableArray *legendViews = [[NSMutableArray alloc] init]; |
| 746 | - NSMutableArray *legendLines = [[NSMutableArray alloc] init]; | ||
| 747 | - NSMutableArray *legendInflexion = [[NSMutableArray alloc] init]; | ||
| 748 | - for (PNLineChartData *pdata in self.chartData) { | ||
| 749 | 752 | ||
| 753 | + | ||
| 754 | + /* Determine the max width of each legend item */ | ||
| 750 | CGFloat maxLabelWidth = self.legendStyle == PNLegendItemStyleStacked ? (mWidth - legendLineWidth) : (mWidth / [self.chartData count] - legendLineWidth); | 755 | CGFloat maxLabelWidth = self.legendStyle == PNLegendItemStyleStacked ? (mWidth - legendLineWidth) : (mWidth / [self.chartData count] - legendLineWidth); |
| 751 | 756 | ||
| 757 | + /* this is used when labels wrap text and the line | ||
| 758 | + * should be in the middle of the first row */ | ||
| 759 | + CGFloat singleRowHeight = [PNLineChart sizeOfString:@"Test" | ||
| 760 | + withWidth:MAXFLOAT | ||
| 761 | + font:[UIFont systemFontOfSize:self.legendFontSize]].height; | ||
| 762 | + | ||
| 763 | + for (PNLineChartData *pdata in self.chartData) { | ||
| 764 | + /* Expected label size*/ | ||
| 752 | CGSize labelsize = [PNLineChart sizeOfString:pdata.dataTitle | 765 | CGSize labelsize = [PNLineChart sizeOfString:pdata.dataTitle |
| 753 | withWidth:maxLabelWidth | 766 | withWidth:maxLabelWidth |
| 754 | font:[UIFont systemFontOfSize:self.legendFontSize]]; | 767 | font:[UIFont systemFontOfSize:self.legendFontSize]]; |
| 755 | 768 | ||
| 756 | - /* draw line */ | 769 | + /* draw lines */ |
| 770 | + | ||
| 771 | + | ||
| 772 | + /* If there is inflection decorator, the line is composed of two lines | ||
| 773 | + * and this is the space that separates two lines in order to put inflection | ||
| 774 | + * decorator */ | ||
| 775 | + | ||
| 757 | CGFloat inflexionWidthSpacer = pdata.inflexionPointStyle == PNLineChartPointStyleTriangle ? pdata.inflexionPointWidth / 2 : pdata.inflexionPointWidth; | 776 | CGFloat inflexionWidthSpacer = pdata.inflexionPointStyle == PNLineChartPointStyleTriangle ? pdata.inflexionPointWidth / 2 : pdata.inflexionPointWidth; |
| 758 | - CGFloat t1 = (legendLineWidth * 0.8 - inflexionWidthSpacer)/2; | 777 | + |
| 759 | - UIView *line = [[UIView alloc] initWithFrame:CGRectMake(x + legendLineWidth * 0.1, y + (labelsize.height - pdata.lineWidth) / 2, t1, pdata.lineWidth)]; | 778 | + CGFloat halfLineLength; |
| 779 | + | ||
| 780 | + if (pdata.inflexionPointStyle != PNLineChartPointStyleNone) { | ||
| 781 | + halfLineLength = (legendLineWidth * 0.8 - inflexionWidthSpacer)/2; | ||
| 782 | + }else{ | ||
| 783 | + halfLineLength = legendLineWidth * 0.8; | ||
| 784 | + } | ||
| 785 | + | ||
| 786 | + UIView *line = [[UIView alloc] initWithFrame:CGRectMake(x + legendLineWidth * 0.1, y + (singleRowHeight - pdata.lineWidth) / 2, halfLineLength, pdata.lineWidth)]; | ||
| 760 | 787 | ||
| 761 | line.backgroundColor = pdata.color; | 788 | line.backgroundColor = pdata.color; |
| 762 | line.alpha = pdata.alpha; | 789 | line.alpha = pdata.alpha; |
| 763 | - [legendLines addObject:line]; | 790 | + [legendViews addObject:line]; |
| 764 | 791 | ||
| 765 | - line = [[UIView alloc] initWithFrame:CGRectMake(x + legendLineWidth * 0.1 + t1 + inflexionWidthSpacer, y + (labelsize.height - pdata.lineWidth) / 2, t1, pdata.lineWidth)]; | 792 | + if (pdata.inflexionPointStyle != PNLineChartPointStyleNone) { |
| 793 | + line = [[UIView alloc] initWithFrame:CGRectMake(x + legendLineWidth * 0.1 + halfLineLength + inflexionWidthSpacer, y + (singleRowHeight - pdata.lineWidth) / 2, halfLineLength, pdata.lineWidth)]; | ||
| 766 | line.backgroundColor = pdata.color; | 794 | line.backgroundColor = pdata.color; |
| 767 | line.alpha = pdata.alpha; | 795 | line.alpha = pdata.alpha; |
| 768 | - | 796 | + [legendViews addObject:line]; |
| 769 | - [legendLines addObject:line]; | 797 | + } |
| 770 | 798 | ||
| 771 | // Add inflexion type | 799 | // Add inflexion type |
| 772 | - [legendInflexion addObject:[self drawInflexion:pdata.inflexionPointWidth | 800 | + [legendViews addObject:[self drawInflexion:pdata.inflexionPointWidth |
| 773 | - center:CGPointMake(x + legendLineWidth / 2, y + labelsize.height / 2) | 801 | + center:CGPointMake(x + legendLineWidth / 2, y + singleRowHeight / 2) |
| 774 | - strokeWidth:2 | 802 | + strokeWidth:pdata.lineWidth |
| 775 | inflexionStyle:pdata.inflexionPointStyle | 803 | inflexionStyle:pdata.inflexionPointStyle |
| 776 | andColor:pdata.color | 804 | andColor:pdata.color |
| 777 | andAlpha:pdata.alpha]]; | 805 | andAlpha:pdata.alpha]]; |
| 778 | 806 | ||
| 779 | UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(x + legendLineWidth, y, maxLabelWidth, labelsize.height)]; | 807 | UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(x + legendLineWidth, y, maxLabelWidth, labelsize.height)]; |
| 780 | label.text = pdata.dataTitle; | 808 | label.text = pdata.dataTitle; |
| 809 | + label.font = [UIFont systemFontOfSize:self.legendFontSize]; | ||
| 810 | + label.lineBreakMode = NSLineBreakByWordWrapping; | ||
| 811 | + label.numberOfLines = 0; | ||
| 781 | x += self.legendStyle == PNLegendItemStyleStacked ? 0 : labelsize.width + legendLineWidth; | 812 | x += self.legendStyle == PNLegendItemStyleStacked ? 0 : labelsize.width + legendLineWidth; |
| 782 | y += self.legendStyle == PNLegendItemStyleStacked ? labelsize.height : 0; | 813 | y += self.legendStyle == PNLegendItemStyleStacked ? labelsize.height : 0; |
| 783 | 814 | ||
| 784 | totalWidth = self.legendStyle == PNLegendItemStyleStacked ? fmaxf(totalWidth, labelsize.width + legendLineWidth) : totalWidth + labelsize.width + legendLineWidth; | 815 | totalWidth = self.legendStyle == PNLegendItemStyleStacked ? fmaxf(totalWidth, labelsize.width + legendLineWidth) : totalWidth + labelsize.width + legendLineWidth; |
| 785 | totalHeight = self.legendStyle == PNLegendItemStyleStacked ? fmaxf(totalHeight, labelsize.height) : totalHeight + labelsize.height; | 816 | totalHeight = self.legendStyle == PNLegendItemStyleStacked ? fmaxf(totalHeight, labelsize.height) : totalHeight + labelsize.height; |
| 786 | - [legendLabels addObject:label]; | 817 | + [legendViews addObject:label]; |
| 787 | - | ||
| 788 | - } | ||
| 789 | 818 | ||
| 790 | - UIView *legend = [[UIView alloc] initWithFrame:CGRectMake(100, 400, totalWidth, totalHeight)]; | ||
| 791 | - for (UILabel *l in legendLabels) { | ||
| 792 | - [legend addSubview:l]; | ||
| 793 | - } | ||
| 794 | - for (UIView* v in legendLines) { | ||
| 795 | - [legend addSubview:v]; | ||
| 796 | } | 819 | } |
| 797 | 820 | ||
| 798 | - for (UIImageView *iv in legendInflexion) { | 821 | + UIView *legend = [[UIView alloc] initWithFrame:CGRectMake(0, 0, totalWidth, totalHeight)]; |
| 799 | 822 | ||
| 800 | - [legend addSubview:iv]; | 823 | + for (UIView* v in legendViews) { |
| 824 | + [legend addSubview:v]; | ||
| 801 | } | 825 | } |
| 802 | - | ||
| 803 | return legend; | 826 | return legend; |
| 804 | } | 827 | } |
| 805 | 828 | ||
| 806 | -//// PaintCode Trial Version | ||
| 807 | -//// www.paintcodeapp.com | ||
| 808 | 829 | ||
| 809 | - (UIImageView*)drawInflexion:(CGFloat)size center:(CGPoint)center strokeWidth: (CGFloat)sw inflexionStyle:(PNLineChartPointStyle)type andColor:(UIColor*)color andAlpha:(CGFloat) alfa | 830 | - (UIImageView*)drawInflexion:(CGFloat)size center:(CGPoint)center strokeWidth: (CGFloat)sw inflexionStyle:(PNLineChartPointStyle)type andColor:(UIColor*)color andAlpha:(CGFloat) alfa |
| 810 | { | 831 | { |
| 811 | - //this is an arbitrary size for example | 832 | + //Make the size a little bigger so it includes also border stroke |
| 812 | CGSize aSize = CGSizeMake(size + sw, size + sw); | 833 | CGSize aSize = CGSizeMake(size + sw, size + sw); |
| 813 | 834 | ||
| 814 | - //this can take any CGSize | ||
| 815 | - //it works like the frame.size would in the drawRect: method | ||
| 816 | - //in the way that it represents the context's size | ||
| 817 | - UIGraphicsBeginImageContextWithOptions(aSize, NO, 0.0); | ||
| 818 | 835 | ||
| 819 | - //this gets the graphic context | 836 | + UIGraphicsBeginImageContextWithOptions(aSize, NO, 0.0); |
| 820 | CGContextRef context = UIGraphicsGetCurrentContext(); | 837 | CGContextRef context = UIGraphicsGetCurrentContext(); |
| 821 | 838 | ||
| 839 | + | ||
| 822 | if (type == PNLineChartPointStyleCircle) { | 840 | if (type == PNLineChartPointStyleCircle) { |
| 823 | - //// Oval Drawing | ||
| 824 | CGContextAddArc(context, (size + sw)/2, (size + sw) / 2, size/2, 0, M_PI*2, YES); | 841 | CGContextAddArc(context, (size + sw)/2, (size + sw) / 2, size/2, 0, M_PI*2, YES); |
| 825 | }else if (type == PNLineChartPointStyleSquare){ | 842 | }else if (type == PNLineChartPointStyleSquare){ |
| 826 | CGContextAddRect(context, CGRectMake(sw/2, sw/2, size, size)); | 843 | CGContextAddRect(context, CGRectMake(sw/2, sw/2, size, size)); |
| @@ -832,12 +849,12 @@ | @@ -832,12 +849,12 @@ | ||
| 832 | CGContextClosePath(context); | 849 | CGContextClosePath(context); |
| 833 | } | 850 | } |
| 834 | 851 | ||
| 835 | - //Set the width of the pen mark | 852 | + //Set some stroke properties |
| 836 | CGContextSetLineWidth(context, sw); | 853 | CGContextSetLineWidth(context, sw); |
| 837 | - | ||
| 838 | CGContextSetAlpha(context, alfa); | 854 | CGContextSetAlpha(context, alfa); |
| 839 | - | ||
| 840 | CGContextSetStrokeColorWithColor(context, color.CGColor); | 855 | CGContextSetStrokeColorWithColor(context, color.CGColor); |
| 856 | + | ||
| 857 | + //Finally draw | ||
| 841 | CGContextDrawPath(context, kCGPathStroke); | 858 | CGContextDrawPath(context, kCGPathStroke); |
| 842 | 859 | ||
| 843 | //now get the image from the context | 860 | //now get the image from the context |
| @@ -845,14 +862,13 @@ | @@ -845,14 +862,13 @@ | ||
| 845 | 862 | ||
| 846 | UIGraphicsEndImageContext(); | 863 | UIGraphicsEndImageContext(); |
| 847 | 864 | ||
| 848 | - //// Variable Declarations | 865 | + //// Translate origin |
| 849 | CGFloat originX = center.x - (size + sw) / 2.0; | 866 | CGFloat originX = center.x - (size + sw) / 2.0; |
| 850 | CGFloat originY = center.y - (size + sw) / 2.0; | 867 | CGFloat originY = center.y - (size + sw) / 2.0; |
| 851 | 868 | ||
| 852 | UIImageView *squareImageView = [[UIImageView alloc]initWithImage:squareImage]; | 869 | UIImageView *squareImageView = [[UIImageView alloc]initWithImage:squareImage]; |
| 853 | [squareImageView setFrame:CGRectMake(originX, originY, size + sw, size + sw)]; | 870 | [squareImageView setFrame:CGRectMake(originX, originY, size + sw, size + sw)]; |
| 854 | return squareImageView; | 871 | return squareImageView; |
| 855 | - | ||
| 856 | } | 872 | } |
| 857 | 873 | ||
| 858 | @end | 874 | @end |
| @@ -47,11 +47,11 @@ | @@ -47,11 +47,11 @@ | ||
| 47 | // Line Chart #2 | 47 | // Line Chart #2 |
| 48 | NSArray * data02Array = @[@20.1, @180.1, @26.4, @202.2, @126.2, @167.2, @276.2]; | 48 | NSArray * data02Array = @[@20.1, @180.1, @26.4, @202.2, @126.2, @167.2, @276.2]; |
| 49 | PNLineChartData *data02 = [PNLineChartData new]; | 49 | PNLineChartData *data02 = [PNLineChartData new]; |
| 50 | - data02.dataTitle = @"Beta"; | 50 | + data02.dataTitle = @"Beta Beta Beta Beta"; |
| 51 | data02.color = PNTwitterColor; | 51 | data02.color = PNTwitterColor; |
| 52 | data02.alpha = 0.5f; | 52 | data02.alpha = 0.5f; |
| 53 | data02.itemCount = data02Array.count; | 53 | data02.itemCount = data02Array.count; |
| 54 | - data02.inflexionPointStyle = PNLineChartPointStyleCircle; | 54 | + data02.inflexionPointStyle = PNLineChartPointStyleNone; |
| 55 | data02.getData = ^(NSUInteger index) { | 55 | data02.getData = ^(NSUInteger index) { |
| 56 | CGFloat yValue = [data02Array[index] floatValue]; | 56 | CGFloat yValue = [data02Array[index] floatValue]; |
| 57 | return [PNLineChartDataItem dataItemWithY:yValue]; | 57 | return [PNLineChartDataItem dataItemWithY:yValue]; |
| @@ -63,9 +63,12 @@ | @@ -63,9 +63,12 @@ | ||
| 63 | 63 | ||
| 64 | 64 | ||
| 65 | [self.view addSubview:self.lineChart]; | 65 | [self.view addSubview:self.lineChart]; |
| 66 | - self.lineChart.legendStyle = PNLegendItemStyleSerial; | 66 | + self.lineChart.legendStyle = PNLegendItemStyleStacked; |
| 67 | - self.lineChart.legendFontSize = 17.0; | 67 | + self.lineChart.legendFontSize = 12.0; |
| 68 | - [self.view addSubview:[self.lineChart getLegendWithMaxWidth:200]]; | 68 | + |
| 69 | + UIView *legend = [self.lineChart getLegendWithMaxWidth:200]; | ||
| 70 | + [legend setFrame:CGRectMake(100, 400, legend.frame.size.width, legend.frame.size.width)]; | ||
| 71 | + [self.view addSubview:legend]; | ||
| 69 | } | 72 | } |
| 70 | else if ([self.title isEqualToString:@"Bar Chart"]) | 73 | else if ([self.title isEqualToString:@"Bar Chart"]) |
| 71 | { | 74 | { |
-
Please register or login to post a comment