Hi,
I'm using core-plot (and the barcharts) to display financial information.
My problem is that whenever I use negative values, it seems that the scale of the shown graph is wrong. I'd like the entire graph to be visible, but often only a part of the graph is shown, leaving the bars cut off and sometimes not even the x-axis visible (the part shown is so far down on the y-axis). If I turn on the user-interaction, it's possible to scroll within the view to see different parts of the graph, but I want an overview, not study the graph in detail. Note that I do not use the whole screen for the graph, but only roughly 300x240px.
For some reason new users are not allowed to post images so I can not attach screenshots. If someone thinks it can help with the answer (and has the time) I'd be happy to send you two screenshots of how it looks with only positive values and how it looks with negative values.
I'd really appreciate any help I can get. Thank you.
The code I use to produce the graph is as follows:
- (id)initWithFrame:(CGRect)frame:(FinancialTopicData *) topicDataToSet:(NSArray *) colors {
//Assert correct data
assert([topicDataToSet isKindOfClass:[FinancialTopicData class]]);
if ((self = [super initWithFrame:frame])) {
self.topicData = topicDataToSet;
//Create the graph
graph = [[CPXYGraph alloc] initWithFrame:CGRectZero];
CPTheme *theme = [CPTheme themeNamed:kCPPlainWhiteTheme];
[graph applyTheme:theme];
self.hostedLayer = graph;
// Border
graph.plotAreaFrame.borderLineStyle = nil;
graph.plotAreaFrame.cornerRadius = 0.0f;
// Paddings
graph.paddingLeft = 0.0f;
graph.paddingRight = 0.0f;
graph.paddingTop = 0.0f;
graph.paddingBottom = 0.0f;
graph.titlePlotAreaFrameAnchor = CPRectAnchorTop;
//Plot padding
graph.plotAreaFrame.paddingLeft = 70.0;
graph.plotAreaFrame.paddingTop = 10;
graph.plotAreaFrame.paddingRight = 20.0;
graph.plotAreaFrame.paddingBottom = 45.0;
NSDecimalNumber *intervalDivider = [NSDecimalNumber decimalNumberWithString:@kIntervalDivider];
// Add plot space for horizontal bar charts
NSDecimalNumber *numberDecimalValueMaxUp = [[topicData maxValueRoundedUp] decimalNumberByAdding:[[[topicData maxValueRoundedUp] decimalNumberBySubtracting:[topicData minValueRoundedDown]] decimalNumberByDividingBy:intervalDivider]];
NSDecimal decimalValueMaxUp = [numberDecimalValueMaxUp decimalValue];
NSDecimal decimalValueMinDown = [[topicData minValueRoundedDown] decimalValue];
NSInteger numberOfTypes = [[topicData years] count];
NSDecimal numberOfBars = [[NSNumber numberWithInteger:numberOfTypes] decimalValue];
NSDecimalNumber *yInterval = [[numberDecimalValueMaxUp decimalNumberBySubtracting:[topicData minValueRoundedDown]] decimalNumberByDividingBy:intervalDivider];
CPXYPlotSpace *plotSpace = (CPXYPlotSpace *)graph.defaultPlotSpace;
plotSpace.yRange = [CPPlotRange plotRangeWithLocation:decimalValueMinDown length:decimalValueMaxUp];
plotSpace.xRange = [CPPlotRange plotRangeWithLocation:CPDecimalFromFloat(0.0f) length:numberOfBars];
//Add x-axis
CPXYAxisSet *axisSet = (CPXYAxisSet *)graph.axisSet;
CPXYAxis *x = axisSet.xAxis;
x.majorTickLineStyle = nil;
x.minorTickLineStyle = nil;
x.majorIntervalLength = CPDecimalFromString(@"1");
x.orthogonalCoordinateDecimal = CPDecimalFromString(@"0");
// Define some custom labels for the data elements
x.labelRotation = M_PI/4;
x.labelingPolicy = CPAxisLabelingPolicyNone;
NSMutableArray *customTickLocations = [NSMutableArray new];
NSArray *xAxisLabels = [topicData years];
for(int i = 0; i < [xAxisLabels count];i++){
[customTickLocations addObject:[NSDecimalNumber numberWithFloat:0.5f+i*1.0f]];
}
NSUInteger labelLocation = 0;
NSMutableArray *customLabels = [NSMutableArray arrayWithCapacity:[xAxisLabels count]];
for (NSNumber *tickLocation in customTickLocations) {
CPAxisLabel *newLabel = [[CPAxisLabel alloc] initWithText: [xAxisLabels objectAtIndex:labelLocation++] textStyle:x.labelTextStyle];
newLabel.tickLocation = [tickLocation decimalValue];
newLabel.offset = x.labelOffset + x.majorTickLength*(numberOfTypes/2);
newLabel.rotation = M_PI/4;
[customLabels addObject:newLabel];
[newLabel release];
}
x.axisLabels = [NSSet setWithArray:customLabels];
[customTickLocations release];
CPXYAxis *y = axisSet.yAxis;
y.minorTickLineStyle = nil;
y.majorIntervalLength = [yInterval decimalValue];
y.orthogonalCoordinateDecimal = CPDecimalFromString(@"0");
int i = 0;
for(NSString *key in [topicData types]){
CPBarPlot *barPlot = [CPBarPlot tubularBarPlotWithColor:[colors objectAtIndex:(i%[colors count])] horizontalBars:NO];
i++;
barPlot.baseValue = CPDecimalFromString(@"0");
barPlot.dataSource = topicData;
barPlot.barOffset = 1.0f+i;
barPlot.identifier = key;
barPlot.delegate = topicData;
barPlot.needsDisplayOnBoundsChange = YES;
[graph addPlot:barPlot toPlotSpace:plotSpace];
}
}
return self;
}
The datasource methods:
-(NSNumber *)numberForPlot:(CPPlot *)plot
field:(NSUInteger)fieldEnum
recordIndex:(NSUInteger)index {
NSNumber *num = nil;
if ( [plot isKindOfClass:[CPBarPlot class]] ) {
switch ( fieldEnum ) {
case CPBarPlotFieldBarLocation:{
num = [NSDecimalNumber numberWithUnsignedInteger:index];
break;
}
case CPBarPlotFieldBarLength:{
NSString *stringValue = [[[types objectForKey:plot.identifier] objectForKey:[years objectAtIndex:index]] objectForKey:KEY_COMPANY_FINANCIALS_VALUE];
num = [formatter numberFromString:stringValue];
break;
}
}
}
return num;
}
-(NSUInteger)numberOfRecordsForPlot:(CPPlot *)plot{
return [years count];
}