Styling problems...HELP!


#1

I’m totally confused about theming charts and how to apply themes. The user guide and API docs seem to have conflicting information. I tried creating a theme subclass and then calling the applyTheme method but I get warnings about being beprecated.

My understanding was that you can subclass SChartTheme, in my case I’m subclassing SChartDarkTheme and override the init method and set the various properties of the style objects. See my example below:

- (id)init
{
    self = [super init];
    if (self) {
        
        // chart
        self.chartStyle.backgroundColor = [UIColor redColor];
        self.chartStyle.backgroundColorGradient = [UIColor redColor];
        self.chartStyle.plotAreaBackgroundColor = [UIColor redColor];
        self.chartStyle.borderWidth = nil;
        self.chartStyle.plotAreaBorderWidth = nil;
        
        // grid lines
        self.xAxisStyle.majorGridLineStyle.showMajorGridLines = NO;
        self.yAxisStyle.majorGridLineStyle.showMajorGridLines = NO;
        
        // series
        self.lineWidth = @1;
    }
    return self;
}

and then add this theme to the chart with the following:

[[ShinobiChart alloc] initWithFrame:self.frame withTheme:theme withPrimaryXAxisType:SChartAxisTypeDateTime withPrimaryYAxisType:SChartAxisTypeNumber]

Yet I’m finding the some styles seemed to get ignored. The self.lineWidth property does not change the lineWidth of all the series as espected. I tried placing applyTheme: at various places but it seems to have no effect.

In another theme I’ve set the self.crosshairStyle.lineWidth and self.crosshairStyle.lineColor properties which also seem to go ignored.

I really don’t understand how the themes work whether they are just objects that are referenced to set defaults when Shinobi creates various elements or whether they are applied to existing elements. 

I’m hoping that it’s just me and my understanding of how themes work, it’s just not clear as some artcles say one thing and the API docs say another yet everything I try seems to result in some of my style properties being ignored.

I’m not overriding the styles anywhere, for instance the lineWidth of the series is not set in my datasource as I wantted chart to pick the width from the theme. I’m avoiding placing any theme relacted code in my datasource as I want to keep a clear speration.

Please help.


#2

Hi,

Thank you for raising these issues with us. Apologies for the difficulties you’re experiencing, it sounds like most of the issues are due to our documentation not being clear enough.

With regard to series styles, the recommended way to configure the series style in a custom theme would be to override the XXSeriesStyleForSeriesAtIndex:selected method in your custom theme (for example, for line series, this would be lineSeriesStyleForSeriesAtIndex). When you call applyTheme: on a chart, it acts as a rubber stamp, and overwrites any theming properties which were set on the chart. For the series styles, it takes any series which are contained within the chart, and sets their styles from the theme. I’m wondering if the issue you were seeing with series styles is because applyTheme was being called on the chart before it had loaded its data. This would mean that the chart wouldn’t contain any series, and so nothing would be configured. A good point to call the applyTheme method in this case would be immediately after the chart has loaded its data. You can hook into this functionality by adopting the SChartDelegate protocol, and then implementing the sChartDidFinishLoadingData: method. Your delegate method would look something like this:

- (void)sChartDidFinishLoadingData:(ShinobiChart *)chart {
    [self.chart applyTheme:[CustomTheme new]];
}

The issue you’re seeing with the crosshair style looks like a bug in the framework - I’ve raised an issue in our Jira backlog to address that. The bug is that the applyTheme method isn’t updating the crosshair style. It looks like the only point where the theme currently updates the chart crosshair style is when the chart is created. A workaround I would recommend for now, until we have fixed this bug, is to create your chart with the initWithFrame:withTheme: method. Like so:

self.chart = [[ShinobiChart alloc] initWithFrame:chartFrame withTheme:[CustomTheme new]];

Because we are applying the theme when we create the chart, any properties which the theme adjusts for the crosshair are respected.

I took the custom theme which you posted, and updated it so that it would have the effects you’re looking for. The implementation I ended up with was as follows:

@implementation CustomTheme

- (id)init
{
    self = [super init];
    if (self) {
        
        // chart
        self.chartStyle.backgroundColor = [UIColor redColor];
        self.chartStyle.backgroundColorGradient = [UIColor redColor];
        self.chartStyle.plotAreaBackgroundColor = [UIColor redColor];
        self.chartStyle.borderWidth = nil;
        self.chartStyle.plotAreaBorderWidth = nil;
        
        // grid lines
        self.xAxisStyle.majorGridLineStyle.showMajorGridLines = NO;
        self.yAxisStyle.majorGridLineStyle.showMajorGridLines = NO;
        
        // crosshair
        self.crosshairStyle.lineColor = [UIColor whiteColor];
        self.crosshairStyle.lineWidth = @20;
    }
    return self;
}

- (SChartLineSeriesStyle *)lineSeriesStyleForSeriesAtIndex:(NSInteger)seriesIndex selected:(BOOL)selected {
    SChartLineSeriesStyle *style = [super lineSeriesStyleForSeriesAtIndex:seriesIndex selected:selected];
    style.lineWidth = @10;
    return style;
}

@end

Once again, apologies that the chart theme has proven difficult to work with. We are planning a major review of our API later on in the year, and theming will definitely come under that. If you have any further questions regarding customizing chart theming, please feel free to get in touch with us again.

Regards,

Dan


#3

This is really helpful. I’ll give this a go. 

I guess the confusing thing is that you can pass a theme object as part of the chart’s construtor so it gives the illusion that all the chart elements (including series’) would get their defaults from the theme object passed in. But if it’s actually more like rubber stamp then this can’t work as like you said the various chart elements don’t necessarily exist when initialising the chart object.


#4

This worked great. I think the documentation could be greatly improved regarding themes and the process in which they are applied. Also it’s not clear that you need to call the super implementation when overriding the theme series methods to get an inital object to override. My first attempt was to create a new style object and return that.

Regarding the crosshair, how should I go about styling the crosshair, what is the workaround for the bug?

Thanks.


#5

Hi camsoft,

Thank you for the feedback on our documentation, that will feed into our API review.

Yeah, with regard to the series style methods, the themes configure a set of styles for each series when they are created, so the easiest thing is definitely to get the style object from the superclass, then tweak that.

With regards the crosshair, if it’s not possible to create a chart with a theme object, then the best idea would be to modify style properties on the crosshair directly, rather than going through the theme. So for example, modifying the code which I added above for applying a theme once data loading is finished, you could do the following:

- (void)sChartDidFinishLoadingData:(ShinobiChart *)chart {
    [self.chart applyTheme:[CustomTheme new]];
    
    // Apply your real properties here
    self.chart.crosshair.style.lineColor = [UIColor whiteColor];
    self.chart.crosshair.style.lineWidth = @10;
}

I hope that helps,

Dan