├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── Screenshots └── InterfaceBuilder.png ├── TEAChart.podspec ├── TEAChart ├── Info.plist ├── NSDate+TEAExtensions.h ├── NSDate+TEAExtensions.m ├── TEABarChart.h ├── TEABarChart.m ├── TEAChart.h ├── TEAClockChart.h ├── TEAClockChart.m ├── TEAContributionGraph.h ├── TEAContributionGraph.m ├── TEATimeRange.h └── TEATimeRange.m ├── TEAChartDemo.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcshareddata │ └── xcschemes │ ├── TEAChart.xcscheme │ └── TEAChartDemo.xcscheme ├── TEAChartDemo ├── Base.lproj │ └── Main.storyboard ├── Images.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── LaunchImage.launchimage │ │ └── Contents.json ├── Launch Screen.storyboard ├── TEAAppDelegate.h ├── TEAAppDelegate.m ├── TEAChartDemo-Info.plist ├── TEAChartDemo-Prefix.pch ├── TEAViewController.h ├── TEAViewController.m ├── en.lproj │ └── InfoPlist.strings └── main.m └── TEAChartDemoTests ├── TEAChartDemoTests-Info.plist ├── TEAChartDemoTests.m └── en.lproj └── InfoPlist.strings /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | .DS_Store 3 | */build/* 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | profile 14 | *.moved-aside 15 | DerivedData 16 | .idea/ 17 | *.hmap 18 | *.xccheckout 19 | 20 | #CocoaPods 21 | Pods 22 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | osx_image: xcode7 3 | xcode_project: TEAChartDemo.xcodeproj 4 | xcode_scheme: TEAChartDemo 5 | xcode_sdk: 6 | - iphonesimulator9.0 7 | script: 8 | - xctool -project TEAChartDemo.xcodeproj -scheme TEAChartDemo -sdk iphonesimulator ONLY_ACTIVE_ARCH=NO 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013-2015 Pomotodo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TEAChart 2 | 3 | [![Travis CI](https://travis-ci.org/xhacker/TEAChart.svg)](https://travis-ci.org/xhacker/TEAChart) 4 | [![Version](https://img.shields.io/cocoapods/v/TEAChart.svg?style=flat)](http://cocoadocs.org/docsets/TEAChart/) 5 | [![License](https://img.shields.io/cocoapods/l/TEAChart.svg?style=flat)](https://github.com/xhacker/TEAChart/blob/master/LICENSE) 6 | [![Platform](https://img.shields.io/cocoapods/p/TEAChart.svg?style=flat)](http://cocoadocs.org/docsets/TEAChart/) 7 | 8 | Simple and intuitive iOS chart library, for [Pomotodo](https://pomotodo.com) app. **Contribution graph**, **clock chart**, and **bar chart**. 9 | 10 | Supports Storyboard and is fully accessible to VoiceOver users. 11 | 12 | ## Usage 13 | 14 | The most convinient way is to use Storyboard, where you can set the attributes right in the Interface Builder. 15 | 16 | Interface Builder 17 | 18 | See the header files for complete documents. 19 | 20 | ### Contribution Graph 21 | 22 | ![Contribution Graph](http://i.imgur.com/9JsSt23.png) 23 | 24 | The contribution graph mimics the GitHub one. You can implement the `TEAContributionGraphDataSource` protocol to provide data and customize the style of the graph. 25 | The required methods are: 26 | ```objective-c 27 | // The DataSource should return an NSDate that occurs inside the month to graph 28 | - (NSDate *)monthForGraph; 29 | 30 | // The day variable is an integer from 1 to the last day of the month given by monthForGraph 31 | // Return the value to graph for each calendar day or 0. 32 | - (NSInteger)valueForDay:(NSUInteger)day; 33 | ``` 34 | There are currently three more DataSource methods to customize the coloring of the graph. 35 | Each grade is represented by a different color. 36 | ```objective-c 37 | // Defines the number of distinct colors in the graph 38 | - (NSUInteger)numberOfGrades; 39 | 40 | // Defines what color should be used by each grade. 41 | - (UIColor *)colorForGrade:(NSUInteger)grade; 42 | 43 | // Defines the cutoff values used for translating values into grades. 44 | // For example, you may want different grades for the values grade == 0, 1 <= grade < 5, 5 <= grade. 45 | // This means there are three grades total 46 | // The minimumValue for the first grade is 0, the minimum for the second grade is 1, and the minimum for the third grade is 5 47 | - (NSInteger)minimumValueForGrade:(NSUInteger)grade; 48 | ``` 49 | 50 | There’s also a method to define the tap behavior on contribution graph cells: 51 | ```objective-c 52 | - (void)dateTapped:(NSDictionary *)dict; 53 | ``` 54 | 55 | Here is a simple sample of implementing the delegate methods after connecting `delegate` in Interface Builder. 56 | ```objective-c 57 | #pragma mark - TEAContributionGraphDataSource Methods 58 | 59 | - (void)dateTapped:(NSDictionary *)dict 60 | { 61 | NSLog(@"date: %@ -- value: %@", dict[@"date"], dict[@"value"]); 62 | } 63 | 64 | - (NSDate *)monthForGraph 65 | { 66 | // Graph the current month 67 | return [NSDate date]; 68 | } 69 | 70 | - (NSInteger)valueForDay:(NSUInteger)day 71 | { 72 | // Return 0-5 73 | return day % 6; 74 | } 75 | ``` 76 | 77 | ### Clock Chart 78 | 79 | ![Clock Chart](http://i.imgur.com/dbk0a5f.png) 80 | 81 | ```objective-c 82 | // This sample uses Storyboard 83 | @property (weak, nonatomic) IBOutlet TEAClockChart *clockChart; 84 | 85 | self.clockChart.data = @[ 86 | [TEATimeRange timeRangeWithStart:[NSDate date] end:[NSDate dateWithTimeIntervalSinceNow:3600]], 87 | // ... 88 | ]; 89 | ``` 90 | 91 | ### Bar Chart 92 | 93 | ![Bar Chart](http://i.imgur.com/ScJksKh.png) 94 | 95 | Just a bar chart, no interaction, no animation. 96 | 97 | ```objective-c 98 | #import "TEAChart.h" 99 | 100 | TEABarChart *barChart = [[TEABarChart alloc] initWithFrame:CGRectMake(20, 20, 100, 40)]; 101 | barChart.data = @[@2, @7, @1, @8, @2, @8]; 102 | [self.view addSubview:barChart]; 103 | ``` 104 | 105 | ![Colored Bar Chart](http://i.imgur.com/evxPmxb.jpg) 106 | 107 | To add colors to the bar chart, add an array of colors 108 | 109 | ```objective-c 110 | #import "TEAChart.h" 111 | 112 | TEABarChart *barChart = [[TEABarChart alloc] initWithFrame:CGRectMake(20, 20, 100, 40)]; 113 | barChart.barColors = @[[UIColor orangeColor], [UIColor yellowColor], [UIColor greenColor], [UIColor blueColor]]; 114 | barChart.data = @[@2, @7, @1, @8, @2, @8]; 115 | [self.view addSubview:barChart]; 116 | ``` 117 | 118 | To add x-labels to the bar chart, set ``xLabels`` property. Should be just one character per label since the bars are narrow. 119 | 120 | ```objective-c 121 | barChart.xLabels = @[@"A", @"B", @"C", @"D", @"E", @"F"]; 122 | ``` 123 | 124 | ## Installation 125 | 126 | Use CocoaPods: 127 | 128 | ```ruby 129 | pod 'TEAChart', '~> 1.0' 130 | ``` 131 | 132 | Or drag **TEAChart** folder into your project. 133 | 134 | ## Contribution 135 | 136 | Pull requests are welcome! If you want to do something big, please open an issue first. 137 | 138 | ## License 139 | 140 | MIT 141 | -------------------------------------------------------------------------------- /Screenshots/InterfaceBuilder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xhacker/TEAChart/50754429fd12049ac19f3e576aa390ccfff59cf3/Screenshots/InterfaceBuilder.png -------------------------------------------------------------------------------- /TEAChart.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "TEAChart" 3 | s.version = "1.0.0" 4 | s.summary = "Simple and intuitive iOS chart library. Contribution graph, clock chart, and bar chart." 5 | s.homepage = "https://github.com/xhacker/TEAChart" 6 | s.social_media_url = "https://twitter.com/xhacker" 7 | 8 | s.license = 'MIT' 9 | s.author = { "Xhacker Liu" => "liu.dongyuan@gmail.com" } 10 | 11 | s.platform = :ios, '6.0' 12 | s.source = { :git => "https://github.com/xhacker/TEAChart.git", :tag => s.version } 13 | s.source_files = 'TEAChart', 'TEAChart/**/*.{h,m}' 14 | s.requires_arc = true 15 | end 16 | -------------------------------------------------------------------------------- /TEAChart/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | TEAChart 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | FMWK 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /TEAChart/NSDate+TEAExtensions.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSDate+TEAExtensions.h 3 | // TEAChartDemo 4 | // 5 | // Created by Xhacker Liu on 1/31/14. 6 | // Copyright (c) 2014 Xhacker. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #ifdef __IPHONE_8_0 12 | #define TEACalendarIdentifierGregorian NSCalendarIdentifierGregorian 13 | #else 14 | #define TEACalendarIdentifierGregorian NSGregorianCalendar 15 | #endif 16 | 17 | @interface NSDate (TEAExtensions) 18 | 19 | - (NSDate *)tea_nextDay; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /TEAChart/NSDate+TEAExtensions.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSDate+TEAExtensions.m 3 | // TEAChartDemo 4 | // 5 | // Created by Xhacker Liu on 1/31/14. 6 | // Copyright (c) 2014 Xhacker. All rights reserved. 7 | // 8 | 9 | #import "NSDate+TEAExtensions.h" 10 | 11 | @implementation NSDate (TEAExtensions) 12 | 13 | - (NSDate *)tea_nextDay 14 | { 15 | NSDateComponents *components = [[NSDateComponents alloc] init]; 16 | components.day = 1; 17 | 18 | NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:TEACalendarIdentifierGregorian]; 19 | return [calendar dateByAddingComponents:components toDate:self options:0]; 20 | } 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /TEAChart/TEABarChart.h: -------------------------------------------------------------------------------- 1 | // 2 | // TEABarChart.h 3 | // Xhacker 4 | // 5 | // Created by Xhacker on 2013-07-25. 6 | // Copyright (c) 2013 Xhacker. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | IB_DESIGNABLE 12 | @interface TEABarChart : UIView 13 | 14 | // Array of NSNumber 15 | @property (nonatomic) NSArray *data; 16 | 17 | // Array of NSString, nil if you don't want labels. 18 | @property (nonatomic) NSArray *xLabels; 19 | 20 | // Max y value for chart (only works when autoMax is NO) 21 | @property (nonatomic) IBInspectable CGFloat max; 22 | 23 | // Auto set max value 24 | @property (nonatomic) IBInspectable BOOL autoMax; 25 | 26 | @property (nonatomic) IBInspectable UIColor *barColor; 27 | @property (nonatomic) NSArray *barColors; 28 | @property (nonatomic) IBInspectable NSInteger barSpacing; 29 | @property (nonatomic) IBInspectable UIColor *backgroundColor; 30 | 31 | // Round bar height to pixel for sharper chart 32 | @property (nonatomic) IBInspectable BOOL roundToPixel; 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /TEAChart/TEABarChart.m: -------------------------------------------------------------------------------- 1 | // 2 | // TEABarChart.m 3 | // Xhacker 4 | // 5 | // Created by Xhacker on 2013-07-25. 6 | // Copyright (c) 2013 Xhacker. All rights reserved. 7 | // 8 | 9 | #import "TEABarChart.h" 10 | 11 | @interface TEABarChart () 12 | 13 | /** 14 | @discussion A mutable array of elements that will be made available to VoiceOver. 15 | */ 16 | @property (nonatomic, strong) NSMutableArray *accessibleElements; 17 | 18 | @end 19 | 20 | @implementation TEABarChart 21 | 22 | - (id)initWithFrame:(CGRect)frame 23 | { 24 | self = [super initWithFrame:frame]; 25 | if (self) { 26 | [self loadDefaults]; 27 | } 28 | return self; 29 | } 30 | 31 | - (id)initWithCoder:(NSCoder *)decoder 32 | { 33 | self = [super initWithCoder:decoder]; 34 | if (self) { 35 | [self loadDefaults]; 36 | } 37 | return self; 38 | } 39 | 40 | - (void)loadDefaults 41 | { 42 | self.opaque = NO; 43 | 44 | // Initialize an empty array which will be populated in -drawRect: 45 | self.accessibleElements = [[NSMutableArray alloc] init]; 46 | 47 | _xLabels = nil; 48 | 49 | _autoMax = YES; 50 | 51 | _barColor = [UIColor colorWithRed:106.0/255 green:175.0/255 blue:232.0/255 alpha:1]; 52 | _barSpacing = 8; 53 | _backgroundColor = [UIColor colorWithWhite:0.97 alpha:1]; 54 | _roundToPixel = YES; 55 | } 56 | 57 | - (void)prepareForInterfaceBuilder 58 | { 59 | [self loadDefaults]; 60 | 61 | self.data = @[@3, @1, @4, @1, @5, @9, @2, @6]; 62 | self.xLabels = @[@"T", @"E", @"A", @"C", @"h", @"a", @"r", @"t"]; 63 | } 64 | 65 | - (void)drawRect:(CGRect)rect 66 | { 67 | [super drawRect:rect]; 68 | 69 | CGContextRef context = UIGraphicsGetCurrentContext(); 70 | 71 | double max = self.autoMax ? [[self.data valueForKeyPath:@"@max.self"] doubleValue] : self.max; 72 | CGFloat barMaxHeight = CGRectGetHeight(rect); 73 | NSInteger numberOfBars = self.data.count; 74 | CGFloat barWidth = (CGRectGetWidth(rect) - self.barSpacing * (numberOfBars - 1)) / numberOfBars; 75 | CGFloat barWidthRounded = ceil(barWidth); 76 | 77 | if (self.xLabels) { 78 | CGFloat fontSize = floor(barWidth); 79 | CGFloat labelsTopMargin = ceil(fontSize * 0.33); 80 | barMaxHeight -= (fontSize + labelsTopMargin); 81 | 82 | [self.xLabels enumerateObjectsUsingBlock:^(NSString *label, NSUInteger idx, BOOL *stop) { 83 | NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc]init] ; 84 | paragraphStyle.alignment = NSTextAlignmentCenter; 85 | 86 | [label drawInRect:CGRectMake(idx * (barWidth + self.barSpacing), barMaxHeight + labelsTopMargin, barWidth, fontSize * 1.2) 87 | withAttributes:@{ 88 | NSFontAttributeName:[UIFont fontWithName:@"HelveticaNeue" size:fontSize], 89 | NSForegroundColorAttributeName:[UIColor colorWithWhite:0.56 alpha:1], 90 | NSParagraphStyleAttributeName:paragraphStyle, 91 | }]; 92 | }]; 93 | } 94 | 95 | for (NSInteger i = 0; i < numberOfBars; i += 1) 96 | { 97 | CGFloat barHeight = (max == 0 ? 0 : barMaxHeight * [self.data[i] floatValue] / max); 98 | if (barHeight > barMaxHeight) { 99 | barHeight = barMaxHeight; 100 | } 101 | if (self.roundToPixel) { 102 | barHeight = (int)barHeight; 103 | } 104 | 105 | CGFloat x = floor(i * (barWidth + self.barSpacing)); 106 | 107 | [self.backgroundColor setFill]; 108 | CGRect backgroundRect = CGRectMake(x, 0, barWidthRounded, barMaxHeight); 109 | CGContextFillRect(context, backgroundRect); 110 | 111 | UIColor *barColor = self.barColors ? self.barColors[i % self.barColors.count] : self.barColor; 112 | [barColor setFill]; 113 | CGRect barRect = CGRectMake(x, barMaxHeight - barHeight, barWidthRounded, barHeight); 114 | CGContextFillRect(context, barRect); 115 | 116 | // Populate self.accessibleElements with each bar's name and value. 117 | UIAccessibilityElement *element = [[UIAccessibilityElement alloc] initWithAccessibilityContainer:self]; 118 | // The frame can be set to just rect, if it improves usability. 119 | element.accessibilityFrame = [self convertRect:barRect toView:nil]; 120 | // If xLabels has not been initialized, give each bar a name to identify them in the accessibiltyLabel. 121 | NSString *barLabel = self.xLabels[i] ? self.xLabels[i] : [NSString stringWithFormat: @"Bar %ld of %ld", i + 1, numberOfBars]; 122 | 123 | // Combine eacb bar's title and value into the accessiblityLabel. 124 | /* The label uses a percentage estimate, in case the value and max are too large, but if a use case 125 | * requires count out of a total, substitute the following single-line comment. 126 | */ 127 | // [NSString stringWithFormat:@"%@ : %@ out of %d", barLabel, self.data[i], (int)max]; 128 | double percentage = [(NSNumber *)(self.data[i]) doubleValue]/max; 129 | element.accessibilityLabel = [NSString stringWithFormat:@"%@ : %.2f %%", barLabel, percentage * 100.0]; 130 | [self.accessibleElements addObject:element]; 131 | } 132 | } 133 | 134 | #pragma mark Accessibility 135 | 136 | - (BOOL)isAccessibilityElement 137 | { 138 | return NO; 139 | } 140 | 141 | - (NSInteger)accessibilityElementCount 142 | { 143 | return self.data.count; 144 | } 145 | 146 | - (id)accessibilityElementAtIndex:(NSInteger)index 147 | { 148 | return self.accessibleElements[index]; 149 | } 150 | 151 | - (NSInteger)indexOfAccessibilityElement:(id)element 152 | { 153 | return [self.accessibleElements indexOfObject:element]; 154 | } 155 | 156 | #pragma mark Setters 157 | 158 | - (void)setData:(NSArray *)data 159 | { 160 | _data = data; 161 | [self setNeedsDisplay]; 162 | } 163 | 164 | - (void)setXLabels:(NSArray *)xLabels 165 | { 166 | _xLabels = xLabels; 167 | [self setNeedsDisplay]; 168 | } 169 | 170 | - (void)setMax:(CGFloat)max 171 | { 172 | _max = max; 173 | [self setNeedsDisplay]; 174 | } 175 | 176 | - (void)setAutoMax:(BOOL)autoMax 177 | { 178 | _autoMax = autoMax; 179 | [self setNeedsDisplay]; 180 | } 181 | 182 | - (void)setBarColors:(NSArray *)barColors 183 | { 184 | _barColors = barColors; 185 | [self setNeedsDisplay]; 186 | } 187 | 188 | - (void)setBarColor:(UIColor *)barColor 189 | { 190 | _barColor = barColor; 191 | [self setNeedsDisplay]; 192 | } 193 | 194 | - (void)setBarSpacing:(NSInteger)barSpacing 195 | { 196 | _barSpacing = barSpacing; 197 | [self setNeedsDisplay]; 198 | } 199 | 200 | - (void)setBackgroundColor:(UIColor *)backgroundColor 201 | { 202 | _backgroundColor = backgroundColor; 203 | [self setNeedsDisplay]; 204 | } 205 | 206 | @end 207 | -------------------------------------------------------------------------------- /TEAChart/TEAChart.h: -------------------------------------------------------------------------------- 1 | // 2 | // TEAChart.h 3 | // Xhacker 4 | // 5 | // Created by Xhacker on 11/11/2013. 6 | // Copyright (c) 2013 Xhacker. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | FOUNDATION_EXPORT double TEAChart_VersionNumber; 12 | FOUNDATION_EXPORT const unsigned char TEAChart_VersionString[]; 13 | 14 | #import "TEABarChart.h" 15 | #import "TEAContributionGraph.h" 16 | #import "TEAClockChart.h" 17 | #import "TEATimeRange.h" 18 | -------------------------------------------------------------------------------- /TEAChart/TEAClockChart.h: -------------------------------------------------------------------------------- 1 | // 2 | // TEAClockChart.h 3 | // Xhacker 4 | // 5 | // Created by Xhacker on 2013-07-27. 6 | // Copyright (c) 2013 Xhacker. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | IB_DESIGNABLE 12 | @interface TEAClockChart : UIView 13 | 14 | // Array of TEATimeRange 15 | @property (nonatomic) NSArray *data; 16 | 17 | @property (nonatomic) IBInspectable UIColor *fillColor; 18 | @property (nonatomic) IBInspectable UIColor *strokeColor; 19 | @property (nonatomic) IBInspectable CGFloat borderWidth; 20 | 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /TEAChart/TEAClockChart.m: -------------------------------------------------------------------------------- 1 | // 2 | // TEAClockChart.m 3 | // Xhacker 4 | // 5 | // Created by Xhacker on 2013-07-27. 6 | // Copyright (c) 2013 Xhacker. All rights reserved. 7 | // 8 | 9 | #import "TEAClockChart.h" 10 | #import "TEATimeRange.h" 11 | #import "NSDate+TEAExtensions.h" 12 | 13 | @interface TEAClockChart () 14 | 15 | /** 16 | @discussion A mutable array of elements that will be made available to VoiceOver. 17 | */ 18 | @property (nonatomic, strong) NSMutableArray *accessibleElements; 19 | 20 | @end 21 | 22 | @implementation TEAClockChart 23 | 24 | - (id)initWithFrame:(CGRect)frame 25 | { 26 | self = [super initWithFrame:frame]; 27 | if (self) { 28 | [self loadDefaults]; 29 | } 30 | return self; 31 | } 32 | 33 | - (id)initWithCoder:(NSCoder *)decoder 34 | { 35 | self = [super initWithCoder:decoder]; 36 | if (self) { 37 | [self loadDefaults]; 38 | } 39 | return self; 40 | } 41 | 42 | - (void)loadDefaults 43 | { 44 | self.opaque = NO; 45 | // Initialize an empty array which will be populated in -drawRect: 46 | self.accessibleElements = [[NSMutableArray alloc] init]; 47 | 48 | _fillColor = [UIColor colorWithRed:0.922 green:0.204 blue:0.239 alpha:0.25]; 49 | _strokeColor = [UIColor colorWithWhite:0.85 alpha:1]; 50 | _borderWidth = 2; 51 | } 52 | 53 | - (void)drawRect:(CGRect)rect 54 | { 55 | [super drawRect:rect]; 56 | 57 | CGContextRef context = UIGraphicsGetCurrentContext(); 58 | CGFloat radius = MIN(CGRectGetWidth(rect), CGRectGetHeight(rect)) / 2; 59 | CGFloat originX = CGRectGetWidth(rect) / 2; 60 | CGFloat originY = CGRectGetHeight(rect) / 2; 61 | 62 | // draw sectors 63 | [self.fillColor setFill]; 64 | [self.data enumerateObjectsUsingBlock:^(TEATimeRange *timeRange, NSUInteger idx, BOOL *stop) { 65 | NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:TEACalendarIdentifierGregorian]; 66 | NSDateComponents *startComp = [calendar components:NSCalendarUnitHour | NSCalendarUnitMinute fromDate:timeRange.start]; 67 | NSDateComponents *endComp = [calendar components:NSCalendarUnitHour | NSCalendarUnitMinute fromDate:timeRange.end]; 68 | CGFloat startMinutes = startComp.hour * 60 + startComp.minute; 69 | CGFloat endMinutes = endComp.hour * 60 + endComp.minute; 70 | 71 | CGContextBeginPath(context); 72 | CGFloat startAngle = startMinutes / (24 * 60) * (2 * M_PI) - M_PI_2; 73 | 74 | // use 26 mins for pomo instead of 30 to prevent small overlaps 75 | CGFloat endAngle = endMinutes / (24 * 60) * (2 * M_PI) - M_PI_2; 76 | 77 | // UIView flips the Y-coordinate, so 0 is actually clockwise 78 | CGContextAddArc(context, originX, originY, radius * 0.9, startAngle, endAngle, 0); 79 | CGContextAddLineToPoint(context, originX, originY); 80 | 81 | // Create and append accessibilityELement by first creating the rect. 82 | CGRect accessibleRect = CGContextGetPathBoundingBox(context); 83 | // The formatter is used to narrate the start and end times 84 | NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; 85 | formatter.dateStyle = NSDateFormatterMediumStyle; 86 | formatter.timeStyle = NSDateFormatterShortStyle; 87 | // Use the above to create the element. IMPORTANT: it MUST be added before FillPath is called. 88 | UIAccessibilityElement *element = [[UIAccessibilityElement alloc] initWithAccessibilityContainer:self]; 89 | NSString *startLabel = [formatter stringFromDate:timeRange.start]; 90 | NSString *endLabel = [formatter stringFromDate:timeRange.end]; 91 | element.accessibilityLabel = [NSString stringWithFormat:@"%@ to %@", startLabel, endLabel]; 92 | element.accessibilityFrame = [self convertRect:accessibleRect toView:nil]; 93 | [self.accessibleElements addObject:element]; 94 | 95 | // The accessibility elements MUST be added before filling the path. 96 | CGContextFillPath(context); 97 | }]; 98 | 99 | // draw ring 100 | CGContextSetLineWidth(context, self.borderWidth); 101 | [self.strokeColor setStroke]; 102 | CGFloat margin = 0.1; 103 | CGContextAddEllipseInRect(context, CGRectMake(originX - radius * (1 - margin), originY - radius * (1 - margin), 2 * (1 - margin) * radius, 2 * (1 - margin) * radius)); 104 | CGContextStrokePath(context); 105 | 106 | // draw scales 107 | CGContextSetLineWidth(context, 1); 108 | for (NSInteger i = 0; i < 24; i += 1) { 109 | CGContextSaveGState(context); 110 | CGContextTranslateCTM(context, originX, originY); 111 | CGContextRotateCTM(context, i * M_PI / 12); 112 | CGContextMoveToPoint(context, 0, radius); 113 | CGFloat lengthFactor = i % 6 == 0 ? 0.08 : 0.04; 114 | CGContextAddLineToPoint(context, 0, radius - radius * lengthFactor); 115 | CGContextStrokePath(context); 116 | CGContextRestoreGState(context); 117 | } 118 | } 119 | 120 | #pragma mark Accessibility 121 | 122 | - (BOOL)isAccessibilityElement 123 | { 124 | return NO; 125 | } 126 | 127 | - (NSInteger)accessibilityElementCount 128 | { 129 | return self.data.count; 130 | } 131 | 132 | - (id)accessibilityElementAtIndex:(NSInteger)index 133 | { 134 | return self.accessibleElements[index]; 135 | } 136 | 137 | - (NSInteger)indexOfAccessibilityElement:(id)element 138 | { 139 | return [self.accessibleElements indexOfObject:element]; 140 | } 141 | 142 | #pragma mark Setters 143 | 144 | - (void)setData:(NSArray *)data 145 | { 146 | _data = data; 147 | [self setNeedsDisplay]; 148 | } 149 | 150 | - (void)setFillColor:(UIColor *)fillColor 151 | { 152 | _fillColor = fillColor; 153 | [self setNeedsDisplay]; 154 | } 155 | 156 | - (void)setStrokeColor:(UIColor *)strokeColor 157 | { 158 | _strokeColor = strokeColor; 159 | [self setNeedsDisplay]; 160 | } 161 | 162 | @end 163 | -------------------------------------------------------------------------------- /TEAChart/TEAContributionGraph.h: -------------------------------------------------------------------------------- 1 | // 2 | // TEAContributionGraph.h 3 | // Xhacker 4 | // 5 | // Created by Xhacker on 2013-07-28. 6 | // Copyright (c) 2013 Xhacker. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #pragma mark - TEAContributionGraphDelegate 12 | 13 | @protocol TEAContributionGraphDataSource 14 | 15 | @optional 16 | 17 | - (void)dateTapped:(NSDictionary *)dict; 18 | 19 | @required 20 | 21 | /** 22 | @discussion For the current date, return [NSDate date] 23 | @returns A NSDate in month that the graph should display 24 | */ 25 | - (NSDate *)monthForGraph; 26 | 27 | /** 28 | @discussion If there is no value, return nil 29 | @param day Defined from 1 to the last day of the month in the graph. 30 | @returns The value to display for each day of the month. 31 | */ 32 | - (NSInteger)valueForDay:(NSUInteger)day; 33 | 34 | @optional 35 | /** 36 | @description If this method isn't implemented, the default value of 5 is used. 37 | @returns Returns the number of color divides in the graph. 38 | */ 39 | - (NSUInteger)numberOfGrades; 40 | 41 | /** 42 | @description Each grade requires exactly one color. 43 | If this method isn't implemented, the default 5 color scheme is used. 44 | @param grade The grade index. From 0-numberOfGrades 45 | @returns A UIColor for the specified grade. 46 | */ 47 | - (UIColor *)colorForGrade:(NSUInteger)grade; 48 | 49 | /** 50 | @description defines how values are translated into grades 51 | If this method isn't implemented, the default values are used. 52 | @param grade The grade from 0-numberOfGrades 53 | @returns An NSUInteger that specifies the minimum cutoff for a grade 54 | */ 55 | - (NSInteger)minimumValueForGrade:(NSUInteger)grade; 56 | 57 | @end 58 | 59 | 60 | @interface TEAContributionGraph : UIView 61 | 62 | #pragma mark - Properties 63 | 64 | // If you want to fine tune the size, override these two properties. 65 | @property (nonatomic) CGFloat cellSize; 66 | @property (nonatomic) CGFloat cellSpacing; 67 | 68 | @property (nonatomic) IBInspectable BOOL showDayNumbers; 69 | 70 | @property (nonatomic, weak) IBOutlet id delegate; 71 | 72 | @end 73 | -------------------------------------------------------------------------------- /TEAChart/TEAContributionGraph.m: -------------------------------------------------------------------------------- 1 | // 2 | // TEAContributionGraph.m 3 | // Xhacker 4 | // 5 | // Created by Xhacker on 2013-07-28. 6 | // Copyright (c) 2013 Xhacker. All rights reserved. 7 | // 8 | 9 | #import "TEAContributionGraph.h" 10 | #import "NSDate+TEAExtensions.h" 11 | #import 12 | 13 | static const NSInteger kDefaultGradeCount = 5; 14 | 15 | @interface TEAContributionGraph () 16 | 17 | @property (nonatomic) NSUInteger gradeCount; 18 | @property (nonatomic, strong) NSMutableArray *gradeMinCutoff; 19 | @property (nonatomic, strong) NSDate *graphMonth; 20 | @property (nonatomic, strong) NSMutableArray *colors; 21 | 22 | /** 23 | @discussion A mutable array of elements that will be made available to VoiceOver. 24 | */ 25 | @property (nonatomic, strong) NSMutableArray *accessibleElements; 26 | 27 | @end 28 | 29 | @implementation TEAContributionGraph 30 | 31 | - (void)loadDefaults 32 | { 33 | self.opaque = NO; 34 | // Initialize an empty array which will be populated in -drawRect: 35 | self.accessibleElements = [[NSMutableArray alloc] init]; 36 | 37 | // Load one-time data from the delegate 38 | 39 | // Get the total number of grades 40 | if ([_delegate respondsToSelector:@selector(numberOfGrades)]) { 41 | _gradeCount = [_delegate numberOfGrades]; 42 | } 43 | else { 44 | _gradeCount = kDefaultGradeCount; 45 | } 46 | 47 | // Load all of the colors from the delegate 48 | if ([_delegate respondsToSelector:@selector(colorForGrade:)]) { 49 | _colors = [[NSMutableArray alloc] initWithCapacity:_gradeCount]; 50 | for (int i = 0; i < _gradeCount; i++) { 51 | [_colors addObject:[_delegate colorForGrade:i]]; 52 | } 53 | } 54 | else { 55 | // Use the defaults 56 | _colors = [[NSMutableArray alloc] initWithObjects: 57 | [UIColor colorWithRed:0.933 green:0.933 blue:0.933 alpha:1], 58 | [UIColor colorWithRed:0.839 green:0.902 blue:0.522 alpha:1], 59 | [UIColor colorWithRed:0.549 green:0.776 blue:0.396 alpha:1], 60 | [UIColor colorWithRed:0.267 green:0.639 blue:0.251 alpha:1], 61 | [UIColor colorWithRed:0.118 green:0.408 blue:0.137 alpha:1], nil]; 62 | // Check if there is the correct number of colors 63 | if (_gradeCount != kDefaultGradeCount) { 64 | [[NSException exceptionWithName:@"Invalid Data" reason:@"The number of grades does not match the number of colors. Implement colorForGrade: to define a different number of colors than the default 5" userInfo:NULL] raise]; 65 | } 66 | } 67 | 68 | // Get the minimum cutoff for each grade 69 | if ([_delegate respondsToSelector:@selector(minimumValueForGrade:)]) { 70 | _gradeMinCutoff = [[NSMutableArray alloc] initWithCapacity:_gradeCount]; 71 | for (int i = 0; i < _gradeCount; i++) { 72 | // Convert each value to a NSNumber 73 | [_gradeMinCutoff addObject:@([_delegate minimumValueForGrade:i])]; 74 | } 75 | } 76 | else { 77 | // Use the default values 78 | _gradeMinCutoff = [[NSMutableArray alloc] initWithObjects: 79 | @0, 80 | @1, 81 | @3, 82 | @6, 83 | @8, nil]; 84 | 85 | if (_gradeCount != kDefaultGradeCount) { 86 | [[NSException exceptionWithName:@"Invalid Data" reason:@"The number of grades does not match the number of grade cutoffs. Implement minimumValueForGrade: to define the correct number of cutoff values" userInfo:NULL] raise]; 87 | } 88 | } 89 | 90 | if ([_delegate respondsToSelector:@selector(monthForGraph)]) { 91 | _graphMonth = [_delegate monthForGraph]; 92 | } 93 | else { 94 | // Use the current month by default 95 | _graphMonth = [NSDate date]; 96 | } 97 | 98 | _cellSpacing = floor(CGRectGetWidth(self.frame) / 20); 99 | _cellSize = _cellSpacing * 2; 100 | } 101 | 102 | - (void)drawRect:(CGRect)rect 103 | { 104 | [super drawRect:rect]; 105 | 106 | CGContextRef context = UIGraphicsGetCurrentContext(); 107 | 108 | NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:TEACalendarIdentifierGregorian]; 109 | calendar.locale = [NSLocale currentLocale]; 110 | NSDateComponents *comp = [calendar components:(NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay) fromDate:_graphMonth]; 111 | comp.day = 1; 112 | NSDate *firstDay = [calendar dateFromComponents:comp]; 113 | NSUInteger firstWeekday = calendar.firstWeekday; 114 | 115 | comp.month = comp.month + 1; 116 | NSDate *nextMonth = [calendar dateFromComponents:comp]; 117 | 118 | NSArray *weekdayNames = [[NSDateFormatter alloc] init].veryShortWeekdaySymbols; 119 | 120 | [[UIColor colorWithWhite:0.56 alpha:1] setFill]; 121 | NSInteger textHeight = self.cellSize * 1.2; 122 | for (NSInteger i = 0; i < 7; i += 1) { 123 | CGRect rect = CGRectMake(i * (self.cellSize + self.cellSpacing), 0, self.cellSize, self.cellSize); 124 | NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle defaultParagraphStyle] mutableCopy]; 125 | paragraphStyle.lineBreakMode = NSLineBreakByClipping; 126 | paragraphStyle.alignment = NSTextAlignmentCenter; 127 | NSDictionary *attributes = @{ 128 | NSFontAttributeName: [UIFont fontWithName:@"HelveticaNeue-Light" size:self.cellSize * 0.65], 129 | NSParagraphStyleAttributeName: paragraphStyle, 130 | }; 131 | [weekdayNames[(i + firstWeekday - 1) % 7] drawInRect:rect withAttributes:attributes]; 132 | } 133 | 134 | NSDictionary *dayNumberTextAttributes = nil; 135 | if (self.showDayNumbers) { 136 | NSMutableParagraphStyle *paragraphStyle = [NSMutableParagraphStyle new]; 137 | paragraphStyle.alignment = NSTextAlignmentLeft; 138 | dayNumberTextAttributes = @{NSFontAttributeName: [UIFont fontWithName:@"HelveticaNeue-Light" size:self.cellSize * 0.4], NSParagraphStyleAttributeName: paragraphStyle}; 139 | } 140 | 141 | for (NSDate *date = firstDay; [date compare:nextMonth] == NSOrderedAscending; date = [date tea_nextDay]) { 142 | NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:TEACalendarIdentifierGregorian]; 143 | calendar.firstWeekday = firstWeekday; 144 | NSDateComponents *comp = [calendar components:NSCalendarUnitWeekday | NSCalendarUnitWeekOfMonth | NSCalendarUnitDay fromDate:date]; 145 | NSInteger weekday = firstWeekday == 1 ? comp.weekday : ((comp.weekday + 5) % 7) + 1; 146 | NSInteger weekOfMonth = comp.weekOfMonth; 147 | NSInteger day = comp.day; 148 | 149 | NSInteger grade = 0; 150 | NSInteger contributions = 0; 151 | if ([self.delegate respondsToSelector:@selector(valueForDay:)]) { 152 | contributions = [self.delegate valueForDay:day]; 153 | } 154 | 155 | // Get the grade from the minimum cutoffs 156 | for (int i = 0; i < _gradeCount; i++) { 157 | if ([_gradeMinCutoff[i] integerValue] <= contributions) { 158 | grade = i; 159 | } 160 | } 161 | 162 | [self.colors[grade] setFill]; 163 | 164 | CGRect backgroundRect = CGRectMake((weekday - 1) * (self.cellSize + self.cellSpacing), 165 | (weekOfMonth - 1) * (self.cellSize + self.cellSpacing) + textHeight, 166 | self.cellSize, self.cellSize); 167 | CGContextFillRect(context, backgroundRect); 168 | 169 | if ([self.delegate respondsToSelector:@selector(dateTapped:)]) { 170 | UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; 171 | button.backgroundColor = [UIColor clearColor]; 172 | button.frame = backgroundRect; 173 | [button addTarget:self action:@selector(daySelected:) forControlEvents:UIControlEventTouchUpInside]; 174 | 175 | NSDictionary *data = @{ 176 | @"date": [date tea_nextDay], 177 | @"value": @([self.delegate valueForDay:day]) 178 | }; 179 | objc_setAssociatedObject(button, @"dynamic_key", data, OBJC_ASSOCIATION_COPY); 180 | [self addSubview:button]; 181 | } 182 | 183 | if (self.showDayNumbers) { 184 | NSString *string = [NSString stringWithFormat:@"%ld", (long)day]; 185 | [string drawInRect:backgroundRect withAttributes:dayNumberTextAttributes]; 186 | } 187 | 188 | // Populate self.accessibleElements with each blocks date and contribution count. 189 | UIAccessibilityElement *dayBlock = [[UIAccessibilityElement alloc] initWithAccessibilityContainer:self]; 190 | dayBlock.accessibilityFrame = [self convertRect:backgroundRect toView:nil] ; 191 | // We use the formatter to convert the date to it's NSString representation. 192 | NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; 193 | formatter.dateStyle = NSDateFormatterFullStyle; 194 | 195 | // Assign the accessibilityLabel and append the element to self.accessibleElements. 196 | if (contributions > 0) { 197 | dayBlock.accessibilityLabel = [NSString stringWithFormat:@"%@ : %ld Contributions", [formatter stringFromDate:date], contributions]; 198 | } else { 199 | dayBlock.accessibilityLabel = [NSString stringWithFormat:@"%@ : No Contributions", [formatter stringFromDate:date]]; 200 | } 201 | 202 | [self.accessibleElements addObject:dayBlock]; 203 | } 204 | } 205 | 206 | - (void)daySelected:(id)sender 207 | { 208 | NSDictionary *data = (NSDictionary *)objc_getAssociatedObject(sender, @"dynamic_key"); 209 | if ([self.delegate respondsToSelector:@selector(dateTapped:)]) { 210 | [self.delegate dateTapped:data]; 211 | } 212 | } 213 | 214 | #pragma mark Accessibility 215 | 216 | - (BOOL)isAccessibilityElement 217 | { 218 | return NO; 219 | } 220 | 221 | - (NSInteger)accessibilityElementCount 222 | { 223 | return [self.accessibleElements count]; 224 | } 225 | 226 | - (id)accessibilityElementAtIndex:(NSInteger)index 227 | { 228 | return self.accessibleElements[index]; 229 | } 230 | 231 | - (NSInteger)indexOfAccessibilityElement:(id)element 232 | { 233 | return [self.accessibleElements indexOfObject:element]; 234 | } 235 | 236 | #pragma mark Setters 237 | 238 | - (void)setDelegate:(id)delegate 239 | { 240 | _delegate = delegate; 241 | [self loadDefaults]; 242 | [self setNeedsDisplay]; 243 | } 244 | 245 | - (void)setCellSize:(CGFloat)cellSize 246 | { 247 | _cellSize = cellSize; 248 | [self setNeedsDisplay]; 249 | } 250 | 251 | - (void)setCellSpacing:(CGFloat)cellSpacing 252 | { 253 | _cellSpacing = cellSpacing; 254 | [self setNeedsDisplay]; 255 | } 256 | 257 | 258 | @end 259 | -------------------------------------------------------------------------------- /TEAChart/TEATimeRange.h: -------------------------------------------------------------------------------- 1 | // 2 | // TEATimeRange.h 3 | // TEAChartDemo 4 | // 5 | // Created by Xhacker on 11/12/2013. 6 | // Copyright (c) 2013 Xhacker. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TEATimeRange : NSObject 12 | 13 | @property (nonatomic) NSDate *start; 14 | @property (nonatomic) NSDate *end; 15 | 16 | + (instancetype)timeRangeWithStart:(NSDate *)startTime end:(NSDate *)endTime; 17 | 18 | - (id)initWithStart:(NSDate *)startTime end:(NSDate *)endTime; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /TEAChart/TEATimeRange.m: -------------------------------------------------------------------------------- 1 | // 2 | // TEATimeRange.m 3 | // TEAChartDemo 4 | // 5 | // Created by Xhacker on 11/12/2013. 6 | // Copyright (c) 2013 Xhacker. All rights reserved. 7 | // 8 | 9 | #import "TEATimeRange.h" 10 | 11 | @implementation TEATimeRange 12 | 13 | + (instancetype)timeRangeWithStart:(NSDate *)startTime end:(NSDate *)endTime 14 | { 15 | return [[TEATimeRange alloc] initWithStart:startTime end:endTime]; 16 | } 17 | 18 | - (id)initWithStart:(NSDate *)startTime end:(NSDate *)endTime 19 | { 20 | self = [super init]; 21 | if (self) { 22 | _start = startTime; 23 | _end = endTime; 24 | } 25 | return self; 26 | } 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /TEAChartDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 48; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1A11497518311D120015BDE2 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A11497418311D120015BDE2 /* Foundation.framework */; }; 11 | 1A11497718311D120015BDE2 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A11497618311D120015BDE2 /* CoreGraphics.framework */; }; 12 | 1A11497918311D120015BDE2 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A11497818311D120015BDE2 /* UIKit.framework */; }; 13 | 1A11497F18311D120015BDE2 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 1A11497D18311D120015BDE2 /* InfoPlist.strings */; }; 14 | 1A11498118311D120015BDE2 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A11498018311D120015BDE2 /* main.m */; }; 15 | 1A11498518311D120015BDE2 /* TEAAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A11498418311D120015BDE2 /* TEAAppDelegate.m */; }; 16 | 1A11498818311D120015BDE2 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 1A11498618311D120015BDE2 /* Main.storyboard */; }; 17 | 1A11498B18311D120015BDE2 /* TEAViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A11498A18311D120015BDE2 /* TEAViewController.m */; }; 18 | 1A11498D18311D120015BDE2 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A11498C18311D120015BDE2 /* Images.xcassets */; }; 19 | 1A11499418311D120015BDE2 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A11499318311D120015BDE2 /* XCTest.framework */; }; 20 | 1A11499518311D120015BDE2 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A11497418311D120015BDE2 /* Foundation.framework */; }; 21 | 1A11499618311D120015BDE2 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A11497818311D120015BDE2 /* UIKit.framework */; }; 22 | 1A11499E18311D120015BDE2 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 1A11499C18311D120015BDE2 /* InfoPlist.strings */; }; 23 | 1A1149A018311D120015BDE2 /* TEAChartDemoTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A11499F18311D120015BDE2 /* TEAChartDemoTests.m */; }; 24 | 1A1149AB18311DA10015BDE2 /* TEABarChart.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1149AA18311DA10015BDE2 /* TEABarChart.m */; }; 25 | 1A1149B018312D610015BDE2 /* TEAContributionGraph.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1149AF18312D610015BDE2 /* TEAContributionGraph.m */; }; 26 | 1A1149B3183134F40015BDE2 /* TEAClockChart.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1149B2183134F40015BDE2 /* TEAClockChart.m */; }; 27 | 1A1149B618313ABB0015BDE2 /* TEATimeRange.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1149B518313ABB0015BDE2 /* TEATimeRange.m */; }; 28 | 1A1DEC271BA4EC3100028BCF /* Launch Screen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 1A1DEC261BA4EC3100028BCF /* Launch Screen.storyboard */; }; 29 | 1AADE620189B990A00EB7C2C /* NSDate+TEAExtensions.m in Sources */ = {isa = PBXBuildFile; fileRef = 1AADE61F189B990A00EB7C2C /* NSDate+TEAExtensions.m */; }; 30 | CFC4CB3F1E3F126C006DF0FE /* TEAChart.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A1149AD183121CF0015BDE2 /* TEAChart.h */; settings = {ATTRIBUTES = (Public, ); }; }; 31 | CFC4CB401E3F126C006DF0FE /* TEABarChart.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A1149A918311DA10015BDE2 /* TEABarChart.h */; settings = {ATTRIBUTES = (Public, ); }; }; 32 | CFC4CB411E3F126C006DF0FE /* TEABarChart.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1149AA18311DA10015BDE2 /* TEABarChart.m */; }; 33 | CFC4CB421E3F126C006DF0FE /* TEAContributionGraph.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A1149AE18312D610015BDE2 /* TEAContributionGraph.h */; settings = {ATTRIBUTES = (Public, ); }; }; 34 | CFC4CB431E3F126C006DF0FE /* TEAContributionGraph.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1149AF18312D610015BDE2 /* TEAContributionGraph.m */; }; 35 | CFC4CB441E3F126C006DF0FE /* TEAClockChart.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A1149B1183134F40015BDE2 /* TEAClockChart.h */; settings = {ATTRIBUTES = (Public, ); }; }; 36 | CFC4CB451E3F126C006DF0FE /* TEAClockChart.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1149B2183134F40015BDE2 /* TEAClockChart.m */; }; 37 | CFC4CB461E3F126C006DF0FE /* TEATimeRange.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A1149B418313ABB0015BDE2 /* TEATimeRange.h */; settings = {ATTRIBUTES = (Public, ); }; }; 38 | CFC4CB471E3F126C006DF0FE /* TEATimeRange.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1149B518313ABB0015BDE2 /* TEATimeRange.m */; }; 39 | CFC4CB481E3F126C006DF0FE /* NSDate+TEAExtensions.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AADE61E189B990A00EB7C2C /* NSDate+TEAExtensions.h */; }; 40 | CFC4CB491E3F126C006DF0FE /* NSDate+TEAExtensions.m in Sources */ = {isa = PBXBuildFile; fileRef = 1AADE61F189B990A00EB7C2C /* NSDate+TEAExtensions.m */; }; 41 | /* End PBXBuildFile section */ 42 | 43 | /* Begin PBXContainerItemProxy section */ 44 | 1A11499718311D120015BDE2 /* PBXContainerItemProxy */ = { 45 | isa = PBXContainerItemProxy; 46 | containerPortal = 1A11496918311D120015BDE2 /* Project object */; 47 | proxyType = 1; 48 | remoteGlobalIDString = 1A11497018311D120015BDE2; 49 | remoteInfo = TEAChartDemo; 50 | }; 51 | /* End PBXContainerItemProxy section */ 52 | 53 | /* Begin PBXCopyFilesBuildPhase section */ 54 | CF18DF321E3F1ACC00D82E1C /* Embed Frameworks */ = { 55 | isa = PBXCopyFilesBuildPhase; 56 | buildActionMask = 2147483647; 57 | dstPath = ""; 58 | dstSubfolderSpec = 10; 59 | files = ( 60 | ); 61 | name = "Embed Frameworks"; 62 | runOnlyForDeploymentPostprocessing = 0; 63 | }; 64 | /* End PBXCopyFilesBuildPhase section */ 65 | 66 | /* Begin PBXFileReference section */ 67 | 1A11497118311D120015BDE2 /* TEAChartDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TEAChartDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 68 | 1A11497418311D120015BDE2 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 69 | 1A11497618311D120015BDE2 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 70 | 1A11497818311D120015BDE2 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 71 | 1A11497C18311D120015BDE2 /* TEAChartDemo-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "TEAChartDemo-Info.plist"; sourceTree = ""; }; 72 | 1A11497E18311D120015BDE2 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 73 | 1A11498018311D120015BDE2 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 74 | 1A11498218311D120015BDE2 /* TEAChartDemo-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "TEAChartDemo-Prefix.pch"; sourceTree = ""; }; 75 | 1A11498318311D120015BDE2 /* TEAAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TEAAppDelegate.h; sourceTree = ""; }; 76 | 1A11498418311D120015BDE2 /* TEAAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TEAAppDelegate.m; sourceTree = ""; }; 77 | 1A11498718311D120015BDE2 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 78 | 1A11498918311D120015BDE2 /* TEAViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TEAViewController.h; sourceTree = ""; }; 79 | 1A11498A18311D120015BDE2 /* TEAViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TEAViewController.m; sourceTree = ""; }; 80 | 1A11498C18311D120015BDE2 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 81 | 1A11499218311D120015BDE2 /* TEAChartDemoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TEAChartDemoTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 82 | 1A11499318311D120015BDE2 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; 83 | 1A11499B18311D120015BDE2 /* TEAChartDemoTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "TEAChartDemoTests-Info.plist"; sourceTree = ""; }; 84 | 1A11499D18311D120015BDE2 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 85 | 1A11499F18311D120015BDE2 /* TEAChartDemoTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TEAChartDemoTests.m; sourceTree = ""; }; 86 | 1A1149A918311DA10015BDE2 /* TEABarChart.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TEABarChart.h; path = TEAChart/TEABarChart.h; sourceTree = ""; }; 87 | 1A1149AA18311DA10015BDE2 /* TEABarChart.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TEABarChart.m; path = TEAChart/TEABarChart.m; sourceTree = ""; }; 88 | 1A1149AD183121CF0015BDE2 /* TEAChart.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = TEAChart.h; path = TEAChart/TEAChart.h; sourceTree = ""; }; 89 | 1A1149AE18312D610015BDE2 /* TEAContributionGraph.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TEAContributionGraph.h; path = TEAChart/TEAContributionGraph.h; sourceTree = ""; }; 90 | 1A1149AF18312D610015BDE2 /* TEAContributionGraph.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TEAContributionGraph.m; path = TEAChart/TEAContributionGraph.m; sourceTree = ""; }; 91 | 1A1149B1183134F40015BDE2 /* TEAClockChart.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TEAClockChart.h; path = TEAChart/TEAClockChart.h; sourceTree = ""; }; 92 | 1A1149B2183134F40015BDE2 /* TEAClockChart.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TEAClockChart.m; path = TEAChart/TEAClockChart.m; sourceTree = ""; }; 93 | 1A1149B418313ABB0015BDE2 /* TEATimeRange.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TEATimeRange.h; path = TEAChart/TEATimeRange.h; sourceTree = ""; }; 94 | 1A1149B518313ABB0015BDE2 /* TEATimeRange.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TEATimeRange.m; path = TEAChart/TEATimeRange.m; sourceTree = ""; }; 95 | 1A1DEC261BA4EC3100028BCF /* Launch Screen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = "Launch Screen.storyboard"; sourceTree = ""; }; 96 | 1AADE61E189B990A00EB7C2C /* NSDate+TEAExtensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSDate+TEAExtensions.h"; path = "TEAChart/NSDate+TEAExtensions.h"; sourceTree = ""; }; 97 | 1AADE61F189B990A00EB7C2C /* NSDate+TEAExtensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSDate+TEAExtensions.m"; path = "TEAChart/NSDate+TEAExtensions.m"; sourceTree = ""; }; 98 | CFC4CB301E3F11E1006DF0FE /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = TEAChart/Info.plist; sourceTree = ""; }; 99 | CFC4CB371E3F1217006DF0FE /* TEAChart.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = TEAChart.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 100 | /* End PBXFileReference section */ 101 | 102 | /* Begin PBXFrameworksBuildPhase section */ 103 | 1A11496E18311D120015BDE2 /* Frameworks */ = { 104 | isa = PBXFrameworksBuildPhase; 105 | buildActionMask = 2147483647; 106 | files = ( 107 | 1A11497718311D120015BDE2 /* CoreGraphics.framework in Frameworks */, 108 | 1A11497918311D120015BDE2 /* UIKit.framework in Frameworks */, 109 | 1A11497518311D120015BDE2 /* Foundation.framework in Frameworks */, 110 | ); 111 | runOnlyForDeploymentPostprocessing = 0; 112 | }; 113 | 1A11498F18311D120015BDE2 /* Frameworks */ = { 114 | isa = PBXFrameworksBuildPhase; 115 | buildActionMask = 2147483647; 116 | files = ( 117 | 1A11499418311D120015BDE2 /* XCTest.framework in Frameworks */, 118 | 1A11499618311D120015BDE2 /* UIKit.framework in Frameworks */, 119 | 1A11499518311D120015BDE2 /* Foundation.framework in Frameworks */, 120 | ); 121 | runOnlyForDeploymentPostprocessing = 0; 122 | }; 123 | CFC4CB331E3F1217006DF0FE /* Frameworks */ = { 124 | isa = PBXFrameworksBuildPhase; 125 | buildActionMask = 2147483647; 126 | files = ( 127 | ); 128 | runOnlyForDeploymentPostprocessing = 0; 129 | }; 130 | /* End PBXFrameworksBuildPhase section */ 131 | 132 | /* Begin PBXGroup section */ 133 | 1A11496818311D120015BDE2 = { 134 | isa = PBXGroup; 135 | children = ( 136 | 1A1149AC18311DA60015BDE2 /* TEAChart */, 137 | 1A11497A18311D120015BDE2 /* TEAChartDemo */, 138 | 1A11499918311D120015BDE2 /* TEAChartDemoTests */, 139 | 1A11497318311D120015BDE2 /* Frameworks */, 140 | 1A11497218311D120015BDE2 /* Products */, 141 | ); 142 | sourceTree = ""; 143 | }; 144 | 1A11497218311D120015BDE2 /* Products */ = { 145 | isa = PBXGroup; 146 | children = ( 147 | 1A11497118311D120015BDE2 /* TEAChartDemo.app */, 148 | 1A11499218311D120015BDE2 /* TEAChartDemoTests.xctest */, 149 | CFC4CB371E3F1217006DF0FE /* TEAChart.framework */, 150 | ); 151 | name = Products; 152 | sourceTree = ""; 153 | }; 154 | 1A11497318311D120015BDE2 /* Frameworks */ = { 155 | isa = PBXGroup; 156 | children = ( 157 | 1A11497418311D120015BDE2 /* Foundation.framework */, 158 | 1A11497618311D120015BDE2 /* CoreGraphics.framework */, 159 | 1A11497818311D120015BDE2 /* UIKit.framework */, 160 | 1A11499318311D120015BDE2 /* XCTest.framework */, 161 | ); 162 | name = Frameworks; 163 | sourceTree = ""; 164 | }; 165 | 1A11497A18311D120015BDE2 /* TEAChartDemo */ = { 166 | isa = PBXGroup; 167 | children = ( 168 | 1A11498318311D120015BDE2 /* TEAAppDelegate.h */, 169 | 1A11498418311D120015BDE2 /* TEAAppDelegate.m */, 170 | 1A11498618311D120015BDE2 /* Main.storyboard */, 171 | 1A1DEC261BA4EC3100028BCF /* Launch Screen.storyboard */, 172 | 1A11498918311D120015BDE2 /* TEAViewController.h */, 173 | 1A11498A18311D120015BDE2 /* TEAViewController.m */, 174 | 1A11498C18311D120015BDE2 /* Images.xcassets */, 175 | 1A11497B18311D120015BDE2 /* Supporting Files */, 176 | ); 177 | path = TEAChartDemo; 178 | sourceTree = ""; 179 | }; 180 | 1A11497B18311D120015BDE2 /* Supporting Files */ = { 181 | isa = PBXGroup; 182 | children = ( 183 | 1A11497C18311D120015BDE2 /* TEAChartDemo-Info.plist */, 184 | 1A11497D18311D120015BDE2 /* InfoPlist.strings */, 185 | 1A11498018311D120015BDE2 /* main.m */, 186 | 1A11498218311D120015BDE2 /* TEAChartDemo-Prefix.pch */, 187 | ); 188 | name = "Supporting Files"; 189 | sourceTree = ""; 190 | }; 191 | 1A11499918311D120015BDE2 /* TEAChartDemoTests */ = { 192 | isa = PBXGroup; 193 | children = ( 194 | 1A11499F18311D120015BDE2 /* TEAChartDemoTests.m */, 195 | 1A11499A18311D120015BDE2 /* Supporting Files */, 196 | ); 197 | path = TEAChartDemoTests; 198 | sourceTree = ""; 199 | }; 200 | 1A11499A18311D120015BDE2 /* Supporting Files */ = { 201 | isa = PBXGroup; 202 | children = ( 203 | 1A11499B18311D120015BDE2 /* TEAChartDemoTests-Info.plist */, 204 | 1A11499C18311D120015BDE2 /* InfoPlist.strings */, 205 | ); 206 | name = "Supporting Files"; 207 | sourceTree = ""; 208 | }; 209 | 1A1149AC18311DA60015BDE2 /* TEAChart */ = { 210 | isa = PBXGroup; 211 | children = ( 212 | CFC4CB2F1E3F0FD4006DF0FE /* Supporting Files */, 213 | 1A1149AD183121CF0015BDE2 /* TEAChart.h */, 214 | 1A1149A918311DA10015BDE2 /* TEABarChart.h */, 215 | 1A1149AA18311DA10015BDE2 /* TEABarChart.m */, 216 | 1A1149AE18312D610015BDE2 /* TEAContributionGraph.h */, 217 | 1A1149AF18312D610015BDE2 /* TEAContributionGraph.m */, 218 | 1A1149B1183134F40015BDE2 /* TEAClockChart.h */, 219 | 1A1149B2183134F40015BDE2 /* TEAClockChart.m */, 220 | 1A1149B418313ABB0015BDE2 /* TEATimeRange.h */, 221 | 1A1149B518313ABB0015BDE2 /* TEATimeRange.m */, 222 | 1AADE61E189B990A00EB7C2C /* NSDate+TEAExtensions.h */, 223 | 1AADE61F189B990A00EB7C2C /* NSDate+TEAExtensions.m */, 224 | ); 225 | name = TEAChart; 226 | sourceTree = ""; 227 | }; 228 | CFC4CB2F1E3F0FD4006DF0FE /* Supporting Files */ = { 229 | isa = PBXGroup; 230 | children = ( 231 | CFC4CB301E3F11E1006DF0FE /* Info.plist */, 232 | ); 233 | name = "Supporting Files"; 234 | sourceTree = ""; 235 | }; 236 | /* End PBXGroup section */ 237 | 238 | /* Begin PBXHeadersBuildPhase section */ 239 | CFC4CB341E3F1217006DF0FE /* Headers */ = { 240 | isa = PBXHeadersBuildPhase; 241 | buildActionMask = 2147483647; 242 | files = ( 243 | CFC4CB461E3F126C006DF0FE /* TEATimeRange.h in Headers */, 244 | CFC4CB421E3F126C006DF0FE /* TEAContributionGraph.h in Headers */, 245 | CFC4CB401E3F126C006DF0FE /* TEABarChart.h in Headers */, 246 | CFC4CB441E3F126C006DF0FE /* TEAClockChart.h in Headers */, 247 | CFC4CB3F1E3F126C006DF0FE /* TEAChart.h in Headers */, 248 | CFC4CB481E3F126C006DF0FE /* NSDate+TEAExtensions.h in Headers */, 249 | ); 250 | runOnlyForDeploymentPostprocessing = 0; 251 | }; 252 | /* End PBXHeadersBuildPhase section */ 253 | 254 | /* Begin PBXNativeTarget section */ 255 | 1A11497018311D120015BDE2 /* TEAChartDemo */ = { 256 | isa = PBXNativeTarget; 257 | buildConfigurationList = 1A1149A318311D120015BDE2 /* Build configuration list for PBXNativeTarget "TEAChartDemo" */; 258 | buildPhases = ( 259 | 1A11496D18311D120015BDE2 /* Sources */, 260 | 1A11496E18311D120015BDE2 /* Frameworks */, 261 | 1A11496F18311D120015BDE2 /* Resources */, 262 | CF18DF321E3F1ACC00D82E1C /* Embed Frameworks */, 263 | ); 264 | buildRules = ( 265 | ); 266 | dependencies = ( 267 | ); 268 | name = TEAChartDemo; 269 | productName = TEAChartDemo; 270 | productReference = 1A11497118311D120015BDE2 /* TEAChartDemo.app */; 271 | productType = "com.apple.product-type.application"; 272 | }; 273 | 1A11499118311D120015BDE2 /* TEAChartDemoTests */ = { 274 | isa = PBXNativeTarget; 275 | buildConfigurationList = 1A1149A618311D120015BDE2 /* Build configuration list for PBXNativeTarget "TEAChartDemoTests" */; 276 | buildPhases = ( 277 | 1A11498E18311D120015BDE2 /* Sources */, 278 | 1A11498F18311D120015BDE2 /* Frameworks */, 279 | 1A11499018311D120015BDE2 /* Resources */, 280 | ); 281 | buildRules = ( 282 | ); 283 | dependencies = ( 284 | 1A11499818311D120015BDE2 /* PBXTargetDependency */, 285 | ); 286 | name = TEAChartDemoTests; 287 | productName = TEAChartDemoTests; 288 | productReference = 1A11499218311D120015BDE2 /* TEAChartDemoTests.xctest */; 289 | productType = "com.apple.product-type.bundle.unit-test"; 290 | }; 291 | CFC4CB361E3F1217006DF0FE /* TEAChart */ = { 292 | isa = PBXNativeTarget; 293 | buildConfigurationList = CFC4CB3C1E3F1217006DF0FE /* Build configuration list for PBXNativeTarget "TEAChart" */; 294 | buildPhases = ( 295 | CFC4CB321E3F1217006DF0FE /* Sources */, 296 | CFC4CB331E3F1217006DF0FE /* Frameworks */, 297 | CFC4CB341E3F1217006DF0FE /* Headers */, 298 | CFC4CB351E3F1217006DF0FE /* Resources */, 299 | ); 300 | buildRules = ( 301 | ); 302 | dependencies = ( 303 | ); 304 | name = TEAChart; 305 | productName = TEAChart_iOS; 306 | productReference = CFC4CB371E3F1217006DF0FE /* TEAChart.framework */; 307 | productType = "com.apple.product-type.framework"; 308 | }; 309 | /* End PBXNativeTarget section */ 310 | 311 | /* Begin PBXProject section */ 312 | 1A11496918311D120015BDE2 /* Project object */ = { 313 | isa = PBXProject; 314 | attributes = { 315 | CLASSPREFIX = TEA; 316 | LastUpgradeCheck = 0800; 317 | ORGANIZATIONNAME = Xhacker; 318 | TargetAttributes = { 319 | 1A11497018311D120015BDE2 = { 320 | LastSwiftMigration = 0820; 321 | }; 322 | 1A11499118311D120015BDE2 = { 323 | TestTargetID = 1A11497018311D120015BDE2; 324 | }; 325 | CFC4CB361E3F1217006DF0FE = { 326 | CreatedOnToolsVersion = 8.2.1; 327 | LastSwiftMigration = 0820; 328 | ProvisioningStyle = Automatic; 329 | }; 330 | }; 331 | }; 332 | buildConfigurationList = 1A11496C18311D120015BDE2 /* Build configuration list for PBXProject "TEAChartDemo" */; 333 | compatibilityVersion = "Xcode 8.0"; 334 | developmentRegion = English; 335 | hasScannedForEncodings = 0; 336 | knownRegions = ( 337 | en, 338 | Base, 339 | ); 340 | mainGroup = 1A11496818311D120015BDE2; 341 | productRefGroup = 1A11497218311D120015BDE2 /* Products */; 342 | projectDirPath = ""; 343 | projectRoot = ""; 344 | targets = ( 345 | 1A11497018311D120015BDE2 /* TEAChartDemo */, 346 | 1A11499118311D120015BDE2 /* TEAChartDemoTests */, 347 | CFC4CB361E3F1217006DF0FE /* TEAChart */, 348 | ); 349 | }; 350 | /* End PBXProject section */ 351 | 352 | /* Begin PBXResourcesBuildPhase section */ 353 | 1A11496F18311D120015BDE2 /* Resources */ = { 354 | isa = PBXResourcesBuildPhase; 355 | buildActionMask = 2147483647; 356 | files = ( 357 | 1A11498D18311D120015BDE2 /* Images.xcassets in Resources */, 358 | 1A11497F18311D120015BDE2 /* InfoPlist.strings in Resources */, 359 | 1A1DEC271BA4EC3100028BCF /* Launch Screen.storyboard in Resources */, 360 | 1A11498818311D120015BDE2 /* Main.storyboard in Resources */, 361 | ); 362 | runOnlyForDeploymentPostprocessing = 0; 363 | }; 364 | 1A11499018311D120015BDE2 /* Resources */ = { 365 | isa = PBXResourcesBuildPhase; 366 | buildActionMask = 2147483647; 367 | files = ( 368 | 1A11499E18311D120015BDE2 /* InfoPlist.strings in Resources */, 369 | ); 370 | runOnlyForDeploymentPostprocessing = 0; 371 | }; 372 | CFC4CB351E3F1217006DF0FE /* Resources */ = { 373 | isa = PBXResourcesBuildPhase; 374 | buildActionMask = 2147483647; 375 | files = ( 376 | ); 377 | runOnlyForDeploymentPostprocessing = 0; 378 | }; 379 | /* End PBXResourcesBuildPhase section */ 380 | 381 | /* Begin PBXSourcesBuildPhase section */ 382 | 1A11496D18311D120015BDE2 /* Sources */ = { 383 | isa = PBXSourcesBuildPhase; 384 | buildActionMask = 2147483647; 385 | files = ( 386 | 1AADE620189B990A00EB7C2C /* NSDate+TEAExtensions.m in Sources */, 387 | 1A11498B18311D120015BDE2 /* TEAViewController.m in Sources */, 388 | 1A1149AB18311DA10015BDE2 /* TEABarChart.m in Sources */, 389 | 1A11498118311D120015BDE2 /* main.m in Sources */, 390 | 1A11498518311D120015BDE2 /* TEAAppDelegate.m in Sources */, 391 | 1A1149B618313ABB0015BDE2 /* TEATimeRange.m in Sources */, 392 | 1A1149B3183134F40015BDE2 /* TEAClockChart.m in Sources */, 393 | 1A1149B018312D610015BDE2 /* TEAContributionGraph.m in Sources */, 394 | ); 395 | runOnlyForDeploymentPostprocessing = 0; 396 | }; 397 | 1A11498E18311D120015BDE2 /* Sources */ = { 398 | isa = PBXSourcesBuildPhase; 399 | buildActionMask = 2147483647; 400 | files = ( 401 | 1A1149A018311D120015BDE2 /* TEAChartDemoTests.m in Sources */, 402 | ); 403 | runOnlyForDeploymentPostprocessing = 0; 404 | }; 405 | CFC4CB321E3F1217006DF0FE /* Sources */ = { 406 | isa = PBXSourcesBuildPhase; 407 | buildActionMask = 2147483647; 408 | files = ( 409 | CFC4CB411E3F126C006DF0FE /* TEABarChart.m in Sources */, 410 | CFC4CB451E3F126C006DF0FE /* TEAClockChart.m in Sources */, 411 | CFC4CB431E3F126C006DF0FE /* TEAContributionGraph.m in Sources */, 412 | CFC4CB471E3F126C006DF0FE /* TEATimeRange.m in Sources */, 413 | CFC4CB491E3F126C006DF0FE /* NSDate+TEAExtensions.m in Sources */, 414 | ); 415 | runOnlyForDeploymentPostprocessing = 0; 416 | }; 417 | /* End PBXSourcesBuildPhase section */ 418 | 419 | /* Begin PBXTargetDependency section */ 420 | 1A11499818311D120015BDE2 /* PBXTargetDependency */ = { 421 | isa = PBXTargetDependency; 422 | target = 1A11497018311D120015BDE2 /* TEAChartDemo */; 423 | targetProxy = 1A11499718311D120015BDE2 /* PBXContainerItemProxy */; 424 | }; 425 | /* End PBXTargetDependency section */ 426 | 427 | /* Begin PBXVariantGroup section */ 428 | 1A11497D18311D120015BDE2 /* InfoPlist.strings */ = { 429 | isa = PBXVariantGroup; 430 | children = ( 431 | 1A11497E18311D120015BDE2 /* en */, 432 | ); 433 | name = InfoPlist.strings; 434 | sourceTree = ""; 435 | }; 436 | 1A11498618311D120015BDE2 /* Main.storyboard */ = { 437 | isa = PBXVariantGroup; 438 | children = ( 439 | 1A11498718311D120015BDE2 /* Base */, 440 | ); 441 | name = Main.storyboard; 442 | sourceTree = ""; 443 | }; 444 | 1A11499C18311D120015BDE2 /* InfoPlist.strings */ = { 445 | isa = PBXVariantGroup; 446 | children = ( 447 | 1A11499D18311D120015BDE2 /* en */, 448 | ); 449 | name = InfoPlist.strings; 450 | sourceTree = ""; 451 | }; 452 | /* End PBXVariantGroup section */ 453 | 454 | /* Begin XCBuildConfiguration section */ 455 | 1A1149A118311D120015BDE2 /* Debug */ = { 456 | isa = XCBuildConfiguration; 457 | buildSettings = { 458 | ALWAYS_SEARCH_USER_PATHS = NO; 459 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 460 | CLANG_CXX_LIBRARY = "libc++"; 461 | CLANG_ENABLE_MODULES = YES; 462 | CLANG_ENABLE_OBJC_ARC = YES; 463 | CLANG_WARN_BOOL_CONVERSION = YES; 464 | CLANG_WARN_CONSTANT_CONVERSION = YES; 465 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 466 | CLANG_WARN_EMPTY_BODY = YES; 467 | CLANG_WARN_ENUM_CONVERSION = YES; 468 | CLANG_WARN_INFINITE_RECURSION = YES; 469 | CLANG_WARN_INT_CONVERSION = YES; 470 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 471 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 472 | CLANG_WARN_UNREACHABLE_CODE = YES; 473 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 474 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 475 | COPY_PHASE_STRIP = NO; 476 | ENABLE_STRICT_OBJC_MSGSEND = YES; 477 | ENABLE_TESTABILITY = YES; 478 | GCC_C_LANGUAGE_STANDARD = gnu99; 479 | GCC_DYNAMIC_NO_PIC = NO; 480 | GCC_NO_COMMON_BLOCKS = YES; 481 | GCC_OPTIMIZATION_LEVEL = 0; 482 | GCC_PREPROCESSOR_DEFINITIONS = ( 483 | "DEBUG=1", 484 | "$(inherited)", 485 | ); 486 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 487 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 488 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 489 | GCC_WARN_UNDECLARED_SELECTOR = YES; 490 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 491 | GCC_WARN_UNUSED_FUNCTION = YES; 492 | GCC_WARN_UNUSED_VARIABLE = YES; 493 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 494 | ONLY_ACTIVE_ARCH = YES; 495 | SDKROOT = iphoneos; 496 | }; 497 | name = Debug; 498 | }; 499 | 1A1149A218311D120015BDE2 /* Release */ = { 500 | isa = XCBuildConfiguration; 501 | buildSettings = { 502 | ALWAYS_SEARCH_USER_PATHS = NO; 503 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 504 | CLANG_CXX_LIBRARY = "libc++"; 505 | CLANG_ENABLE_MODULES = YES; 506 | CLANG_ENABLE_OBJC_ARC = YES; 507 | CLANG_WARN_BOOL_CONVERSION = YES; 508 | CLANG_WARN_CONSTANT_CONVERSION = YES; 509 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 510 | CLANG_WARN_EMPTY_BODY = YES; 511 | CLANG_WARN_ENUM_CONVERSION = YES; 512 | CLANG_WARN_INFINITE_RECURSION = YES; 513 | CLANG_WARN_INT_CONVERSION = YES; 514 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 515 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 516 | CLANG_WARN_UNREACHABLE_CODE = YES; 517 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 518 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 519 | COPY_PHASE_STRIP = YES; 520 | ENABLE_NS_ASSERTIONS = NO; 521 | ENABLE_STRICT_OBJC_MSGSEND = YES; 522 | GCC_C_LANGUAGE_STANDARD = gnu99; 523 | GCC_NO_COMMON_BLOCKS = YES; 524 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 525 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 526 | GCC_WARN_UNDECLARED_SELECTOR = YES; 527 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 528 | GCC_WARN_UNUSED_FUNCTION = YES; 529 | GCC_WARN_UNUSED_VARIABLE = YES; 530 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 531 | SDKROOT = iphoneos; 532 | VALIDATE_PRODUCT = YES; 533 | }; 534 | name = Release; 535 | }; 536 | 1A1149A418311D120015BDE2 /* Debug */ = { 537 | isa = XCBuildConfiguration; 538 | buildSettings = { 539 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 540 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 541 | CLANG_ENABLE_MODULES = YES; 542 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 543 | GCC_PREFIX_HEADER = "TEAChartDemo/TEAChartDemo-Prefix.pch"; 544 | INFOPLIST_FILE = "TEAChartDemo/TEAChartDemo-Info.plist"; 545 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 546 | PRODUCT_BUNDLE_IDENTIFIER = "com.teawhen.${PRODUCT_NAME:rfc1034identifier}"; 547 | PRODUCT_NAME = "$(TARGET_NAME)"; 548 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 549 | SWIFT_VERSION = 3.0; 550 | WRAPPER_EXTENSION = app; 551 | }; 552 | name = Debug; 553 | }; 554 | 1A1149A518311D120015BDE2 /* Release */ = { 555 | isa = XCBuildConfiguration; 556 | buildSettings = { 557 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 558 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 559 | CLANG_ENABLE_MODULES = YES; 560 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 561 | GCC_PREFIX_HEADER = "TEAChartDemo/TEAChartDemo-Prefix.pch"; 562 | INFOPLIST_FILE = "TEAChartDemo/TEAChartDemo-Info.plist"; 563 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 564 | PRODUCT_BUNDLE_IDENTIFIER = "com.teawhen.${PRODUCT_NAME:rfc1034identifier}"; 565 | PRODUCT_NAME = "$(TARGET_NAME)"; 566 | SWIFT_VERSION = 3.0; 567 | WRAPPER_EXTENSION = app; 568 | }; 569 | name = Release; 570 | }; 571 | 1A1149A718311D120015BDE2 /* Debug */ = { 572 | isa = XCBuildConfiguration; 573 | buildSettings = { 574 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/TEAChartDemo.app/TEAChartDemo"; 575 | FRAMEWORK_SEARCH_PATHS = ( 576 | "$(SDKROOT)/Developer/Library/Frameworks", 577 | "$(inherited)", 578 | "$(DEVELOPER_FRAMEWORKS_DIR)", 579 | ); 580 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 581 | GCC_PREFIX_HEADER = "TEAChartDemo/TEAChartDemo-Prefix.pch"; 582 | GCC_PREPROCESSOR_DEFINITIONS = ( 583 | "DEBUG=1", 584 | "$(inherited)", 585 | ); 586 | INFOPLIST_FILE = "TEAChartDemoTests/TEAChartDemoTests-Info.plist"; 587 | PRODUCT_BUNDLE_IDENTIFIER = "com.teawhen.${PRODUCT_NAME:rfc1034identifier}"; 588 | PRODUCT_NAME = "$(TARGET_NAME)"; 589 | TEST_HOST = "$(BUNDLE_LOADER)"; 590 | WRAPPER_EXTENSION = xctest; 591 | }; 592 | name = Debug; 593 | }; 594 | 1A1149A818311D120015BDE2 /* Release */ = { 595 | isa = XCBuildConfiguration; 596 | buildSettings = { 597 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/TEAChartDemo.app/TEAChartDemo"; 598 | FRAMEWORK_SEARCH_PATHS = ( 599 | "$(SDKROOT)/Developer/Library/Frameworks", 600 | "$(inherited)", 601 | "$(DEVELOPER_FRAMEWORKS_DIR)", 602 | ); 603 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 604 | GCC_PREFIX_HEADER = "TEAChartDemo/TEAChartDemo-Prefix.pch"; 605 | INFOPLIST_FILE = "TEAChartDemoTests/TEAChartDemoTests-Info.plist"; 606 | PRODUCT_BUNDLE_IDENTIFIER = "com.teawhen.${PRODUCT_NAME:rfc1034identifier}"; 607 | PRODUCT_NAME = "$(TARGET_NAME)"; 608 | TEST_HOST = "$(BUNDLE_LOADER)"; 609 | WRAPPER_EXTENSION = xctest; 610 | }; 611 | name = Release; 612 | }; 613 | CFC4CB3D1E3F1217006DF0FE /* Debug */ = { 614 | isa = XCBuildConfiguration; 615 | buildSettings = { 616 | CLANG_ANALYZER_NONNULL = YES; 617 | CLANG_ENABLE_MODULES = YES; 618 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 619 | CODE_SIGN_IDENTITY = ""; 620 | CURRENT_PROJECT_VERSION = 1; 621 | DEBUG_INFORMATION_FORMAT = dwarf; 622 | DEFINES_MODULE = YES; 623 | DYLIB_COMPATIBILITY_VERSION = 1; 624 | DYLIB_CURRENT_VERSION = 1; 625 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 626 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 627 | INFOPLIST_FILE = "$(SRCROOT)/TEAChart/Info.plist"; 628 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 629 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 630 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 631 | PRODUCT_BUNDLE_IDENTIFIER = com.teawhen.TEAChart; 632 | PRODUCT_NAME = "${TARGET_NAME}"; 633 | SKIP_INSTALL = YES; 634 | TARGETED_DEVICE_FAMILY = "1,2"; 635 | VERSIONING_SYSTEM = "apple-generic"; 636 | VERSION_INFO_PREFIX = ""; 637 | }; 638 | name = Debug; 639 | }; 640 | CFC4CB3E1E3F1217006DF0FE /* Release */ = { 641 | isa = XCBuildConfiguration; 642 | buildSettings = { 643 | CLANG_ANALYZER_NONNULL = YES; 644 | CLANG_ENABLE_MODULES = YES; 645 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 646 | CODE_SIGN_IDENTITY = ""; 647 | COPY_PHASE_STRIP = NO; 648 | CURRENT_PROJECT_VERSION = 1; 649 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 650 | DEFINES_MODULE = YES; 651 | DYLIB_COMPATIBILITY_VERSION = 1; 652 | DYLIB_CURRENT_VERSION = 1; 653 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 654 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 655 | INFOPLIST_FILE = "$(SRCROOT)/TEAChart/Info.plist"; 656 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 657 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 658 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 659 | PRODUCT_BUNDLE_IDENTIFIER = com.teawhen.TEAChart; 660 | PRODUCT_NAME = "${TARGET_NAME}"; 661 | SKIP_INSTALL = YES; 662 | TARGETED_DEVICE_FAMILY = "1,2"; 663 | VERSIONING_SYSTEM = "apple-generic"; 664 | VERSION_INFO_PREFIX = ""; 665 | }; 666 | name = Release; 667 | }; 668 | /* End XCBuildConfiguration section */ 669 | 670 | /* Begin XCConfigurationList section */ 671 | 1A11496C18311D120015BDE2 /* Build configuration list for PBXProject "TEAChartDemo" */ = { 672 | isa = XCConfigurationList; 673 | buildConfigurations = ( 674 | 1A1149A118311D120015BDE2 /* Debug */, 675 | 1A1149A218311D120015BDE2 /* Release */, 676 | ); 677 | defaultConfigurationIsVisible = 0; 678 | defaultConfigurationName = Release; 679 | }; 680 | 1A1149A318311D120015BDE2 /* Build configuration list for PBXNativeTarget "TEAChartDemo" */ = { 681 | isa = XCConfigurationList; 682 | buildConfigurations = ( 683 | 1A1149A418311D120015BDE2 /* Debug */, 684 | 1A1149A518311D120015BDE2 /* Release */, 685 | ); 686 | defaultConfigurationIsVisible = 0; 687 | defaultConfigurationName = Release; 688 | }; 689 | 1A1149A618311D120015BDE2 /* Build configuration list for PBXNativeTarget "TEAChartDemoTests" */ = { 690 | isa = XCConfigurationList; 691 | buildConfigurations = ( 692 | 1A1149A718311D120015BDE2 /* Debug */, 693 | 1A1149A818311D120015BDE2 /* Release */, 694 | ); 695 | defaultConfigurationIsVisible = 0; 696 | defaultConfigurationName = Release; 697 | }; 698 | CFC4CB3C1E3F1217006DF0FE /* Build configuration list for PBXNativeTarget "TEAChart" */ = { 699 | isa = XCConfigurationList; 700 | buildConfigurations = ( 701 | CFC4CB3D1E3F1217006DF0FE /* Debug */, 702 | CFC4CB3E1E3F1217006DF0FE /* Release */, 703 | ); 704 | defaultConfigurationIsVisible = 0; 705 | defaultConfigurationName = Release; 706 | }; 707 | /* End XCConfigurationList section */ 708 | }; 709 | rootObject = 1A11496918311D120015BDE2 /* Project object */; 710 | } 711 | -------------------------------------------------------------------------------- /TEAChartDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /TEAChartDemo.xcodeproj/xcshareddata/xcschemes/TEAChart.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 70 | 71 | 72 | 73 | 75 | 76 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /TEAChartDemo.xcodeproj/xcshareddata/xcschemes/TEAChartDemo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 64 | 66 | 72 | 73 | 74 | 75 | 76 | 77 | 83 | 85 | 91 | 92 | 93 | 94 | 96 | 97 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /TEAChartDemo/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /TEAChartDemo/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /TEAChartDemo/Images.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "orientation" : "portrait", 5 | "idiom" : "iphone", 6 | "extent" : "full-screen", 7 | "minimum-system-version" : "7.0", 8 | "scale" : "2x" 9 | }, 10 | { 11 | "orientation" : "portrait", 12 | "idiom" : "iphone", 13 | "subtype" : "retina4", 14 | "extent" : "full-screen", 15 | "minimum-system-version" : "7.0", 16 | "scale" : "2x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /TEAChartDemo/Launch Screen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 27 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /TEAChartDemo/TEAAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // TEAAppDelegate.h 3 | // TEAChartDemo 4 | // 5 | // Created by Xhacker on 11/11/2013. 6 | // Copyright (c) 2013 Xhacker. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TEAAppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /TEAChartDemo/TEAAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // TEAAppDelegate.m 3 | // TEAChartDemo 4 | // 5 | // Created by Xhacker on 11/11/2013. 6 | // Copyright (c) 2013 Xhacker. All rights reserved. 7 | // 8 | 9 | #import "TEAAppDelegate.h" 10 | 11 | @implementation TEAAppDelegate 12 | 13 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 14 | { 15 | return YES; 16 | } 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /TEAChartDemo/TEAChartDemo-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UILaunchStoryboardName 28 | Launch Screen 29 | UIMainStoryboardFile 30 | Main 31 | UIRequiredDeviceCapabilities 32 | 33 | armv7 34 | 35 | UISupportedInterfaceOrientations 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationLandscapeLeft 39 | UIInterfaceOrientationLandscapeRight 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /TEAChartDemo/TEAChartDemo-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #import 8 | 9 | #ifndef __IPHONE_5_0 10 | #warning "This project uses features only available in iOS SDK 5.0 and later." 11 | #endif 12 | 13 | #ifdef __OBJC__ 14 | #import 15 | #import 16 | #endif 17 | -------------------------------------------------------------------------------- /TEAChartDemo/TEAViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // TEAViewController.h 3 | // TEAChartDemo 4 | // 5 | // Created by Xhacker on 11/11/2013. 6 | // Copyright (c) 2013 Xhacker. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "TEAChart.h" 11 | 12 | @interface TEAViewController : UIViewController 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /TEAChartDemo/TEAViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // TEAViewController.m 3 | // TEAChartDemo 4 | // 5 | // Created by Xhacker on 11/11/2013. 6 | // Copyright (c) 2013 Xhacker. All rights reserved. 7 | // 8 | 9 | #import "TEAViewController.h" 10 | 11 | @interface TEAViewController () 12 | 13 | @property (weak, nonatomic) IBOutlet TEABarChart *barChart; 14 | @property (weak, nonatomic) IBOutlet TEAContributionGraph *contributionGraph; 15 | @property (weak, nonatomic) IBOutlet TEAClockChart *clockChart; 16 | 17 | @end 18 | 19 | @implementation TEAViewController 20 | 21 | - (void)viewDidLoad 22 | { 23 | [super viewDidLoad]; 24 | 25 | // Bar chart, the Storyboard way 26 | self.barChart.data = @[@3, @1, @4, @1, @5, @9, @2, @6, @5, @3]; 27 | self.barChart.barSpacing = 10; 28 | self.barChart.barColors = @[[UIColor orangeColor], [UIColor yellowColor], [UIColor greenColor], [UIColor blueColor]]; 29 | 30 | // Bar chart, the code way 31 | TEABarChart *secondBarChart = [[TEABarChart alloc] initWithFrame:CGRectMake(35, 180, 100, 56)]; 32 | secondBarChart.data = @[@2, @7, @1, @8, @2, @8]; 33 | secondBarChart.xLabels = @[@"A", @"B", @"C", @"D", @"E", @"F"]; 34 | [self.view addSubview:secondBarChart]; 35 | 36 | // Contribution graph, the code way 37 | TEAContributionGraph *secondContributionGraph = [[TEAContributionGraph alloc] initWithFrame:CGRectMake(75, 430, 140, 140)]; 38 | [self.view addSubview:secondContributionGraph]; 39 | secondContributionGraph.showDayNumbers = YES; 40 | secondContributionGraph.delegate = self; 41 | 42 | // Clock chart 43 | self.clockChart.data = @[ 44 | [TEATimeRange timeRangeWithStart:[NSDate date] end:[NSDate dateWithTimeIntervalSinceNow:3600]], 45 | [TEATimeRange timeRangeWithStart:[NSDate date] end:[NSDate dateWithTimeIntervalSinceNow:7200]], 46 | [TEATimeRange timeRangeWithStart:[NSDate date] end:[NSDate dateWithTimeIntervalSinceNow:10800]], 47 | ]; 48 | } 49 | 50 | #pragma mark - TEAContributionGraphDataSource Methods 51 | 52 | - (void)dateTapped:(NSDictionary *)dict 53 | { 54 | NSLog(@"date: %@ -- value: %@", dict[@"date"], dict[@"value"]); 55 | } 56 | 57 | - (NSDate *)monthForGraph 58 | { 59 | return [NSDate date]; 60 | } 61 | 62 | - (NSInteger)valueForDay:(NSUInteger)day 63 | { 64 | return day % 6; 65 | } 66 | 67 | @end 68 | -------------------------------------------------------------------------------- /TEAChartDemo/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /TEAChartDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // TEAChartDemo 4 | // 5 | // Created by Xhacker on 11/11/2013. 6 | // Copyright (c) 2013 Xhacker. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "TEAAppDelegate.h" 12 | 13 | int main(int argc, char * argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([TEAAppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /TEAChartDemoTests/TEAChartDemoTests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /TEAChartDemoTests/TEAChartDemoTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // TEAChartDemoTests.m 3 | // TEAChartDemoTests 4 | // 5 | // Created by Xhacker on 11/11/2013. 6 | // Copyright (c) 2013 Xhacker. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TEAChartDemoTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation TEAChartDemoTests 16 | 17 | - (void)setUp 18 | { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown 24 | { 25 | // Put teardown code here. This method is called after the invocation of each test method in the class. 26 | [super tearDown]; 27 | } 28 | 29 | - (void)testExample 30 | { 31 | XCTAssertEqual(1 + 1, 2); 32 | } 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /TEAChartDemoTests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | --------------------------------------------------------------------------------