|
|
|
@@ -19,7 +19,6 @@ typedef NS_ENUM(NSUInteger, JBLineChartHorizontalIndexClamp){
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Numerics (JBLineChartLineView)
|
|
|
|
|
CGFloat static const kJBLineChartLinesViewEdgePadding = 10.0;
|
|
|
|
|
CGFloat static const kJBLineChartLinesViewStrokeWidth = 5.0;
|
|
|
|
|
CGFloat static const kJBLineChartLinesViewMiterLimit = -5.0;
|
|
|
|
|
CGFloat static const kJBLineChartLinesViewDefaultLinePhase = 1.0f;
|
|
|
|
@@ -88,6 +87,7 @@ static UIColor *kJBLineChartViewDefaultLineSelectionColor = nil;
|
|
|
|
|
- (UIColor *)lineChartLinesView:(JBLineChartLinesView *)lineChartLinesView colorForLineAtLineIndex:(NSUInteger)lineIndex;
|
|
|
|
|
- (UIColor *)lineChartLinesView:(JBLineChartLinesView *)lineChartLinesView selectedColorForLineAtLineIndex:(NSUInteger)lineIndex;
|
|
|
|
|
- (CGFloat)lineChartLinesView:(JBLineChartLinesView *)lineChartLinesView widthForLineAtLineIndex:(NSUInteger)lineIndex;
|
|
|
|
|
- (CGFloat)paddingForLineChartLinesView:(JBLineChartLinesView *)lineChartLinesView;
|
|
|
|
|
- (JBLineChartViewLineStyle)lineChartLinesView:(JBLineChartLinesView *)lineChartLinesView lineStyleForLineAtLineIndex:(NSUInteger)lineIndex;
|
|
|
|
|
- (BOOL)lineChartLinesView:(JBLineChartLinesView *)lineChartLinesView smoothLineAtLineIndex:(NSUInteger)lineIndex;
|
|
|
|
|
|
|
|
|
@@ -115,6 +115,7 @@ static UIColor *kJBLineChartViewDefaultLineSelectionColor = nil;
|
|
|
|
|
- (UIColor *)lineChartDotsView:(JBLineChartDotsView *)lineChartDotsView colorForLineAtLineIndex:(NSUInteger)lineIndex;
|
|
|
|
|
- (UIColor *)lineChartDotsView:(JBLineChartDotsView *)lineChartDotsView selectedColorForLineAtLineIndex:(NSUInteger)lineIndex;
|
|
|
|
|
- (CGFloat)lineChartDotsView:(JBLineChartDotsView *)lineChartDotsView widthForLineAtLineIndex:(NSUInteger)lineIndex;
|
|
|
|
|
- (CGFloat)paddingForLineChartDotsView:(JBLineChartDotsView *)lineChartDotsView;
|
|
|
|
|
- (BOOL)lineChartDotsView:(JBLineChartDotsView *)lineChartDotsView showsDotsForLineAtLineIndex:(NSUInteger)lineIndex;
|
|
|
|
|
|
|
|
|
|
@end
|
|
|
|
@@ -143,6 +144,7 @@ static UIColor *kJBLineChartViewDefaultLineSelectionColor = nil;
|
|
|
|
|
- (CGFloat)availableHeight;
|
|
|
|
|
- (CGFloat)minHeight;
|
|
|
|
|
- (CGFloat)maxHeight;
|
|
|
|
|
- (CGFloat)padding;
|
|
|
|
|
- (NSUInteger)dataCount;
|
|
|
|
|
|
|
|
|
|
// Touch helpers
|
|
|
|
@@ -214,9 +216,12 @@ static UIColor *kJBLineChartViewDefaultLineSelectionColor = nil;
|
|
|
|
|
|
|
|
|
|
- (void)reloadData
|
|
|
|
|
{
|
|
|
|
|
// reset cached max height
|
|
|
|
|
// Reset cached max height
|
|
|
|
|
self.cachedMinHeight = kJBBarChartViewUndefinedCachedHeight;
|
|
|
|
|
self.cachedMaxHeight = kJBBarChartViewUndefinedCachedHeight;
|
|
|
|
|
|
|
|
|
|
// Padding
|
|
|
|
|
CGFloat chartPadding = [self padding];
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Subview rectangle calculations
|
|
|
|
@@ -229,8 +234,8 @@ static UIColor *kJBLineChartViewDefaultLineSelectionColor = nil;
|
|
|
|
|
*/
|
|
|
|
|
dispatch_block_t createChartData = ^{
|
|
|
|
|
|
|
|
|
|
CGFloat pointSpace = (self.bounds.size.width - (kJBLineChartLinesViewEdgePadding * 2)) / ([self dataCount] - 1); // Space in between points
|
|
|
|
|
CGFloat xOffset = kJBLineChartLinesViewEdgePadding;
|
|
|
|
|
CGFloat pointSpace = (self.bounds.size.width - (chartPadding * 2)) / ([self dataCount] - 1); // Space in between points
|
|
|
|
|
CGFloat xOffset = chartPadding;
|
|
|
|
|
CGFloat yOffset = 0;
|
|
|
|
|
|
|
|
|
|
NSMutableArray *mutableChartData = [NSMutableArray array];
|
|
|
|
@@ -256,7 +261,7 @@ static UIColor *kJBLineChartViewDefaultLineSelectionColor = nil;
|
|
|
|
|
xOffset += pointSpace;
|
|
|
|
|
}
|
|
|
|
|
[mutableChartData addObject:chartPointData];
|
|
|
|
|
xOffset = kJBLineChartLinesViewEdgePadding;
|
|
|
|
|
xOffset = chartPadding;
|
|
|
|
|
}
|
|
|
|
|
self.chartData = [NSArray arrayWithArray:mutableChartData];
|
|
|
|
|
};
|
|
|
|
@@ -356,6 +361,9 @@ static UIColor *kJBLineChartViewDefaultLineSelectionColor = nil;
|
|
|
|
|
// 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 callback:nil force:YES];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#pragma mark - View Quick Accessors
|
|
|
|
@@ -396,6 +404,25 @@ static UIColor *kJBLineChartViewDefaultLineSelectionColor = nil;
|
|
|
|
|
return self.cachedMaxHeight;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (CGFloat)padding
|
|
|
|
|
{
|
|
|
|
|
if ([self.dataSource respondsToSelector:@selector(lineChartView:widthForLineAtLineIndex:)])
|
|
|
|
|
{
|
|
|
|
|
NSAssert([self.dataSource respondsToSelector:@selector(numberOfLinesInLineChartView:)], @"JBLineChartView // dataSource must implement - (NSUInteger)numberOfLinesInLineChartView:(JBLineChartView *)lineChartView");
|
|
|
|
|
CGFloat maxWidth = 0.0f;
|
|
|
|
|
for (int lineIndex=0; lineIndex<[self.dataSource numberOfLinesInLineChartView:self]; lineIndex++)
|
|
|
|
|
{
|
|
|
|
|
CGFloat lineWidth = [self.dataSource lineChartView:self widthForLineAtLineIndex:lineIndex];
|
|
|
|
|
if (lineWidth > maxWidth)
|
|
|
|
|
{
|
|
|
|
|
maxWidth = lineWidth;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return ceil(maxWidth * 0.5);
|
|
|
|
|
}
|
|
|
|
|
return ceil(kJBLineChartLinesViewStrokeWidth * 0.5);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (NSUInteger)dataCount
|
|
|
|
|
{
|
|
|
|
|
NSUInteger dataCount = 0;
|
|
|
|
@@ -446,6 +473,11 @@ static UIColor *kJBLineChartViewDefaultLineSelectionColor = nil;
|
|
|
|
|
return kJBLineChartLinesViewStrokeWidth;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (CGFloat)paddingForLineChartLinesView:(JBLineChartLinesView *)lineChartLinesView
|
|
|
|
|
{
|
|
|
|
|
return [self padding];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (BOOL)lineChartLinesView:(JBLineChartLinesView *)lineChartLinesView smoothLineAtLineIndex:(NSUInteger)lineIndex
|
|
|
|
|
{
|
|
|
|
|
if ([self.dataSource respondsToSelector:@selector(lineChartView:smoothLineAtLineIndex:)])
|
|
|
|
@@ -498,6 +530,11 @@ static UIColor *kJBLineChartViewDefaultLineSelectionColor = nil;
|
|
|
|
|
return kJBLineChartLinesViewStrokeWidth;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (CGFloat)paddingForLineChartDotsView:(JBLineChartDotsView *)lineChartDotsView
|
|
|
|
|
{
|
|
|
|
|
return [self padding];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (BOOL)lineChartDotsView:(JBLineChartDotsView *)lineChartDotsView showsDotsForLineAtLineIndex:(NSUInteger)lineIndex
|
|
|
|
|
{
|
|
|
|
|
if ([self.dataSource respondsToSelector:@selector(lineChartView:showsDotsForLineAtLineIndex:)])
|
|
|
|
@@ -509,9 +546,9 @@ static UIColor *kJBLineChartViewDefaultLineSelectionColor = nil;
|
|
|
|
|
|
|
|
|
|
#pragma mark - Setters
|
|
|
|
|
|
|
|
|
|
- (void)setState:(JBChartViewState)state animated:(BOOL)animated callback:(void (^)())callback
|
|
|
|
|
- (void)setState:(JBChartViewState)state animated:(BOOL)animated callback:(void (^)())callback force:(BOOL)force
|
|
|
|
|
{
|
|
|
|
|
[super setState:state animated:animated callback:callback];
|
|
|
|
|
[super setState:state animated:animated callback:callback force:force];
|
|
|
|
|
|
|
|
|
|
if ([self.chartData count] > 0)
|
|
|
|
|
{
|
|
|
|
@@ -542,7 +579,7 @@ static UIColor *kJBLineChartViewDefaultLineSelectionColor = nil;
|
|
|
|
|
callback();
|
|
|
|
|
}
|
|
|
|
|
}];
|
|
|
|
|
}];
|
|
|
|
|
}];
|
|
|
|
|
[UIView animateWithDuration:kJBLineChartViewStateAnimationDuration delay:(self.state == JBChartViewStateExpanded) ? kJBLineChartViewStateAnimationDelay : 0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
|
|
|
|
|
adjustViewAlphas();
|
|
|
|
|
} completion:nil];
|
|
|
|
@@ -566,6 +603,11 @@ static UIColor *kJBLineChartViewDefaultLineSelectionColor = nil;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void)setState:(JBChartViewState)state animated:(BOOL)animated callback:(void (^)())callback
|
|
|
|
|
{
|
|
|
|
|
[self setState:state animated:animated callback:callback force:NO];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#pragma mark - Getters
|
|
|
|
|
|
|
|
|
|
- (CGFloat)cachedMinHeight
|
|
|
|
@@ -690,6 +732,9 @@ static UIColor *kJBLineChartViewDefaultLineSelectionColor = nil;
|
|
|
|
|
NSInteger leftHorizontalIndex = [self horizontalIndexForPoint:point indexClamp:JBLineChartHorizontalIndexClampLeft];
|
|
|
|
|
NSInteger rightHorizontalIndex = [self horizontalIndexForPoint:point indexClamp:JBLineChartHorizontalIndexClampRight];
|
|
|
|
|
|
|
|
|
|
// Padding
|
|
|
|
|
CGFloat chartPadding = [self padding];
|
|
|
|
|
|
|
|
|
|
NSUInteger shortestDistance = INT_MAX;
|
|
|
|
|
NSInteger selectedIndex = kJBLineChartUnselectedLineIndex;
|
|
|
|
|
NSAssert([self.dataSource respondsToSelector:@selector(numberOfLinesInLineChartView:)], @"JBLineChartView // dataSource must implement - (NSUInteger)numberOfLinesInLineChartView:(JBLineChartView *)lineChartView");
|
|
|
|
@@ -704,11 +749,11 @@ static UIColor *kJBLineChartViewDefaultLineSelectionColor = nil;
|
|
|
|
|
|
|
|
|
|
// Left point
|
|
|
|
|
JBLineChartPoint *leftLineChartPoint = [lineData objectAtIndex:leftHorizontalIndex];
|
|
|
|
|
CGPoint leftPoint = CGPointMake(leftLineChartPoint.position.x, fmin(fmax(kJBLineChartLinesViewEdgePadding, self.linesView.bounds.size.height - leftLineChartPoint.position.y), self.linesView.bounds.size.height - kJBLineChartLinesViewEdgePadding));
|
|
|
|
|
CGPoint leftPoint = CGPointMake(leftLineChartPoint.position.x, fmin(fmax(chartPadding, self.linesView.bounds.size.height - leftLineChartPoint.position.y), self.linesView.bounds.size.height - chartPadding));
|
|
|
|
|
|
|
|
|
|
// Right point
|
|
|
|
|
JBLineChartPoint *rightLineChartPoint = [lineData objectAtIndex:rightHorizontalIndex];
|
|
|
|
|
CGPoint rightPoint = CGPointMake(rightLineChartPoint.position.x, fmin(fmax(kJBLineChartLinesViewEdgePadding, self.linesView.bounds.size.height - rightLineChartPoint.position.y), self.linesView.bounds.size.height - kJBLineChartLinesViewEdgePadding));
|
|
|
|
|
CGPoint rightPoint = CGPointMake(rightLineChartPoint.position.x, fmin(fmax(chartPadding, self.linesView.bounds.size.height - rightLineChartPoint.position.y), self.linesView.bounds.size.height - chartPadding));
|
|
|
|
|
|
|
|
|
|
// Touch point
|
|
|
|
|
CGPoint normalizedTouchPoint = CGPointMake(point.x, self.linesView.bounds.size.height - point.y);
|
|
|
|
@@ -738,7 +783,7 @@ static UIColor *kJBLineChartViewDefaultLineSelectionColor = nil;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UITouch *touch = [touches anyObject];
|
|
|
|
|
CGPoint touchPoint = [self clampPoint:[touch locationInView:self.linesView] toBounds:self.linesView.bounds padding:kJBLineChartLinesViewEdgePadding];
|
|
|
|
|
CGPoint touchPoint = [self clampPoint:[touch locationInView:self.linesView] toBounds:self.linesView.bounds padding:[self padding]];
|
|
|
|
|
|
|
|
|
|
if ([self.delegate respondsToSelector:@selector(lineChartView:didSelectLineAtIndex:horizontalIndex:touchPoint:)])
|
|
|
|
|
{
|
|
|
|
@@ -811,7 +856,7 @@ static UIColor *kJBLineChartViewDefaultLineSelectionColor = nil;
|
|
|
|
|
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
|
|
|
|
|
{
|
|
|
|
|
UITouch *touch = [touches anyObject];
|
|
|
|
|
CGPoint touchPoint = [self clampPoint:[touch locationInView:self.linesView] toBounds:self.linesView.bounds padding:kJBLineChartLinesViewEdgePadding];
|
|
|
|
|
CGPoint touchPoint = [self clampPoint:[touch locationInView:self.linesView] toBounds:self.linesView.bounds padding:[self padding]];
|
|
|
|
|
[self.linesView setSelectedLineIndex:[self lineIndexForPoint:touchPoint] animated:YES];
|
|
|
|
|
[self.dotsView setSelectedLineIndex:[self lineIndexForPoint:touchPoint] animated:YES];
|
|
|
|
|
[self touchesBeganOrMovedWithTouches:touches];
|
|
|
|
@@ -929,6 +974,9 @@ static UIColor *kJBLineChartViewDefaultLineSelectionColor = nil;
|
|
|
|
|
|
|
|
|
|
NSAssert([self.delegate respondsToSelector:@selector(chartDataForLineChartLinesView:)], @"JBLineChartLinesView // delegate must implement - (NSArray *)chartDataForLineChartLinesView:(JBLineChartLinesView *)lineChartLinesView");
|
|
|
|
|
NSArray *chartData = [self.delegate chartDataForLineChartLinesView:self];
|
|
|
|
|
|
|
|
|
|
NSAssert([self.delegate respondsToSelector:@selector(paddingForLineChartLinesView:)], @"JBLineChartLinesView // delegate must implement - (CGFloat)paddingForLineChartLinesView:(JBLineChartLinesView *)lineChartLinesView");
|
|
|
|
|
CGFloat padding = [self.delegate paddingForLineChartLinesView:self];
|
|
|
|
|
|
|
|
|
|
NSUInteger lineIndex = 0;
|
|
|
|
|
for (NSArray *lineData in chartData)
|
|
|
|
@@ -941,11 +989,11 @@ static UIColor *kJBLineChartViewDefaultLineSelectionColor = nil;
|
|
|
|
|
{
|
|
|
|
|
if (index == 0)
|
|
|
|
|
{
|
|
|
|
|
[path moveToPoint:CGPointMake(lineChartPoint.position.x, fmin(self.bounds.size.height - kJBLineChartLinesViewEdgePadding, fmax(kJBLineChartLinesViewEdgePadding, lineChartPoint.position.y)))];
|
|
|
|
|
[path moveToPoint:CGPointMake(lineChartPoint.position.x, fmin(self.bounds.size.height - padding, fmax(padding, lineChartPoint.position.y)))];
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
[path addLineToPoint:CGPointMake(lineChartPoint.position.x, fmin(self.bounds.size.height - kJBLineChartLinesViewEdgePadding, fmax(kJBLineChartLinesViewEdgePadding, lineChartPoint.position.y)))];
|
|
|
|
|
[path addLineToPoint:CGPointMake(lineChartPoint.position.x, fmin(self.bounds.size.height - padding, fmax(padding, lineChartPoint.position.y)))];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
index++;
|
|
|
|
@@ -1098,6 +1146,9 @@ static UIColor *kJBLineChartViewDefaultLineSelectionColor = nil;
|
|
|
|
|
|
|
|
|
|
NSAssert([self.delegate respondsToSelector:@selector(chartDataForLineChartDotsView:)], @"JBLineChartDotsView // delegate must implement - (NSArray *)chartDataForLineChartDotsView:(JBLineChartDotsView *)lineChartDotsView");
|
|
|
|
|
NSArray *chartData = [self.delegate chartDataForLineChartDotsView:self];
|
|
|
|
|
|
|
|
|
|
NSAssert([self.delegate respondsToSelector:@selector(paddingForLineChartDotsView:)], @"JBLineChartDotsView // delegate must implement - (CGFloat)paddingForLineChartDotsView:(JBLineChartDotsView *)lineChartDotsView");
|
|
|
|
|
CGFloat padding = [self.delegate paddingForLineChartDotsView:self];
|
|
|
|
|
|
|
|
|
|
NSUInteger lineIndex = 0;
|
|
|
|
|
NSMutableDictionary *mutableDotViewsDict = [NSMutableDictionary dictionary];
|
|
|
|
@@ -1115,7 +1166,7 @@ static UIColor *kJBLineChartViewDefaultLineSelectionColor = nil;
|
|
|
|
|
CGFloat dotRadius = lineWidth * kJBLineChartDotsViewRadiusFactor;
|
|
|
|
|
|
|
|
|
|
JBLineChartDotView *dotView = [[JBLineChartDotView alloc] initWithRadius:dotRadius];
|
|
|
|
|
dotView.center = CGPointMake(lineChartPoint.position.x, fmin(self.bounds.size.height - kJBLineChartLinesViewEdgePadding, fmax(kJBLineChartLinesViewEdgePadding, lineChartPoint.position.y)));
|
|
|
|
|
dotView.center = CGPointMake(lineChartPoint.position.x, fmin(self.bounds.size.height - padding, fmax(padding, lineChartPoint.position.y)));
|
|
|
|
|
|
|
|
|
|
NSAssert([self.delegate respondsToSelector:@selector(lineChartDotsView:colorForLineAtLineIndex:)], @"JBLineChartDotsView // delegate must implement - (UIColor *)lineChartDotsView:(JBLineChartDotsView *)lineChartDotsView colorForLineAtLineIndex:(NSUInteger)lineIndex");
|
|
|
|
|
dotView.backgroundColor = [self.delegate lineChartDotsView:self colorForLineAtLineIndex:lineIndex];
|
|
|
|
|