EmmKay
EmmKay

Reputation: 23

How to use custom label and label for individual bars at the same time on the bar chart with coreplot?

I am trying to create a bar graph similar to the one below - where the x axis has 2 different labels - one the labels on the bars themselves, indicating performance, and the other at the bottom of the axis, indicating the year. Only the numbers need to be shown rotated, on the graph rather than at the top.

bar graph

I am showing the years by creating custom labels. I am also able to show the performance figures for the bars by implementing the -dataLabelForPlot:recordIndex: method. The performance figures shows up but horizontally, but I want to be able to rotate the performance figures by 90 degrees. Setting the labelRotation on the plot does not help because I have set the labelingPolicy to CPTAxisLabelingPolicyNone so I can add custom labels.

Below is my code:

-(CPTLayer *)dataLabelForPlot:(CPTPlot *)plot recordIndex:(NSUInteger)index 
{
    CPTMutableTextStyle *axisTitleTextStyle = [CPTMutableTextStyle textStyle];
    axisTitleTextStyle.fontSize = 10.0;
    axisTitleTextStyle.color = [CPTColor blackColor];

    CPTTextLayer *label = [[CPTTextLayer alloc] init];
    label.textStyle = axisTitleTextStyle;
    if ( [plot isKindOfClass:[CPTBarPlot class]] ) {
        if ( [plot.identifier isEqual:@"Fund"] ) {
            label.text =  [[[self dataGroup1] objectAtIndex:index] stringValue];
        }
        else if ( [plot.identifier isEqual:@"Benchmark"] ) {
            label.text =  [[[self dataGroup2] objectAtIndex:index] stringValue];
        }

    }
    return [label autorelease];
}


- (void) drawGraph 
{
    graphHostingView_ = [[CPTGraphHostingView alloc] initWithFrame:self.bounds];

    calPerfGraph_ = [[CPTXYGraph alloc] initWithFrame:self.bounds];
    graphHostingView_.hostedGraph = calPerfGraph_;

    [self addSubview:graphHostingView_];

    calPerfGraph_.plotAreaFrame.masksToBorder = NO;

    calPerfGraph_.paddingLeft = 5.0;
    calPerfGraph_.paddingTop = 20.0;
    calPerfGraph_.paddingRight = 10.0;
    calPerfGraph_.paddingBottom =20.0;

    calPerfGraph_.plotAreaFrame.paddingTop = 10.0;
    calPerfGraph_.plotAreaFrame.paddingBottom = 50.0;
    calPerfGraph_.plotAreaFrame.paddingLeft = 10.0;
    calPerfGraph_.plotAreaFrame.paddingRight = 35.0;

    // Y axis scale - round to nearest ten
    int maxYScale = (([[self getPositiveMax] intValue] / 10 ) + 1) * 10;
    int minYScale = (([[self getNegativeMax] intValue] / 10 ) + 1) * 10;

    // Styles
    CPTMutableLineStyle *lineStyle = [CPTMutableLineStyle lineStyle];
    lineStyle.lineColor = [CPTColor grayColor];
    lineStyle.lineWidth = 2.0f;

    CPTMutableLineStyle *gridLineStyle = [CPTMutableLineStyle lineStyle];
    gridLineStyle.lineColor = [CPTColor grayColor];
    gridLineStyle.lineWidth = 1.0f;

    // X axis
    CPTXYAxisSet *axisSet = (CPTXYAxisSet *)calPerfGraph_.axisSet;
    axisSet.xAxis.minorTicksPerInterval = 0;
    axisSet.xAxis.majorTickLineStyle = lineStyle;
    axisSet.xAxis.axisLineStyle = lineStyle;
    axisSet.xAxis.majorTickLength = 0;
    axisSet.xAxis.labelingPolicy = CPTAxisLabelingPolicyNone;
    axisSet.xAxis.axisConstraints = [CPTConstraints constraintWithLowerOffset:0]; // Bring labels to the bottom on the plot
    axisSet.xAxis.labelRotation = M_PI/2;

    int currentYear = [self getCurrentYear];
    NSMutableArray *customLabels = [NSMutableArray arrayWithCapacity:6];
    for (int i=currentYear-5,count=1; currentYear>=i; i++,count++) {
        CPTAxisLabel *newLabel = [[CPTAxisLabel alloc] initWithText:[NSString stringWithFormat:@"%d",i] textStyle:axisSet.xAxis.labelTextStyle];
        newLabel.tickLocation = CPTDecimalFromInt(count);
        newLabel.offset = axisSet.xAxis.labelOffset + axisSet.xAxis.majorTickLength;
        [customLabels addObject:newLabel];
        [newLabel release];
    }
    axisSet.xAxis.axisLabels =  [NSSet setWithArray:customLabels];

    // Y axis
    if ( maxYScale >= 40 || minYScale >= 40) {
        axisSet.yAxis.majorIntervalLength = [[NSDecimalNumber decimalNumberWithString:@"20"] decimalValue];
    }
    else {
        axisSet.yAxis.majorIntervalLength = [[NSDecimalNumber decimalNumberWithString:@"10"] decimalValue];
    }

    axisSet.yAxis.minorTicksPerInterval = 0;
    axisSet.yAxis.majorTickLength = 0;
    axisSet.yAxis.majorGridLineStyle = gridLineStyle;
    axisSet.yAxis.axisLineStyle = nil;
    axisSet.yAxis.axisConstraints = [CPTConstraints constraintWithUpperOffset:0]; // Bring labels to the right end of the plot
    axisSet.yAxis.tickDirection = CPTSignPositive;

    CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *)calPerfGraph_.defaultPlotSpace;
    plotSpace.xRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromDouble(0.0) length:CPTDecimalFromDouble([[self calPerfFundData] count]+1)];
    plotSpace.yRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromDouble(-minYScale) length:CPTDecimalFromDouble(minYScale + maxYScale)];

    CPTBarPlot *barPlot = [CPTBarPlot tubularBarPlotWithColor:[CPTColor greenColor] horizontalBars:NO];    
    barPlot.baseValue = CPTDecimalFromString(@"0");
    barPlot.dataSource = self;
    barPlot.barOffset = CPTDecimalFromFloat(.7);
    barPlot.identifier = @"Fund";
    barPlot.barWidth = CPTDecimalFromFloat(.25);
    [barPlot addAnimation:[self animateVerticalBars] forKey:@"FundAnimation"];
    [calPerfGraph_ addPlot:barPlot toPlotSpace:plotSpace];

    CPTBarPlot *bbarPlot = [CPTBarPlot tubularBarPlotWithColor:[CPTColor colorWithComponentRed:0.9 green:0.9 blue:0.9 alpha:0.8] horizontalBars:NO];    
    bbarPlot.baseValue = CPTDecimalFromString(@"0");
    bbarPlot.dataSource = self;
    bbarPlot.barOffset = CPTDecimalFromFloat(1);
    bbarPlot.barWidth = CPTDecimalFromFloat(.25);
    bbarPlot.identifier = @"Benchmark";
    [bbarPlot addAnimation:[self animateVerticalBars] forKey:@"BenchmarkAnimation"];
    [calPerfGraph_ addPlot:bbarPlot toPlotSpace:plotSpace];
}

How can I rotate the performance figures on the bars? Any help is appreciated. Thanks.

Upvotes: 2

Views: 2389

Answers (1)

Eric Skroch
Eric Skroch

Reputation: 27381

Both plots and axes have their own independent labelRotation properties. You will be responsible for setting the rotation of your custom axis labels, but the labelRotation property of the bar plot should set the rotation for the data labels above the bars.

Upvotes: 3

Related Questions