Skip to content
This repository was archived by the owner on Dec 2, 2020. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
language: objective-c
xcode_project: Sample Project/SimpleLineChart.xcodeproj
xcode_scheme: SimpleLineChartTests
xcode_sdk: iphonesimulator
# xcode_project: Sample Project/SimpleLineChart.xcodeproj
# xcode_scheme: SimpleLineChartTests
# xcode_sdk: iphonesimulator
script:
- xcodebuild clean build test -project "Sample Project/SimpleLineChart.xcodeproj" -scheme SimpleLineChartTests -sdk iphonesimulator ONLY_ACTIVE_ARCH=NO
15 changes: 15 additions & 0 deletions Classes/BEMSimpleLineGraphView.h
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,11 @@
@todo Could enhance further by specifying the position of Y-Axis, i.e. Left or Right of the view. Also auto detection on label overlapping. */
@property (nonatomic) BOOL enableYAxisLabel;


/** Show X-Axis label on the side. Default value is NO.
*/
@property (nonatomic) BOOL enableXAxisLabel;
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good.
Although, should be set to YES in the sample project.
The comment should state that the label will be at the bottom of the graph and not on the side.


/** When set to YES, the points on the Y-axis will be set to all fit in the graph view. When set to NO, the points on the Y-axis will be set with their absolute value (which means that certain points might not be visible because they are outside of the view). Default value is YES. */
@property (nonatomic) BOOL autoScaleYAxis;

Expand Down Expand Up @@ -345,6 +350,16 @@
@return The minimum value of the Y-Axis. */
- (CGFloat)minValueForLineGraph:(BEMSimpleLineGraphView *)graph;

/** Optional method to control whether a label indicating NO DATA will be shown while number of data is zero
@param graph The graph object for the NO DATA label
@return The boolean value indicating the availability of the NO DATA label. */
- (BOOL)noDataLabelEnableForLineGraph:(BEMSimpleLineGraphView *)graph;

/** Optional method to set the static padding distance between the graph line and the whole graph
@param graph The graph object requesting the padding value.
@return The padding value of the graph. */
- (CGFloat)staticPaddingForLineGraph:(BEMSimpleLineGraphView *)graph;


//----- TOUCH EVENTS -----//

Expand Down
120 changes: 75 additions & 45 deletions Classes/BEMSimpleLineGraphView.m
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ - (void)commonInit {
_enableTouchReport = NO;
_enablePopUpReport = NO;
_enableBezierCurve = NO;
_enableXAxisLabel = NO;
_enableYAxisLabel = NO;
_YAxisLabelXOffset = 0;
_autoScaleYAxis = YES;
Expand Down Expand Up @@ -202,6 +203,10 @@ - (void)layoutNumberOfPoints {

// There are no points to load
if (numberOfPoints == 0) {
if (self.delegate &&
[self.delegate respondsToSelector:@selector(noDataLabelEnableForLineGraph:)] &&
![self.delegate noDataLabelEnableForLineGraph:self]) return;

NSLog(@"[BEMSimpleLineGraph] Data source contains no data. A no data label will be displayed and drawing will stop. Add data to the data source and then reload the graph.");

self.noDataLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, self.viewForBaselineLayout.frame.size.width, self.viewForBaselineLayout.frame.size.height)];
Expand Down Expand Up @@ -254,11 +259,21 @@ - (void)layoutTouchReport {
[self.panView addGestureRecognizer:self.panGesture];

if (self.enablePopUpReport == YES && self.alwaysDisplayPopUpLabels == NO) {
NSDictionary *labelAttributes = @{NSFontAttributeName: self.labelFont};
NSString *maxValueString = [NSString stringWithFormat:@"%li",
(long)[self calculateMaximumPointValue].integerValue];
NSString *minValueString = [NSString stringWithFormat:@"%li",
(long)[self calculateMinimumPointValue].integerValue];
NSString *longestString = nil;
if ([minValueString sizeWithAttributes:labelAttributes].width >
[maxValueString sizeWithAttributes:labelAttributes].width)
longestString = minValueString;
else longestString = maxValueString;

self.popUpLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 100, 20)];
if ([self.delegate respondsToSelector:@selector(popUpSuffixForlineGraph:)])
self.popUpLabel.text = [NSString stringWithFormat:@"%@%@", [NSNumber numberWithInteger:[self calculateMaximumPointValue].integerValue], [self.delegate popUpSuffixForlineGraph:self]];
else
self.popUpLabel.text = [NSString stringWithFormat:@"%@", [NSNumber numberWithInteger:[self calculateMaximumPointValue].integerValue]];
self.popUpLabel.text = [NSString stringWithFormat:@"%@%@", longestString, [self.delegate popUpSuffixForlineGraph:self]];
else self.popUpLabel.text = longestString;
self.popUpLabel.textAlignment = 1;
self.popUpLabel.numberOfLines = 1;
self.popUpLabel.font = self.labelFont;
Expand All @@ -284,11 +299,18 @@ - (void)drawEntireGraph {

// Set the Y-Axis Offset if the Y-Axis is enabled. The offset is relative to the size of the longest label on the Y-Axis.
if (self.enableYAxisLabel) {
UILabel *longestLabel = [[UILabel alloc] init];
if (self.autoScaleYAxis == YES)longestLabel.text = [NSString stringWithFormat:@"%i", (int)[self maxValue]];
else longestLabel.text = [NSString stringWithFormat:@"%i", (int)self.frame.size.height];
NSDictionary *attributes = @{NSFontAttributeName: self.labelFont};
self.YAxisLabelXOffset = [longestLabel.text sizeWithAttributes:attributes].width + 5;
if (self.autoScaleYAxis == YES){
NSString *maxValueString = [NSString stringWithFormat:@"%i", (int)[self maxValue]];
NSString *minValueString = [NSString stringWithFormat:@"%i", (int)[self minValue]];

self.YAxisLabelXOffset = MAX([maxValueString sizeWithAttributes:attributes].width,
[minValueString sizeWithAttributes:attributes].width) + 5;
}
else{
NSString *longestString = [NSString stringWithFormat:@"%i", (int)self.frame.size.height];
self.YAxisLabelXOffset = [longestString sizeWithAttributes:attributes].width + 5;
}
} else self.YAxisLabelXOffset = 0;

// Draw the X-Axis
Expand Down Expand Up @@ -346,40 +368,42 @@ - (void)drawDots {
positionOnXAxis = (((self.frame.size.width - self.YAxisLabelXOffset) / (numberOfPoints - 1)) * i) + self.YAxisLabelXOffset;
positionOnYAxis = [self yPositionForDotValue:dotValue];

BEMCircle *circleDot = [[BEMCircle alloc] initWithFrame:CGRectMake(0, 0, self.sizePoint, self.sizePoint)];
circleDot.center = CGPointMake(positionOnXAxis, positionOnYAxis);
circleDot.tag = i+100;
circleDot.alpha = 0;
circleDot.absoluteValue = dotValue;
circleDot.Pointcolor = self.colorPoint;

[yAxisValues addObject:[NSNumber numberWithFloat:positionOnYAxis]];

[self addSubview:circleDot];

if (self.alwaysDisplayPopUpLabels == YES) {
if ([self.delegate respondsToSelector:@selector(lineGraph:alwaysDisplayPopUpAtIndex:)]) {
if ([self.delegate lineGraph:self alwaysDisplayPopUpAtIndex:i] == YES) {
[self displayPermanentLabelForPoint:circleDot];
}
} else [self displayPermanentLabelForPoint:circleDot];
}

// Dot entrance animation
if (self.animationGraphEntranceTime == 0) {
if (self.alwaysDisplayDots == NO) {
circleDot.alpha = 0;
} else circleDot.alpha = 0.7;
} else {
[UIView animateWithDuration:(float)self.animationGraphEntranceTime/numberOfPoints delay:(float)i*((float)self.animationGraphEntranceTime/numberOfPoints) options:UIViewAnimationOptionCurveLinear animations:^{
circleDot.alpha = 0.7;
} completion:^(BOOL finished) {

if (self.animationGraphEntranceTime != 0 || self.alwaysDisplayDots == YES) {
BEMCircle *circleDot = [[BEMCircle alloc] initWithFrame:CGRectMake(0, 0, self.sizePoint, self.sizePoint)];
circleDot.center = CGPointMake(positionOnXAxis, positionOnYAxis);
circleDot.tag = i+100;
circleDot.alpha = 0;
circleDot.absoluteValue = dotValue;
circleDot.Pointcolor = self.colorPoint;

[self addSubview:circleDot];

if (self.alwaysDisplayPopUpLabels == YES) {
if ([self.delegate respondsToSelector:@selector(lineGraph:alwaysDisplayPopUpAtIndex:)]) {
if ([self.delegate lineGraph:self alwaysDisplayPopUpAtIndex:i] == YES) {
[self displayPermanentLabelForPoint:circleDot];
}
} else [self displayPermanentLabelForPoint:circleDot];
}

// Dot entrance animation
if (self.animationGraphEntranceTime == 0) {
if (self.alwaysDisplayDots == NO) {
[UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
circleDot.alpha = 0;
} completion:nil];
}
}];
circleDot.alpha = 0; // never reach here
} else circleDot.alpha = 0.7;
} else {
[UIView animateWithDuration:(float)self.animationGraphEntranceTime/numberOfPoints delay:(float)i*((float)self.animationGraphEntranceTime/numberOfPoints) options:UIViewAnimationOptionCurveLinear animations:^{
circleDot.alpha = 0.7;
} completion:^(BOOL finished) {
if (self.alwaysDisplayDots == NO) {
[UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
circleDot.alpha = 0;
} completion:nil];
}
}];
}
}
}
}
Expand Down Expand Up @@ -433,6 +457,7 @@ - (void)drawLine {
}

- (void)drawXAxis {
if(!self.enableXAxisLabel) return;
if (![self.dataSource respondsToSelector:@selector(lineGraph:labelOnXAxisForIndex:)] && ![self.dataSource respondsToSelector:@selector(labelOnXAxisForIndex:)]) return;

for (UIView *subview in [self subviews]) {
Expand Down Expand Up @@ -1001,7 +1026,7 @@ - (CGFloat)maxValue {
return [self.delegate maxValueForLineGraph:self];
} else {
CGFloat dotValue;
CGFloat maxValue = 0;
CGFloat maxValue = -FLT_MAX;

@autoreleasepool {
for (int i = 0; i < numberOfPoints; i++) {
Expand Down Expand Up @@ -1077,11 +1102,16 @@ - (CGFloat)yPositionForDotValue:(CGFloat)dotValue {
if (padding > 90.0) {
padding = 90.0;
}

if ([self.dataSource respondsToSelector:@selector(lineGraph:labelOnXAxisForIndex:)] || [self.dataSource respondsToSelector:@selector(labelOnXAxisForIndex:)]) {
if ([xAxisLabels count] > 0) {
UILabel *label = [xAxisLabels objectAtIndex:0];
self.XAxisLabelYOffset = label.frame.size.height + self.widthLine;

if([self.delegate respondsToSelector:@selector(staticPaddingForLineGraph:)])
padding = [self.delegate staticPaddingForLineGraph:self];

if (self.enableXAxisLabel) {
if ([self.dataSource respondsToSelector:@selector(lineGraph:labelOnXAxisForIndex:)] || [self.dataSource respondsToSelector:@selector(labelOnXAxisForIndex:)]) {
if ([xAxisLabels count] > 0) {
UILabel *label = [xAxisLabels objectAtIndex:0];
self.XAxisLabelYOffset = label.frame.size.height + self.widthLine;
}
}
}

Expand Down