Created
May 26, 2014 07:19
-
-
Save ricobeck/e276dcf89ca582f6dd99 to your computer and use it in GitHub Desktop.
Draws two plots
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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:@"[email protected]"] floatValue]; | |
CGFloat minTemperature = [[conversionController convertedTemperature:@(minTemperatureOrigin)] floatValue]; | |
minTemperature = minTemperature > 0 ? 0 : minTemperature; | |
CGFloat maxTemperatureOrigin = [[self.location.forecastItems valueForKeyPath:@"[email protected]"] 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