2
votes

I'm using Core-Plot 0.9 and have a seemingly peculiar problem. I have an X-Y plot with labels on the y-axis. When the plot is initially displayed, the labels are correctly positioned on the tick marks (actually offset 1.0) to the left of the axis itself, which is correct.

Then, I select a new set of data to display using a UIPickerView to set the x-axis starting point and regenerate the plot. On this and all subsequent regenerations of the plot, the y-axis labels show up inside the plot (to the right of the axis) and not on the tick marks (actually shifted upwards a bit.

I have created what I think is enough room on the left hand side of the plot to contain the y-axis labels. In particular, I have code as follows:

graph.paddingLeft = 0.0;
graph.plotAreaFrame.paddingLeft = 25.0;

y.labelOffset = 1.0f;
y.labelAlignment = CPTAlignmentLeft;

Here is the correct representation of the y-axis labels on initial loading.


(source: msyapps.com)

Here is the incorrect representation of the y-axis labels after scrolling the picker view on the left and regenerating the plot.


(source: msyapps.com)

2
Perhaps I am not asking the questions in an intelligible way. I wish I could show images of the situation, because a picture or two may be better than my English. - Michael Young
Siddharthan, Thanks. That discussion and the included images are similar to what I am experiencing. The difference it seems is that my labels end up in the incorrect position except when I very carefully move the scroll wheel up and down just a little bit but not enough to move to a different row. In this odd way, I can get the labels to show in the proper location but this is just a kluge. I can't understand the remedy suggested and from the discussion, it seems that it doesn't work either and requires modifying the core-plot code, something that I don't think I should attempt. - Michael Young
I've been playing with graph.paddingLeft and graph.plotAreaFrame.paddingLeft. All that happens is that the rightward shift is or seems to be exactly the amount of graph.plotAreaFrame.paddingLeft. The greater the padding, the greater the rightward shift. - Michael Young

2 Answers

1
votes

Are you changing the tickDirection property? That's what controls which side the labels are on.

1
votes

I have a workable solution, but it violates the commonly recommended action for displaying the y-axis. The annotations in the code snippet below indicates where I think I deviated from conventions and where I think I have added a unique solution for fixing the y-axis in place on subsequent redrawing of plot.

#pragma mark - Choose returns to chart
- (IBAction)returnsToChart:(int)startPt andInteger:(int)endPt; { 
    contentArray1 = [[NSMutableArray alloc] initWithObjects:nil];
    dataContent = [[NSMutableArray alloc] initWithObjects:nil];
    int xPosition = 0;
    for (int i=startPt; i<endPt+1; ++i) {
        [dataContent addObject:[returnsAll objectAtIndex:i]];
        id x = [NSNumber numberWithFloat:xPosition];
        id y = [NSNumber numberWithFloat:[[returnsAll objectAtIndex:i] floatValue]];
        if ([[returnsAll objectAtIndex:i] isEqualToString:@""]) {
            [contentArray1 addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:x, @"x", @"", @"y", nil]];
        }
        else {
            [contentArray1 addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:x, @"x", y, @"y", nil]]; }
        xPosition = xPosition + 1;
    }

    dataForPlot = contentArray1;

    quarterlyReturnView.frame = CGRectMake(0.0f, 8.0f, 320.0f, 240.0f);    

    graph = [[CPTXYGraph alloc] initWithFrame:CGRectZero];    
    quarterlyReturnView.hostedGraph = graph;

    //paddingLeft leaves room for y-axis labels
    //paddingBottom must be set at zero otherwise and the space that must be added in order for the bottom-most label text to show will be handled by extending the length of the y-axis downward by a little bit
    graph.paddingLeft = 8.0;
    graph.paddingTop = 5.0;
    graph.paddingRight = 5.0;
    graph.paddingBottom = 0.0;

    //convention says that paddingLeft should be some number greater than zero
    //convention says that paddingBottom should be some number greater than zero, but if greater than zero, then each subsequent redrawing of plot results in a label shift upwards by the non-zero amount
    graph.plotAreaFrame.paddingLeft = 0.0;
    graph.plotAreaFrame.paddingTop = 5.0;
    graph.plotAreaFrame.paddingRight = 5.0;
    graph.plotAreaFrame.paddingBottom = 0.0;

    // Setup plot space
    CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *)graph.defaultPlotSpace;

    //this is where the magic happens...
    //I tweaked the percentage adjustments for the location as a function of the number of data points along the x-axis that had to be plotted
    //I settled on 8% plus and minus to provide room for the y-axis labels
    //this percentage is expressed as -0.08*(datacontent.count-1.0) and 1.08*(datacontent.count-1.0)
    //in other words, I put 8% on the left-hand side of the x-axis and made the whole x-axis 108% of the number of data points

    plotSpace.xRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat(-0.08 * (dataContent.count-1.0)) length:CPTDecimalFromFloat(1.08 * (dataContent.count-1.0))];

    //Text styles
    CPTMutableTextStyle *axisTitleTextStyle = [CPTTextStyle textStyle];
    axisTitleTextStyle.fontName = @"Helvetica";
    axisTitleTextStyle.fontSize = 9.0;

    //Grid styles
    CPTMutableLineStyle *majorGridLineStyle = [CPTLineStyle lineStyle];
    majorGridLineStyle.lineWidth = 0.5f;

    //Axis styles
    CPTMutableLineStyle *axisLineStyle = [CPTLineStyle lineStyle];
    axisLineStyle.lineColor = [CPTColor blueColor];
    axisLineStyle.lineWidth = 1.0f;

    float maxNum = -100.0;
    float minNum = 100.0;
    float testMaxNum = 0.0;
    float testMinNum = 0.0;
    for (int i=0; i<[dataContent count]; ++i) {
        if ([[dataContent objectAtIndex:i] isEqualToString:@""]) { }
        else {
            testMaxNum = [[dataContent objectAtIndex:i] floatValue];
            if (maxNum < testMaxNum) { maxNum = testMaxNum; }
            testMinNum = [[dataContent objectAtIndex:i] floatValue];
            if (minNum > testMinNum) { minNum = testMinNum; } }
    }
    int maxInt = (maxNum + 1.0) / 1.0;
    float yMax = 1.0 * maxInt;
    int minInt = (minNum - 1.0) / 1.0;
    float yMin = 1.0 * minInt;

    //here is where the y-axis is stretched a bit to allow the labels to show unclipped
    plotSpace.yRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat(yMin-0.2) length:CPTDecimalFromFloat(yMax-yMin+0.2)];

    // Axes (x is horizontal; y is vertical)
    CPTXYAxisSet *axisSet = (CPTXYAxisSet *)graph.axisSet;
    CPTXYAxis *x = axisSet.xAxis;
    x.axisLineStyle = axisLineStyle;
    x.labelOffset = 1.0f;
    x.labelTextStyle = nil;
    x.majorTickLength = 5.0f;
    x.majorIntervalLength = CPTDecimalFromString(@"16");
    x.orthogonalCoordinateDecimal = CPTDecimalFromString(@"0");
    x.minorTicksPerInterval = 0;
    x.minorTickLength = 0.0f;
    x.tickDirection =CPTSignNone;
    x.visibleRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat(0.0) length:CPTDecimalFromFloat(dataContent.count-1.0)];

    CPTXYAxis *y = axisSet.yAxis;
    y.axisLineStyle = axisLineStyle;
    NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
    [formatter setMaximumFractionDigits:0];
    y.labelFormatter = formatter;
    y.labelOffset = 2.0f;
    y.labelAlignment = CPTAlignmentLeft;
    y.labelTextStyle = axisTitleTextStyle;
    y.tickDirection = CPTSignNegative;    
    y.majorTickLength = 3.0f;    
    y.majorIntervalLength = CPTDecimalFromString(@"2");
    y.majorGridLineStyle = majorGridLineStyle;
    //y.gridLinesRange is needed because the x-axis has been stretched 8% as described above
    y.gridLinesRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromInt(0) length:CPTDecimalFromInt(dataContent.count-1)];
    y.minorTicksPerInterval = 1;
    y.minorTickLength = 2.0f;
    y.orthogonalCoordinateDecimal = CPTDecimalFromString(@"0");

    // Create plot area
    CPTScatterPlot *boundLinePlot = [[CPTScatterPlot alloc] init];
    CPTMutableLineStyle *lineStyle = [CPTMutableLineStyle lineStyle];
    lineStyle.miterLimit = 1.0f;
    lineStyle.lineWidth = 2.0f;
    lineStyle.lineColor = [CPTColor blueColor];
    boundLinePlot.dataLineStyle = lineStyle;
    boundLinePlot.dataSource = self;
    [graph addPlot:boundLinePlot];
    [boundLinePlot reloadData];
}