Skip to content

Instantly share code, notes, and snippets.

@ricobeck
Created May 26, 2014 07:19
Show Gist options
  • Save ricobeck/e276dcf89ca582f6dd99 to your computer and use it in GitHub Desktop.
Save ricobeck/e276dcf89ca582f6dd99 to your computer and use it in GitHub Desktop.
Draws two plots
//
// NWLocationWeatherViewController.m
// NextWeather
//
// Created by rick on 03/04/14.
// Copyright (c) 2014 KF Interactive. All rights reserved.
//
#import "NWLocationWeatherViewController.h"
#import "NWLocationWeatherViewModel.h"
#import "NWLocation.h"
#import "NWIconController.h"
#import "NWColorController.h"
#import "NWConversionController.h"
#import "NWForecastItem.h"
#import "NWFontController.h"
#import "NGAParallaxMotion.h"
#import <CorePlot/CorePlot-CocoaTouch.h>
@interface NWLocationWeatherViewController () <CPTPlotDataSource>
@property (weak, nonatomic) IBOutlet UILabel *temperatureLabel;
@property (weak, nonatomic) IBOutlet UILabel *weatherIconLabel;
@property (weak, nonatomic) IBOutlet UILabel *locationLabel;
@property (weak, nonatomic) IBOutlet UILabel *weatherDescriptionLabel;
@property (weak, nonatomic) IBOutlet UILabel *dayLightLabel;
@property (nonatomic, strong) NWLocationWeatherViewModel *viewModel;
@property (nonatomic, strong) NSMutableArray *statusCodes;
@property (weak, nonatomic) IBOutlet UIButton *settingsButton;
@property (nonatomic, strong) CPTGraphHostingView *hostView;
@property (nonatomic, strong) CPTScatterPlot *temperaturePlot;
@property (nonatomic) BOOL isInitialized;
@end
@implementation NWLocationWeatherViewController
- (void)viewDidLoad
{
[super viewDidLoad];
_valueCount = 3;
NWIconController *iconController = [NWIconController sharedController];
NWFontController *fontController = [NWFontController sharedController];
self.weatherIconLabel.font = [fontController iconFontWithSize:80.0];
self.weatherIconLabel.textColor = [[NWColorController sharedController] temperatureColor];
self.temperatureLabel.font = [fontController blackFontWithSize:18];
self.locationLabel.font = [fontController boldFontWithSize:18.0];
self.weatherDescriptionLabel.font = [fontController fontWithSize:12.0];
self.dayLightLabel.font = [fontController fontWithSize:12.0];
self.settingsButton.titleLabel.font = [fontController iconFontWithSize:80.0];
[self.settingsButton setTitleColor:[[NWColorController sharedController] temperatureColor] forState:UIControlStateNormal];
[self.settingsButton setTitle:[iconController characterForSettingsIcon] forState:UIControlStateNormal];
self.viewModel = [NWLocationWeatherViewModel new];
RAC(self, temperatureLabel.textColor) = RACObserve(self, viewModel.textColor);
RAC(self, locationLabel.textColor) = RACObserve(self, viewModel.textColor);
RAC(self, weatherDescriptionLabel.textColor) = RACObserve(self, viewModel.textColor);
RAC(self, dayLightLabel.textColor) = RACObserve(self, viewModel.textColor);
RAC(self, self.view.backgroundColor) = RACObserve(self, viewModel.backgroundColor);
self.statusCodes = [[iconController allStatusCodes] mutableCopy];
@weakify(self);
[[RACObserve([NWColorController sharedController], isDark) distinctUntilChanged]
subscribeNext:^(id x)
{
@strongify(self);
[self resetGraphs];
}];
}
- (void)redraw
{
CPTGraph *graph = self.hostView.hostedGraph;
CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *) graph.defaultPlotSpace;
plotSpace.xRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat(.0) length:CPTDecimalFromUnsignedInteger([self numberOfItemsToDraw])];
[self.hostView.hostedGraph reloadData];
self.isInitialized = YES;
}
- (void)configureHost
{
NSUInteger topSpacing = 85;
CGRect frame = CGRectMake(0, topSpacing, CGRectGetWidth(self.view.bounds), CGRectGetHeight(self.view.bounds) - topSpacing);
self.hostView = [(CPTGraphHostingView *) [CPTGraphHostingView alloc] initWithFrame:frame];
self.hostView.parallaxIntensity = 10.0;
[self.view addSubview:self.hostView];
self.hostView.alpha = 1.0f;
}
- (void)configureGraph
{
CPTGraph *graph = [[CPTXYGraph alloc] initWithFrame:self.hostView.bounds];
graph.backgroundColor = [UIColor clearColor].CGColor;
[graph.plotAreaFrame setPaddingLeft:-.5f];
[graph.plotAreaFrame setPaddingBottom:.0f];
[graph.plotAreaFrame setPaddingTop:.0f];
[graph.plotAreaFrame setPaddingRight:.0f];
[graph setPaddingLeft:.0f];
[graph setPaddingBottom:.0f];
[graph setPaddingTop:.0f];
[graph setPaddingRight:.0f];
self.hostView.hostedGraph = graph;
}
- (void)configurePlot
{
CPTGraph *graph = self.hostView.hostedGraph;
CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *) graph.defaultPlotSpace;
NWConversionController *conversionController = [NWConversionController sharedController];
CGFloat minTemperatureOrigin = [[self.location.forecastItems valueForKeyPath:@"temperature.@min.intValue"] floatValue];
CGFloat minTemperature = [[conversionController convertedTemperature:@(minTemperatureOrigin)] floatValue];
minTemperature = minTemperature > 0 ? 0 : minTemperature;
CGFloat maxTemperatureOrigin = [[self.location.forecastItems valueForKeyPath:@"temperature.@max.intValue"] floatValue];
CGFloat maxTemperature = [[conversionController convertedTemperature:@(maxTemperatureOrigin)] floatValue];
CGFloat temperatureRange = fabsf(minTemperature) + fabsf(maxTemperature);
plotSpace.xRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat(.0) length:CPTDecimalFromUnsignedInteger([self numberOfItemsToDraw])];
plotSpace.yRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat(minTemperature) length:CPTDecimalFromFloat(temperatureRange)];
self.temperaturePlot = [[CPTScatterPlot alloc] init];
self.temperaturePlot.dataSource = self;
self.temperaturePlot.identifier = @"Temperature";
NWColorController *brightnessController = [NWColorController sharedController];
CPTColor *temperatureColor = [CPTColor colorWithCGColor:brightnessController.temperatureColor.CGColor];
CPTMutablePlotRange *yRange = (CPTMutablePlotRange *) [plotSpace.yRange mutableCopy];
[yRange expandRangeByFactor:CPTDecimalFromCGFloat(1.5f)];
plotSpace.yRange = yRange;
CPTMutableLineStyle *temperatureLineStyle = (CPTMutableLineStyle *) [self.temperaturePlot.dataLineStyle mutableCopy];
temperatureLineStyle.lineWidth = 1.5f;
temperatureLineStyle.lineColor = temperatureColor;
self.temperaturePlot.dataLineStyle = temperatureLineStyle;
CPTMutableLineStyle *temperatureSymbolLineStyle = [CPTMutableLineStyle lineStyle];
temperatureSymbolLineStyle.lineColor = temperatureColor;
CPTPlotSymbol *temperatureSymbol = [CPTPlotSymbol ellipsePlotSymbol];
temperatureSymbol.fill = [CPTFill fillWithColor:[CPTColor colorWithCGColor:brightnessController.temperatureColor.CGColor]];
temperatureSymbol.lineStyle = temperatureSymbolLineStyle;
temperatureSymbol.size = CGSizeMake(4.5f, 4.5f);
self.temperaturePlot.plotSymbol = temperatureSymbol;
CPTBarPlot *barPlot = [CPTBarPlot tubularBarPlotWithColor:[CPTColor colorWithCGColor:brightnessController.rainColor.CGColor] horizontalBars:NO];
barPlot.baseValue = CPTDecimalFromString(@"0");
barPlot.dataSource = self;
barPlot.barOffset = CPTDecimalFromFloat(.5f);
barPlot.identifier = @"Rain";
barPlot.barCornerRadius = CPTFloat(.5f);
barPlot.fill = [CPTFill fillWithColor:[CPTColor colorWithCGColor:brightnessController.rainColor.CGColor]];
CPTMutableLineStyle *barLineStyle = [[CPTMutableLineStyle alloc] init];
barLineStyle.lineWidth = .0f;
barPlot.lineStyle = barLineStyle;
[graph addPlot:barPlot toPlotSpace:plotSpace];
[graph addPlot:self.temperaturePlot toPlotSpace:plotSpace];
}
- (void)configureAxis
{
CPTColor *gridAxisColor = [CPTColor colorWithCGColor:self.viewModel.gridAxisColor.CGColor];
CPTColor *gridMajorColor = [CPTColor colorWithCGColor:self.viewModel.gridMajorColor.CGColor];
CPTGraph *graph = self.hostView.hostedGraph;
CPTXYAxisSet *axisSet = (CPTXYAxisSet *)graph.axisSet;
CPTMutableLineStyle *xAxisGridLineStyle = (CPTMutableLineStyle *) [[CPTLineStyle lineStyle] mutableCopy];
xAxisGridLineStyle.lineColor = gridAxisColor;
xAxisGridLineStyle.lineWidth = .5f;
CPTXYAxis *xAxis = axisSet.xAxis;
xAxis.majorTickLineStyle = nil;
xAxis.minorTickLineStyle = nil;
xAxis.axisLineStyle = xAxisGridLineStyle;
xAxis.labelFormatter = nil;
CPTXYAxis *yAxis = axisSet.yAxis;
CPTMutableLineStyle *yAxisGridLineStyle = (CPTMutableLineStyle *) [[CPTLineStyle lineStyle] mutableCopy];
yAxisGridLineStyle.lineColor = gridMajorColor;
yAxisGridLineStyle.lineWidth = .5f;
yAxis.majorGridLineStyle = yAxisGridLineStyle;
yAxis.majorIntervalLength = CPTDecimalFromString(@"10.0");
}
#pragma mark - CPTPlotDataSource Methods
- (NSUInteger)numberOfRecordsForPlot:(CPTPlot *)plot
{
return [self numberOfItemsToDraw];
}
- (NSUInteger)numberOfItemsToDraw
{
if (UIDeviceOrientationIsLandscape(self.interfaceOrientation))
{
return [self.location.forecastItems count];
}
else
{
return (NSUInteger)self.valueCount;
}
}
- (NSNumber *)numberForPlot:(CPTPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)index
{
NWForecastItem *model = nil;
if (self.location.forecastItems != nil && index < [self.location.forecastItems count])
{
model = [self.location forecastItemsSortedByDate][index];
}
if (model == nil)
{
return @0;
}
switch (fieldEnum)
{
case CPTScatterPlotFieldX:
if ([plot.identifier isEqual:@"Temperature"])
{
return @(index + .5f);
}
else
{
return @(index);
}
case CPTScatterPlotFieldY:
if ([plot.identifier isEqual:@"Rain"])
{
CGFloat value = [model.rainAmount floatValue];
value = MAX(.25f, value);
return @(value);
}
else
{
return [[NWConversionController sharedController] convertedTemperature:model.temperature];
}
}
return @0;
}
- (CPTLayer *)dataLabelForPlot:(CPTPlot *)plot recordIndex:(NSUInteger)index
{
if ([plot.identifier isEqual:@"Temperature"] && (self.valueCount < 10 || (UIDeviceOrientationIsLandscape(self.interfaceOrientation) && index % 3 == 0)))
{
NWForecastItem *model = nil;
if (self.location.forecastItems != nil && index < [self.location.forecastItems count])
{
model = [self.location forecastItemsSortedByDate][index];
}
if (model != nil)
{
NSString *currentLabel = [[NWConversionController sharedController] displayTemperature:model.temperature];
CPTMutableTextStyle *textStyle = [[CPTMutableTextStyle alloc] init];
textStyle.color = [CPTColor darkGrayColor];
textStyle.fontSize = 9.0f;
textStyle.fontName = @"HelveticaNeue-CondensedBold";
CPTLayer *layer = [[CPTLayer alloc] initWithFrame:CGRectMake(.0f, -20.0f, 30.0f, 20.0f)];
CPTTextLayer *newLayer = [[CPTTextLayer alloc] initWithText:currentLabel style:textStyle];
[layer addSublayer:newLayer];
return layer;
}
}
return nil;
}
#pragma mark - Accessors
- (void)setLocation:(NWLocation *)location
{
_location = location;
[self update];
[self resetGraphs];
}
- (void)resetGraphs
{
[self.hostView removeFromSuperview];
[self configureHost];
[self configureGraph];
[self configurePlot];
[self configureAxis];
[self redraw];
}
- (void)setValueCount:(NSInteger)valueCount
{
if (self.isInitialized && _valueCount != valueCount)
{
NSUInteger totalCount = [self.location.forecastItems count];
_valueCount = MAX(valueCount, MIN(5, totalCount));
[self redraw];
}
}
#pragma mark - NWWeatherChildViewControllerDelegate
- (void)update
{
NWConversionController *conversionController = [NWConversionController sharedController];
self.temperatureLabel.text = [conversionController displayTemperature:self.location.temperature];
self.locationLabel.text = self.location.displayName;
self.weatherIconLabel.text = [[NWIconController sharedController] characterForStatusCode:self.location.weatherCode atDate:[NSDate date]];
self.weatherDescriptionLabel.text = self.location.weatherDescription;
self.dayLightLabel.text = [NSString stringWithFormat:NSLocalizedString(@"Sunrise: %@ – Sunset: %@", nil), [conversionController localTimeFromDate:self.location.sunrise], [conversionController localTimeFromDate:self.location.sunset]];
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment