andi

improved legend for line chart, added thousands separator option for y labels

@@ -48,6 +48,7 @@ @@ -48,6 +48,7 @@
48 @property (nonatomic) CGFloat chartMargin; 48 @property (nonatomic) CGFloat chartMargin;
49 @property (nonatomic) BOOL showLabel; 49 @property (nonatomic) BOOL showLabel;
50 @property (nonatomic) BOOL showGenYLabels; 50 @property (nonatomic) BOOL showGenYLabels;
  51 +@property (nonatomic) BOOL thousandsSeparator;
51 52
52 53
53 /** 54 /**
@@ -56,7 +56,6 @@ @@ -56,7 +56,6 @@
56 { 56 {
57 CGFloat yStep = (_yValueMax - _yValueMin) / _yLabelNum; 57 CGFloat yStep = (_yValueMax - _yValueMin) / _yLabelNum;
58 CGFloat yStepHeight = _chartCavanHeight / _yLabelNum; 58 CGFloat yStepHeight = _chartCavanHeight / _yLabelNum;
59 - NSString *yLabelFormat = self.yLabelFormat ? : @"%1.f";  
60 59
61 if (_yChartLabels) { 60 if (_yChartLabels) {
62 for (PNChartLabel * label in _yChartLabels) { 61 for (PNChartLabel * label in _yChartLabels) {
@@ -68,19 +67,19 @@ @@ -68,19 +67,19 @@
68 67
69 if (yStep == 0.0) { 68 if (yStep == 0.0) {
70 PNChartLabel *minLabel = [[PNChartLabel alloc] initWithFrame:CGRectMake(0.0, (NSInteger)_chartCavanHeight, (NSInteger)_chartMargin, (NSInteger)_yLabelHeight)]; 69 PNChartLabel *minLabel = [[PNChartLabel alloc] initWithFrame:CGRectMake(0.0, (NSInteger)_chartCavanHeight, (NSInteger)_chartMargin, (NSInteger)_yLabelHeight)];
71 - minLabel.text = [NSString stringWithFormat:yLabelFormat, 0.0]; 70 + minLabel.text = [self formatYLabel:0.0];
72 [self setCustomStyleForYLabel:minLabel]; 71 [self setCustomStyleForYLabel:minLabel];
73 [self addSubview:minLabel]; 72 [self addSubview:minLabel];
74 [_yChartLabels addObject:minLabel]; 73 [_yChartLabels addObject:minLabel];
75 74
76 PNChartLabel *midLabel = [[PNChartLabel alloc] initWithFrame:CGRectMake(0.0, (NSInteger)(_chartCavanHeight / 2), (NSInteger)_chartMargin, (NSInteger)_yLabelHeight)]; 75 PNChartLabel *midLabel = [[PNChartLabel alloc] initWithFrame:CGRectMake(0.0, (NSInteger)(_chartCavanHeight / 2), (NSInteger)_chartMargin, (NSInteger)_yLabelHeight)];
77 - midLabel.text = [NSString stringWithFormat:yLabelFormat, _yValueMax]; 76 + midLabel.text = [self formatYLabel:_yValueMax];
78 [self setCustomStyleForYLabel:midLabel]; 77 [self setCustomStyleForYLabel:midLabel];
79 [self addSubview:midLabel]; 78 [self addSubview:midLabel];
80 [_yChartLabels addObject:midLabel]; 79 [_yChartLabels addObject:midLabel];
81 80
82 PNChartLabel *maxLabel = [[PNChartLabel alloc] initWithFrame:CGRectMake(0.0, 0.0, (NSInteger)_chartMargin, (NSInteger)_yLabelHeight)]; 81 PNChartLabel *maxLabel = [[PNChartLabel alloc] initWithFrame:CGRectMake(0.0, 0.0, (NSInteger)_chartMargin, (NSInteger)_yLabelHeight)];
83 - maxLabel.text = [NSString stringWithFormat:yLabelFormat, _yValueMax * 2]; 82 + maxLabel.text = [self formatYLabel:_yValueMax * 2];
84 [self setCustomStyleForYLabel:maxLabel]; 83 [self setCustomStyleForYLabel:maxLabel];
85 [self addSubview:maxLabel]; 84 [self addSubview:maxLabel];
86 [_yChartLabels addObject:maxLabel]; 85 [_yChartLabels addObject:maxLabel];
@@ -93,7 +92,7 @@ @@ -93,7 +92,7 @@
93 { 92 {
94 PNChartLabel *label = [[PNChartLabel alloc] initWithFrame:CGRectMake(0.0, (NSInteger)(_chartCavanHeight - index * yStepHeight), (NSInteger)_chartMargin, (NSInteger)_yLabelHeight)]; 93 PNChartLabel *label = [[PNChartLabel alloc] initWithFrame:CGRectMake(0.0, (NSInteger)(_chartCavanHeight - index * yStepHeight), (NSInteger)_chartMargin, (NSInteger)_yLabelHeight)];
95 [label setTextAlignment:NSTextAlignmentRight]; 94 [label setTextAlignment:NSTextAlignmentRight];
96 - label.text = [NSString stringWithFormat:yLabelFormat, _yValueMin + (yStep * index)]; 95 + label.text = [self formatYLabel:_yValueMin + (yStep * index)];
97 [self setCustomStyleForYLabel:label]; 96 [self setCustomStyleForYLabel:label];
98 [self addSubview:label]; 97 [self addSubview:label];
99 [_yChartLabels addObject:label]; 98 [_yChartLabels addObject:label];
@@ -589,8 +588,8 @@ @@ -589,8 +588,8 @@
589 yMin = 0.0f; 588 yMin = 0.0f;
590 } 589 }
591 590
592 - _yValueMin = _yFixedValueMin ? _yFixedValueMin : yMin ; 591 + _yValueMin = (_yFixedValueMin > -FLT_MAX) ? _yFixedValueMin : yMin ;
593 - _yValueMax = _yFixedValueMax ? _yFixedValueMax : yMax + yMax / 10.0; 592 + _yValueMax = (_yFixedValueMax > -FLT_MAX) ? _yFixedValueMax : yMax + yMax / 10.0;
594 593
595 if (_showGenYLabels) { 594 if (_showGenYLabels) {
596 [self setYLabels]; 595 [self setYLabels];
@@ -732,6 +731,8 @@ @@ -732,6 +731,8 @@
732 _endPointsOfPath = [[NSMutableArray alloc] init]; 731 _endPointsOfPath = [[NSMutableArray alloc] init];
733 self.userInteractionEnabled = YES; 732 self.userInteractionEnabled = YES;
734 733
  734 + _yFixedValueMin = -FLT_MAX;
  735 + _yFixedValueMax = -FLT_MAX;
735 _yLabelNum = 5.0; 736 _yLabelNum = 5.0;
736 _yLabelHeight = [[[[PNChartLabel alloc] init] font] pointSize]; 737 _yLabelHeight = [[[[PNChartLabel alloc] init] font] pointSize];
737 738
@@ -791,6 +792,19 @@ @@ -791,6 +792,19 @@
791 } 792 }
792 793
793 794
  795 +- (NSString*) formatYLabel:(double)value{
  796 + if (!self.thousandsSeparator) {
  797 + NSString *format = self.yLabelFormat ? : @"%1.f";
  798 + return [NSString stringWithFormat:format,value];
  799 + }
  800 +
  801 + NSNumberFormatter* numberFormatter = [[NSNumberFormatter alloc] init];
  802 + [numberFormatter setFormatterBehavior: NSNumberFormatterBehavior10_4];
  803 + [numberFormatter setNumberStyle: NSNumberFormatterDecimalStyle];
  804 + return [numberFormatter stringFromNumber: [NSNumber numberWithDouble:value]];
  805 +}
  806 +
  807 +
794 - (UIView*) getLegendWithMaxWidth:(CGFloat)mWidth{ 808 - (UIView*) getLegendWithMaxWidth:(CGFloat)mWidth{
795 if ([self.chartData count] < 1) { 809 if ([self.chartData count] < 1) {
796 return nil; 810 return nil;
@@ -805,13 +819,17 @@ @@ -805,13 +819,17 @@
805 819
806 /* accumulated height */ 820 /* accumulated height */
807 CGFloat totalHeight = 0; 821 CGFloat totalHeight = 0;
  822 + CGFloat totalWidth = 0;
808 823
809 NSMutableArray *legendViews = [[NSMutableArray alloc] init]; 824 NSMutableArray *legendViews = [[NSMutableArray alloc] init];
810 -  
811 - NSUInteger numLabelsPerRow = ceil((float)[self.chartData count] / self.labelRowsInSerialMode);  
812 825
813 /* Determine the max width of each legend item */ 826 /* Determine the max width of each legend item */
814 - CGFloat maxLabelWidth = self.legendStyle == PNLegendItemStyleStacked ? (mWidth - legendLineWidth) : (mWidth / numLabelsPerRow - legendLineWidth); 827 + CGFloat maxLabelWidth;
  828 + if (self.legendStyle == PNLegendItemStyleStacked) {
  829 + maxLabelWidth = mWidth - legendLineWidth;
  830 + }else{
  831 + maxLabelWidth = MAXFLOAT;
  832 + }
815 833
816 /* this is used when labels wrap text and the line 834 /* this is used when labels wrap text and the line
817 * should be in the middle of the first row */ 835 * should be in the middle of the first row */
@@ -820,6 +838,7 @@ @@ -820,6 +838,7 @@
820 font:self.legendFont ? self.legendFont : [UIFont systemFontOfSize:12.0f]].height; 838 font:self.legendFont ? self.legendFont : [UIFont systemFontOfSize:12.0f]].height;
821 839
822 NSUInteger counter = 0; 840 NSUInteger counter = 0;
  841 + NSUInteger rowWidth = 0;
823 NSUInteger rowMaxHeight = 0; 842 NSUInteger rowMaxHeight = 0;
824 843
825 for (PNLineChartData *pdata in self.chartData) { 844 for (PNLineChartData *pdata in self.chartData) {
@@ -829,12 +848,14 @@ @@ -829,12 +848,14 @@
829 font:self.legendFont ? self.legendFont : [UIFont systemFontOfSize:12.0f]]; 848 font:self.legendFont ? self.legendFont : [UIFont systemFontOfSize:12.0f]];
830 849
831 /* draw lines */ 850 /* draw lines */
832 - 851 + if ((rowWidth + labelsize.width + legendLineWidth > mWidth)&&(self.legendStyle == PNLegendItemStyleSerial)) {
833 - if (counter != 0 && counter % numLabelsPerRow == 0) { 852 + rowWidth = 0;
834 x = 0; 853 x = 0;
835 y += rowMaxHeight; 854 y += rowMaxHeight;
836 rowMaxHeight = 0; 855 rowMaxHeight = 0;
837 } 856 }
  857 + rowWidth += labelsize.width + legendLineWidth;
  858 + totalWidth = self.legendStyle == PNLegendItemStyleSerial ? fmaxf(rowWidth, totalWidth) : fmaxf(totalWidth, labelsize.width + legendLineWidth);
838 859
839 /* If there is inflection decorator, the line is composed of two lines 860 /* If there is inflection decorator, the line is composed of two lines
840 * and this is the space that separates two lines in order to put inflection 861 * and this is the space that separates two lines in order to put inflection
@@ -871,19 +892,20 @@ @@ -871,19 +892,20 @@
871 andColor:pdata.color 892 andColor:pdata.color
872 andAlpha:pdata.alpha]]; 893 andAlpha:pdata.alpha]];
873 894
874 - UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(x + legendLineWidth, y, maxLabelWidth, labelsize.height)]; 895 + UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(x + legendLineWidth, y, labelsize.width, labelsize.height)];
875 label.text = pdata.dataTitle; 896 label.text = pdata.dataTitle;
876 label.textColor = self.legendFontColor ? self.legendFontColor : [UIColor blackColor]; 897 label.textColor = self.legendFontColor ? self.legendFontColor : [UIColor blackColor];
877 label.font = self.legendFont ? self.legendFont : [UIFont systemFontOfSize:12.0f]; 898 label.font = self.legendFont ? self.legendFont : [UIFont systemFontOfSize:12.0f];
878 label.lineBreakMode = NSLineBreakByWordWrapping; 899 label.lineBreakMode = NSLineBreakByWordWrapping;
879 label.numberOfLines = 0; 900 label.numberOfLines = 0;
880 - 901 +
881 rowMaxHeight = fmaxf(rowMaxHeight, labelsize.height); 902 rowMaxHeight = fmaxf(rowMaxHeight, labelsize.height);
882 x += self.legendStyle == PNLegendItemStyleStacked ? 0 : labelsize.width + legendLineWidth; 903 x += self.legendStyle == PNLegendItemStyleStacked ? 0 : labelsize.width + legendLineWidth;
883 y += self.legendStyle == PNLegendItemStyleStacked ? labelsize.height : 0; 904 y += self.legendStyle == PNLegendItemStyleStacked ? labelsize.height : 0;
884 905
885 - 906 +
886 - totalHeight = self.legendStyle == PNLegendItemStyleStacked ? fmaxf(totalHeight, rowMaxHeight + y) : totalHeight + labelsize.height; 907 + totalHeight = self.legendStyle == PNLegendItemStyleSerial ? fmaxf(totalHeight, rowMaxHeight + y) : totalHeight + labelsize.height;
  908 +
887 [legendViews addObject:label]; 909 [legendViews addObject:label];
888 counter++; 910 counter++;
889 } 911 }