├── .gitignore
├── Images
├── app_store_download_button.gif
├── app_store_download_button_in_motion.gif
├── app_store_download_finish.png
├── app_store_download_middle.png
├── app_store_download_start.png
├── dimming_view.gif
├── progress_view.gif
├── rounded_rect.png
├── shapes_logo.png
└── voice_memos_record_button.gif
├── LICENSE
├── README.md
├── Shapes.podspec
├── Shapes
├── CAShapeLayer+UIBezierPath.h
├── CAShapeLayer+UIBezierPath.m
├── CATransaction+AnimateWithDuration.h
├── CATransaction+AnimateWithDuration.m
├── DTAnimatableShapeLayer.h
├── DTAnimatableShapeLayer.m
├── DTDimmingView.h
├── DTDimmingView.m
├── DTGraphicsConverter.h
├── DTGraphicsConverter.m
├── DTProgressView.h
├── DTProgressView.m
├── DTShapeButton.h
├── DTShapeButton.m
├── DTShapeView.h
├── DTShapeView.m
└── Shapes.h
└── ShapesExample
├── Rakefile
├── ShapeKitExample
├── AppDelegate.h
├── AppDelegate.m
├── Controllers
│ ├── DimmingViewController.h
│ ├── DimmingViewController.m
│ ├── DownloadButtonViewController.h
│ ├── DownloadButtonViewController.m
│ ├── ProgressViewController.h
│ ├── ProgressViewController.m
│ ├── VoiceMemosRecordButtonViewController.h
│ ├── VoiceMemosRecordButtonViewController.m
│ └── cat_selfie.png
├── Controls
│ ├── DimmableShapeButton.h
│ ├── DimmableShapeButton.m
│ ├── HighlightableShapeButton.h
│ └── HighlightableShapeButton.m
├── Images.xcassets
│ ├── AppIcon.appiconset
│ │ └── Contents.json
│ ├── LaunchImage.launchimage
│ │ └── Contents.json
│ └── cat_selfie.imageset
│ │ ├── Contents.json
│ │ └── cat_selfie.png
├── ShapesExample-Info.plist
├── ShapesExample-Prefix.pch
├── ShapesExample.storyboard
├── en.lproj
│ └── InfoPlist.strings
└── main.m
├── ShapeKitExampleTests
├── ShapesExampleTests-Info.plist
├── Specs
│ └── ShapedView
│ │ ├── ShapedViewGettersAndSettersTestCase.m
│ │ └── ShapedViewPathTestCase.m
└── en.lproj
│ └── InfoPlist.strings
└── ShapesExample.xcodeproj
├── project.pbxproj
└── xcshareddata
└── xcschemes
├── ShapesExample.xcscheme
└── ShapesTests.xcscheme
/.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 | *.moved-aside
14 | DerivedData
15 | .idea/
16 | *.hmap
17 | *.xccheckout
18 |
19 | #CocoaPods
20 | Pods
21 | Podfile.lock
22 | *.xcworkspace
--------------------------------------------------------------------------------
/Images/app_store_download_button.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MLSDev/Shapes/35d19f56082a2cde54585b14671af6f4d58ba28e/Images/app_store_download_button.gif
--------------------------------------------------------------------------------
/Images/app_store_download_button_in_motion.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MLSDev/Shapes/35d19f56082a2cde54585b14671af6f4d58ba28e/Images/app_store_download_button_in_motion.gif
--------------------------------------------------------------------------------
/Images/app_store_download_finish.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MLSDev/Shapes/35d19f56082a2cde54585b14671af6f4d58ba28e/Images/app_store_download_finish.png
--------------------------------------------------------------------------------
/Images/app_store_download_middle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MLSDev/Shapes/35d19f56082a2cde54585b14671af6f4d58ba28e/Images/app_store_download_middle.png
--------------------------------------------------------------------------------
/Images/app_store_download_start.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MLSDev/Shapes/35d19f56082a2cde54585b14671af6f4d58ba28e/Images/app_store_download_start.png
--------------------------------------------------------------------------------
/Images/dimming_view.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MLSDev/Shapes/35d19f56082a2cde54585b14671af6f4d58ba28e/Images/dimming_view.gif
--------------------------------------------------------------------------------
/Images/progress_view.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MLSDev/Shapes/35d19f56082a2cde54585b14671af6f4d58ba28e/Images/progress_view.gif
--------------------------------------------------------------------------------
/Images/rounded_rect.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MLSDev/Shapes/35d19f56082a2cde54585b14671af6f4d58ba28e/Images/rounded_rect.png
--------------------------------------------------------------------------------
/Images/shapes_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MLSDev/Shapes/35d19f56082a2cde54585b14671af6f4d58ba28e/Images/shapes_logo.png
--------------------------------------------------------------------------------
/Images/voice_memos_record_button.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MLSDev/Shapes/35d19f56082a2cde54585b14671af6f4d58ba28e/Images/voice_memos_record_button.gif
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Denys Telezhkin
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, 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,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 | 
3 | 
4 |
5 | 
6 |
7 | Shapes is a set of wrappers around CAShapeLayer and UIBezierPath, that allows drawing and animating geometrically shaped views on iOS. Read more about it on the blog: http://mlsdev.com/blog/23
8 |
9 | 
10 | 
11 |
12 | 
13 | 
14 |
15 | ### Shaped views
16 |
17 | `DTShapeView` is a UIView subclass, that is backed by CAShapeLayer instead of CALayer. It provides API for changing CAShapeLayer path, fill and stroke colors and other layer properties, basically allowing UIView to behave like geometric shape.
18 |
19 | All `DTShapeView` properties are automatically converted to CAShapeLayer properties or use CAShapeLayer properties directly. You can use whatever style you like, but we recommend using UIBezierPath and `DTShapeView` properties, because this allows you to completely bypass CoreFoundation objects. It also allows you to use CoreGraphics API instead of QuartzCore.
20 |
21 | `DTShapeView` fully supports both explicit and implicit animation and hit testing inside it's path.
22 |
23 | ### Progress views
24 |
25 | `DTProgressView` is a `DTShapeView` subclass, that allow animating progress views of any shape. `DTProgressView` uses `DTShapeView` path as track.
26 |
27 | By default, `DTProgressView` fills entire view bounds, filling view from left to right. And all you need to create a progress view, is drop it onto your view, set strokeColor and your progress view is ready!
28 |
29 | ```objective-c
30 | self.simpleProgressView.strokeColor = [UIColor greenColor];
31 | ```
32 |
33 | Whenever your progress changes, simply call
34 |
35 | ```objective-c
36 | [self.simpleProgressView setProgress:progress animated:YES];
37 | ```
38 |
39 | And progress change will be animated. `DTProgressView` supports any geometric shape UIBezierPath can define, and allows customizing animation duration and animation function.
40 |
41 | ### Dimming views
42 |
43 | `DTDimmingView` allows dimming part of the view, by "cutting" visible path from it. By default, dimming path contains entire UIView bounds. Create UIBezierPath, that describes, which part of the view should be visible, and set it on `DTDimmingView` instance to allow content to be seen.
44 |
45 | ```objective-c
46 | UIBezierPath * roundedPath = [UIBezierPath bezierPathWithOvalInRect:CGRectInset(self.view.bounds, 100, 100)];
47 | self.dimmingDynamicView.visiblePath = roundedPath;
48 | ```
49 |
50 | ### Shaped buttons
51 |
52 | `DTShapeButton` is a UIButton, that has `DTShapedView` added as a subview. As a result, it allows manipulating UIButton shape and visual appearance by changing `DTShapedView` properties. By default, button shape is a rectangle with UIButton bounds set as it's frame. For example, drawing initial state of AppStore download button looks like this:
53 |
54 | ```objective-c
55 | self.downloadButton.shape.path = [UIBezierPath bezierPathWithRoundedRect:self.downloadButton.bounds cornerRadius:5.0f];
56 | ```
57 |
58 | To find out more about how animating between shapes works, read [Animatable buttons with Shapes tutorial](https://github.com/DenHeadless/Shapes/wiki/Building-animatable-buttons-with-Shapes)
59 |
60 | ## Examples
61 |
62 | Take a look at example project, provided in ShapesExample folder.
63 |
64 | ## Requirements
65 |
66 | * iOS 7,8,9
67 | * ARC
68 | * XCode 7 and iOS 9 SDK
69 |
70 | ## Installation
71 |
72 | Using CocoaPods:
73 | ```bash
74 | pod 'Shapes', '~> 1.0.2'
75 | ```
76 |
77 | ## About MLSDev
78 |
79 | [
][mlsdev]
80 |
81 | Development Standards are maintained by MLSDev, Inc. We specialize in providing all-in-one solution in mobile and web development. Our team follows Lean principles and works according to agile methodologies to deliver the best results reducing the budget for development and its timeline.
82 |
83 | Find out more [here][mlsdev] and don't hesitate to [contact us][contact]!
84 |
85 | [mlsdev]: http://mlsdev.com
86 | [contact]: http://mlsdev.com/contact_us
87 |
--------------------------------------------------------------------------------
/Shapes.podspec:
--------------------------------------------------------------------------------
1 |
2 | Pod::Spec.new do |s|
3 | s.name = "Shapes"
4 | s.version = "1.0.2"
5 | s.summary = "Framework for drawing and animating shaped views on iOS"
6 |
7 | s.homepage = "https://github.com/DenHeadless/Shapes"
8 | s.screenshots = "https://github.com/DenHeadless/Shapes/raw/master/Images/progress_view.gif", "https://github.com/DenHeadless/Shapes/raw/master/Images/dimming_view.gif","https://github.com/DenHeadless/Shapes/raw/master/Images/app_store_download_button.gif", "https://github.com/DenHeadless/Shapes/raw/master/Images/voice_memos_record_button.gif"
9 |
10 | s.license = "MIT"
11 |
12 | s.author = { "Denys Telezhkin" => "denys.telezhkin@yandex.ru" }
13 | s.social_media_url = 'https://twitter.com/DTCoder'
14 |
15 | s.platform = :ios, "7.0"
16 | s.source = { :git => "https://github.com/DenHeadless/Shapes.git", :tag => s.version.to_s }
17 |
18 | s.source_files = "Shapes"
19 |
20 | s.frameworks = "UIKit", "Foundation", "QuartzCore"
21 | s.requires_arc = true
22 | end
23 |
--------------------------------------------------------------------------------
/Shapes/CAShapeLayer+UIBezierPath.h:
--------------------------------------------------------------------------------
1 | //
2 | // CAShapeLayer+UIBezierPath.h
3 | // Shapes
4 | //
5 | // Created by Denys Telezhkin on 19.08.14.
6 | // Copyright (c) 2014 Denys Telezhkin. All rights reserved.
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 |
26 | #import
27 |
28 | #if __has_feature(nullability) // Xcode 6.3+
29 | #pragma clang assume_nonnull begin
30 | #else
31 | #define nullable
32 | #define __nullable
33 | #endif
34 |
35 | /**
36 | Category on `CAShapeLayer`, that allows setting and getting UIBezierPath on CAShapeLayer.
37 | */
38 | @interface CAShapeLayer (UIBezierPath)
39 |
40 | /**
41 | Update CAShapeLayer with UIBezierPath.
42 | */
43 | - (void)dt_updateWithBezierPath:(UIBezierPath *)path;
44 |
45 | /**
46 | Get UIBezierPath object, constructed from CAShapeLayer.
47 | */
48 | - (UIBezierPath*)dt_bezierPath;
49 |
50 | @end
51 |
52 | #if __has_feature(nullability)
53 | #pragma clang assume_nonnull end
54 | #endif
--------------------------------------------------------------------------------
/Shapes/CAShapeLayer+UIBezierPath.m:
--------------------------------------------------------------------------------
1 | //
2 | // CAShapeLayer+UIBezierPath.m
3 | // Shapes
4 | //
5 | // Created by Denys Telezhkin on 19.08.14.
6 | // Copyright (c) 2014 Denys Telezhkin. All rights reserved.
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 |
26 | #import "CAShapeLayer+UIBezierPath.h"
27 | #import "DTGraphicsConverter.h"
28 |
29 | @implementation CAShapeLayer (UIBezierPath)
30 |
31 | -(void)dt_updateWithBezierPath:(UIBezierPath *)path
32 | {
33 | self.path = [path CGPath];
34 | self.lineWidth = path.lineWidth;
35 | self.miterLimit = path.miterLimit;
36 |
37 | self.lineCap = [DTGraphicsConverter lineCapFromCGLineCap:path.lineCapStyle];
38 | self.lineJoin = [DTGraphicsConverter lineJoinFromCGLineJoin:path.lineJoinStyle];
39 |
40 | self.fillRule = path.usesEvenOddFillRule ? kCAFillRuleEvenOdd : kCAFillRuleNonZero;
41 |
42 | NSInteger count;
43 | [path getLineDash:NULL count:&count phase:NULL];
44 | CGFloat pattern[count], phase;
45 | [path getLineDash:pattern count:NULL phase:&phase];
46 |
47 | NSMutableArray *lineDashPattern = [NSMutableArray array];
48 | for (NSUInteger i = 0; i < count; i++) {
49 | [lineDashPattern addObject:@(pattern[i])];
50 | }
51 |
52 | self.lineDashPattern = [lineDashPattern copy];
53 | self.lineDashPhase = phase;
54 | }
55 |
56 | -(UIBezierPath *)dt_bezierPath
57 | {
58 | UIBezierPath * path = [UIBezierPath bezierPathWithCGPath:self.path];
59 | path.lineWidth = self.lineWidth;
60 | path.miterLimit = self.miterLimit;
61 |
62 | path.lineCapStyle = [DTGraphicsConverter lineCapFromCALineCap:self.lineCap];
63 | path.lineJoinStyle = [DTGraphicsConverter lineJoinFromCALineJoin:self.lineJoin];
64 |
65 | path.usesEvenOddFillRule = (self.fillRule == kCAFillRuleEvenOdd);
66 |
67 | CGFloat phase = self.lineDashPhase;
68 | NSInteger count = self.lineDashPattern.count;
69 | CGFloat pattern[count];
70 | for (NSUInteger i = 0; i < count; i++) {
71 | pattern[i] = [[self.lineDashPattern objectAtIndex:i] floatValue];
72 | }
73 | [path setLineDash:pattern count:count phase:phase];
74 |
75 | return path;
76 | }
77 |
78 | @end
79 |
--------------------------------------------------------------------------------
/Shapes/CATransaction+AnimateWithDuration.h:
--------------------------------------------------------------------------------
1 | //
2 | // CATransaction+AnimateWithDuration.h
3 | // ShapesExample
4 | //
5 | // Created by Denys Telezhkin on 20.09.14.
6 | // Copyright (c) 2014 Denys Telezhkin. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | #if __has_feature(nullability) // Xcode 6.3+
12 | #pragma clang assume_nonnull begin
13 | #else
14 | #define nullable
15 | #define __nullable
16 | #endif
17 |
18 | @interface CATransaction (AnimateWithDuration)
19 |
20 | +(void)dt_animateWithDuration:(NSTimeInterval)duration
21 | animations:(nullable void (^)(void))animations
22 | completion:(nullable void (^)())completion;
23 |
24 | @end
25 |
26 | #if __has_feature(nullability)
27 | #pragma clang assume_nonnull end
28 | #endif
29 |
--------------------------------------------------------------------------------
/Shapes/CATransaction+AnimateWithDuration.m:
--------------------------------------------------------------------------------
1 | //
2 | // CATransaction+AnimateWithDuration.m
3 | // ShapesExample
4 | //
5 | // Created by Denys Telezhkin on 20.09.14.
6 | // Copyright (c) 2014 Denys Telezhkin. All rights reserved.
7 | //
8 |
9 | #import "CATransaction+AnimateWithDuration.h"
10 |
11 | @implementation CATransaction (AnimateWithDuration)
12 |
13 | +(void)dt_animateWithDuration:(NSTimeInterval)duration
14 | animations:(void (^)(void))animations
15 | completion:(void (^)())completion
16 | {
17 | [CATransaction begin];
18 | [CATransaction setAnimationDuration:duration];
19 |
20 | if (completion)
21 | {
22 | [CATransaction setCompletionBlock:completion];
23 | }
24 |
25 | if (animations)
26 | {
27 | animations();
28 | }
29 | [CATransaction commit];
30 | }
31 |
32 | @end
33 |
--------------------------------------------------------------------------------
/Shapes/DTAnimatableShapeLayer.h:
--------------------------------------------------------------------------------
1 | //
2 | // DTAnimatableShapeLayer.h
3 | // Shapes
4 | //
5 | // Created by Denys Telezhkin on 31.08.14.
6 | // Copyright (c) 2014 Denys Telezhkin. All rights reserved.
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 |
26 | #import
27 |
28 | #if __has_feature(nullability) // Xcode 6.3+
29 | #pragma clang assume_nonnull begin
30 | #else
31 | #define nullable
32 | #define __nullable
33 | #define null_resettable
34 | #endif
35 |
36 | /**
37 | `DTAnimatableShapeLayer` allows implicit animation of CAShapeLayer path. It uses CTTransaction animation duration and animation timing function to animate a change.
38 | */
39 |
40 | @interface DTAnimatableShapeLayer : CAShapeLayer
41 |
42 | /**
43 | Set of all animatable properties on CAShapeLayer. By default, contains "path" key. Add properties to the set, if you wan't them to change with animation.
44 |
45 | To animate changes, use CATransaction, or provided CATransaction+AnimateWithDuration convenience category.
46 | */
47 | @property (nonatomic, strong, null_resettable) NSMutableSet * animatableKeys;
48 |
49 | @end
50 |
51 | #if __has_feature(nullability)
52 | #pragma clang assume_nonnull end
53 | #endif
--------------------------------------------------------------------------------
/Shapes/DTAnimatableShapeLayer.m:
--------------------------------------------------------------------------------
1 | //
2 | // DTAnimatableShapeLayer.m
3 | // Shapes
4 | //
5 | // Created by Denys Telezhkin on 31.08.14.
6 | // Copyright (c) 2014 Denys Telezhkin. All rights reserved.
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 |
26 | #import "DTAnimatableShapeLayer.h"
27 |
28 | @implementation DTAnimatableShapeLayer
29 |
30 | -(NSMutableSet *)animatableKeys
31 | {
32 | if (!_animatableKeys)
33 | {
34 | _animatableKeys = [NSMutableSet setWithObject:@"path"];
35 | }
36 | return _animatableKeys;
37 | }
38 |
39 | -(id)actionForKey:(NSString *)key
40 | {
41 | if ([self.animatableKeys containsObject:key])
42 | {
43 | return [self customAnimationForKey:key];
44 | }
45 | return [super actionForKey:key];
46 | }
47 |
48 | - (CABasicAnimation *) customAnimationForKey: (NSString *) key
49 | {
50 | CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:key];
51 | animation.fromValue = [self.presentationLayer valueForKey:key];
52 | animation.duration = [CATransaction animationDuration];
53 | return animation;
54 | }
55 |
56 | @end
57 |
--------------------------------------------------------------------------------
/Shapes/DTDimmingView.h:
--------------------------------------------------------------------------------
1 | //
2 | // DTDimmedView.h
3 | // Shapes
4 | //
5 | // Created by Denys Telezhkin on 23.07.14.
6 | // Copyright (c) 2014 MLSDev. All rights reserved.
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 |
26 | #import
27 |
28 | #if __has_feature(nullability) // Xcode 6.3+
29 | #pragma clang assume_nonnull begin
30 | #else
31 | #define nullable
32 | #define __nullable
33 | #endif
34 |
35 | /**
36 | `DTDimmingView` allows dimming part of the view, by "cutting" visible path from it. By default, dimming path contains entire UIView bounds. Create UIBezierPath, that describes, which part of the view should be visible, and set it on `DTDimmingView` instance to allow content to be seen.
37 | */
38 | @interface DTDimmingView : UIView
39 |
40 | /**
41 | UIBezierPath, that describes, which part of the content should be visible. It must be completely inside dimmedPath for dimming to work.
42 | */
43 | @property (nonatomic, strong, nullable) UIBezierPath * visiblePath;
44 |
45 | /**
46 | UIBezierPath, that describes, which part of the view should be dimmed. By default, entire view is dimmed.
47 | */
48 | @property (nonatomic, strong, null_resettable) UIBezierPath * dimmedPath;
49 |
50 | /**
51 | Opacity for dimming view. 0.9 by default.
52 | */
53 | @property (nonatomic, assign) float dimmingOpacity UI_APPEARANCE_SELECTOR;
54 |
55 | /**
56 | Color of a dimming view. [UIColor blackColor] by default.
57 | */
58 | @property (nonatomic, strong, nullable) UIColor * dimmingColor UI_APPEARANCE_SELECTOR;
59 |
60 | @end
61 |
62 | #if __has_feature(nullability)
63 | #pragma clang assume_nonnull end
64 | #endif
65 |
--------------------------------------------------------------------------------
/Shapes/DTDimmingView.m:
--------------------------------------------------------------------------------
1 | //
2 | // DTDimmedView.m
3 | // Shapes
4 | //
5 | // Created by Denys Telezhkin on 23.07.14.
6 | // Copyright (c) 2014 MLSDev. All rights reserved.
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 |
26 | #import "DTDimmingView.h"
27 | #import "CAShapeLayer+UIBezierPath.h"
28 |
29 | @interface DTDimmingView()
30 | @property (nonatomic, strong) CAShapeLayer * fillLayer;
31 |
32 | @end
33 |
34 | @implementation DTDimmingView
35 |
36 | @synthesize dimmedPath = _dimmedPath;
37 |
38 | #pragma mark - appearance
39 |
40 | +(void)load
41 | {
42 | [self.appearance setDimmingOpacity:0.9];
43 | [self.appearance setDimmingColor:[UIColor blackColor]];
44 | }
45 |
46 | #pragma mark - getters and setters
47 |
48 | -(UIBezierPath *)dimmedPath
49 | {
50 | if (!_dimmedPath)
51 | {
52 | _dimmedPath = [UIBezierPath bezierPathWithRect:self.bounds];
53 | }
54 | return _dimmedPath;
55 | }
56 |
57 | -(void)setDimmedPath:(UIBezierPath *)dimmedPath
58 | {
59 | _dimmedPath = dimmedPath;
60 | [self updatePathsWithVisiblePath:self.visiblePath];
61 | }
62 |
63 | -(void)setVisiblePath:(UIBezierPath *)visiblePath
64 | {
65 | _visiblePath = visiblePath;
66 | [self updatePathsWithVisiblePath:visiblePath];
67 | }
68 |
69 | -(void)setDimmingColor:(UIColor *)dimmingColor
70 | {
71 | _dimmingColor = dimmingColor;
72 | [self updatePathsWithVisiblePath:self.visiblePath];
73 | }
74 |
75 | #pragma mark - updating visible paths
76 |
77 | -(void)updatePathsWithVisiblePath:(UIBezierPath *)visiblePath
78 | {
79 | [self.fillLayer removeFromSuperlayer];
80 |
81 | visiblePath.usesEvenOddFillRule = YES;
82 |
83 | UIBezierPath * dimmedPath = [UIBezierPath bezierPathWithCGPath:self.dimmedPath.CGPath];
84 |
85 | [dimmedPath appendPath:visiblePath];
86 | dimmedPath.usesEvenOddFillRule = YES;
87 |
88 | self.fillLayer = [CAShapeLayer layer];
89 | self.fillLayer.path = dimmedPath.CGPath;
90 | self.fillLayer.fillRule = kCAFillRuleEvenOdd;
91 | self.fillLayer.fillColor = self.dimmingColor.CGColor;
92 | self.fillLayer.opacity = self.dimmingOpacity;
93 |
94 | [self.layer addSublayer:self.fillLayer];
95 | }
96 |
97 | @end
98 |
--------------------------------------------------------------------------------
/Shapes/DTGraphicsConverter.h:
--------------------------------------------------------------------------------
1 | //
2 | // DTGraphicsConverter.h
3 | // Shapes
4 | //
5 | // Created by Denys Telezhkin on 06.09.14.
6 | // Copyright (c) 2014 Denys Telezhkin. All rights reserved.
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 |
26 | #import
27 |
28 | #if __has_feature(nullability) // Xcode 6.3+
29 | #pragma clang assume_nonnull begin
30 | #else
31 | #define nullable
32 | #define __nullable
33 | #endif
34 |
35 | /**
36 | `DTGraphicsConverter` allows converting from CoreGraphics values to Quartz values and vice versa.
37 | */
38 |
39 | @interface DTGraphicsConverter : NSObject
40 |
41 | /**
42 | Convert CALineCap string constant to CGLineCap value.
43 | */
44 | +(CGLineCap)lineCapFromCALineCap:(NSString *)lineCap;
45 |
46 | /**
47 | Convert CALineJoin string constant to CGLineJoin value.
48 | */
49 | +(CGLineJoin)lineJoinFromCALineJoin:(NSString *)lineJoin;
50 |
51 | /**
52 | Convert CGLineCap value to CALineCap string constant.
53 | */
54 | +(NSString *)lineCapFromCGLineCap:(CGLineCap)lineCap;
55 |
56 | /**
57 | Convert CGLineJoin value to CALineCap string constant.
58 | */
59 | +(NSString *)lineJoinFromCGLineJoin:(CGLineJoin)lineJoin;
60 |
61 | @end
62 |
63 | #if __has_feature(nullability)
64 | #pragma clang assume_nonnull end
65 | #endif
66 |
--------------------------------------------------------------------------------
/Shapes/DTGraphicsConverter.m:
--------------------------------------------------------------------------------
1 | //
2 | // DTGraphicsConverter.m
3 | // Shapes
4 | //
5 | // Created by Denys Telezhkin on 06.09.14.
6 | // Copyright (c) 2014 Denys Telezhkin. All rights reserved.
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 |
26 | #import "DTGraphicsConverter.h"
27 |
28 | @implementation DTGraphicsConverter
29 |
30 | +(NSDictionary *)CGtoCALineCaps
31 | {
32 | return @{
33 | @(kCGLineCapSquare) :kCALineCapSquare,
34 | @(kCGLineCapButt) : kCALineCapButt,
35 | @(kCGLineCapRound) : kCALineCapRound
36 | };
37 | }
38 |
39 | +(NSDictionary *)CGtoCALineJoins
40 | {
41 | return @{
42 | @(kCGLineJoinRound) : kCALineJoinRound,
43 | @(kCGLineJoinMiter) : kCALineJoinMiter,
44 | @(kCGLineJoinBevel) : kCALineJoinBevel
45 | };
46 | }
47 |
48 | +(NSDictionary *)CAtoCGLineCaps
49 | {
50 | return @{
51 | kCALineCapSquare : @(kCGLineCapSquare),
52 | kCALineCapButt : @(kCGLineCapButt),
53 | kCALineCapRound : @(kCGLineCapRound)
54 | };
55 | }
56 |
57 | +(NSDictionary *)CAtoCGLineJoins
58 | {
59 | return @{
60 | kCALineJoinRound : @(kCGLineJoinRound),
61 | kCALineJoinMiter : @(kCGLineJoinMiter),
62 | kCALineJoinBevel : @(kCGLineJoinBevel)
63 | };
64 | }
65 |
66 | +(NSString *)lineCapFromCGLineCap:(CGLineCap)lineCap
67 | {
68 | return [self CGtoCALineCaps][@(lineCap)];
69 | }
70 |
71 | +(NSString *)lineJoinFromCGLineJoin:(CGLineJoin)lineJoin
72 | {
73 | return [self CGtoCALineJoins][@(lineJoin)];
74 | }
75 |
76 | +(CGLineCap)lineCapFromCALineCap:(NSString *)lineCap
77 | {
78 | return [[self CAtoCGLineCaps][lineCap] intValue];
79 | }
80 |
81 | +(CGLineJoin)lineJoinFromCALineJoin:(NSString *)lineJoin
82 | {
83 | return [[self CAtoCGLineJoins][lineJoin] intValue];
84 | }
85 |
86 | @end
87 |
--------------------------------------------------------------------------------
/Shapes/DTProgressView.h:
--------------------------------------------------------------------------------
1 | //
2 | // DTProgressView.h
3 | // Shapes
4 | //
5 | // Created by Denys Telezhkin on 17.07.14.
6 | // Copyright (c) 2014 MLSDev. All rights reserved.
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 |
26 | #import "DTShapeView.h"
27 |
28 | #if __has_feature(nullability) // Xcode 6.3+
29 | #pragma clang assume_nonnull begin
30 | #else
31 | #define nullable
32 | #define __nullable
33 | #endif
34 |
35 | /**
36 | `DTProgressView` is a `DTShapeView` subclass, that allow animating progress views of any shape. `DTProgressView` uses `DTShapeView` path as track. Stroke start and stroke end properties provide ability to change progress state of a view.
37 |
38 | By default, progress view fills entire view frame, animating progress from left to right.
39 | */
40 | @interface DTProgressView : DTShapeView
41 |
42 | /**
43 | `DTProgressView` progress. Value range from 0 to 1, 0 by default.
44 | */
45 | @property (nonatomic, assign, readonly) IBInspectable float progress;
46 |
47 | /**
48 | Duration of an animated progress change.
49 |
50 | Default is 0.3s.
51 | */
52 | @property (nonatomic, assign) NSTimeInterval animationDuration UI_APPEARANCE_SELECTOR;
53 |
54 | /**
55 | Animation function to use, when animating progress change.
56 | */
57 | @property (nonatomic, strong, nullable) CAValueFunction * animationFunction;
58 |
59 | /**
60 | Set progress value. This method is an alias for setStrokeEnd:animated:.
61 |
62 | @param progress The new progress value.
63 |
64 | @param animated Specify YES to animate the change or NO if you do not want the change to be animated.
65 | */
66 | - (void)setProgress:(float)progress animated:(BOOL)animated;
67 |
68 | /**
69 | Set stroke start value.
70 |
71 | @param progress The new progress value.
72 |
73 | @param animated Specify YES to animate the change or NO if you do not want the change to be animated.
74 | */
75 | - (void)setStrokeStart:(float)start animated:(BOOL)animated;
76 |
77 | /**
78 | Set strokeEnd value. This method is an alias for setProgress:animated:.
79 |
80 | @param progress The new strokeEnd value.
81 |
82 | @param animated Specify YES to animate the change or NO if you do not want the change to be animated.
83 | */
84 | - (void)setStrokeEnd:(float)end animated:(BOOL)animated;
85 |
86 | @end
87 |
88 | #if __has_feature(nullability)
89 | #pragma clang assume_nonnull end
90 | #endif
91 |
--------------------------------------------------------------------------------
/Shapes/DTProgressView.m:
--------------------------------------------------------------------------------
1 | //
2 | // DTProgressView.m
3 | // Shapes
4 | //
5 | // Created by Denys Telezhkin on 17.07.14.
6 | // Copyright (c) 2014 MLSDev. All rights reserved.
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 |
26 |
27 | #import "DTProgressView.h"
28 |
29 | @interface DTProgressView()
30 | @end
31 |
32 | @implementation DTProgressView
33 |
34 | static NSString * const kStrokeEndAnimationKey = @"Stroke end animation";
35 | static NSString * const kStrokeStartAnimationKey = @"Stroke start animation";
36 |
37 | +(void)load
38 | {
39 | [self.appearance setAnimationDuration:0.3];
40 | }
41 |
42 | -(void)commonSetup
43 | {
44 | UIBezierPath * path = [UIBezierPath bezierPath];
45 | path.lineWidth = self.frame.size.height;
46 | [path moveToPoint:CGPointMake(0, self.frame.size.height/2)];
47 | [path addLineToPoint:CGPointMake(self.frame.size.width, self.frame.size.height/2)];
48 | [self setPath:path];
49 |
50 | [self setFillColor:[UIColor clearColor]];
51 | self.strokeColor = [UIColor grayColor];
52 |
53 | self.shapeLayer.strokeEnd = 0;
54 | self.shapeLayer.strokeStart = 0;
55 | }
56 |
57 | -(instancetype)initWithCoder:(NSCoder *)aDecoder
58 | {
59 | if (self=[super initWithCoder:aDecoder])
60 | {
61 | [self commonSetup];
62 | }
63 | return self;
64 | }
65 |
66 | -(instancetype)initWithFrame:(CGRect)frame
67 | {
68 | if (self = [super initWithFrame:frame])
69 | {
70 | [self commonSetup];
71 | }
72 | return self;
73 | }
74 |
75 | -(float)progress
76 | {
77 | return self.strokeEnd;
78 | }
79 |
80 | - (void)setProgress:(float)progress animated:(BOOL)animated
81 | {
82 | [self setStrokeEnd:progress animated:animated];
83 | }
84 |
85 | -(float)normalizedProgressValueFromValue:(float)value
86 | {
87 | if (value>1)
88 | return 1;
89 | if (value<0)
90 | return 0;
91 | return value;
92 | }
93 |
94 | -(void)setStrokeStart:(float)strokeStart animated:(BOOL)animated
95 | {
96 | strokeStart = [self normalizedProgressValueFromValue:strokeStart];
97 |
98 | if (animated)
99 | {
100 | [self animateStrokeStart:strokeStart];
101 | }
102 | else {
103 | [self.layer removeAnimationForKey:kStrokeStartAnimationKey];
104 | self.shapeLayer.strokeStart = strokeStart;
105 | self.strokeStart = strokeStart;
106 | }
107 | }
108 |
109 | -(void)setStrokeEnd:(float)end animated:(BOOL)animated
110 | {
111 | end = [self normalizedProgressValueFromValue:end];
112 |
113 | if (animated)
114 | {
115 | [self animateStrokeEnd:end];
116 | }
117 | else {
118 | [self.layer removeAnimationForKey:kStrokeEndAnimationKey];
119 | self.shapeLayer.strokeEnd = end;
120 | self.strokeEnd = end;
121 | }
122 | }
123 |
124 | -(void)animateStrokeStart:(float)start
125 | {
126 | float fromValue = self.strokeStart;
127 |
128 | if ( [self.shapeLayer animationForKey:kStrokeStartAnimationKey]!=nil)
129 | {
130 | CAShapeLayer * presentationLayer = [self.shapeLayer presentationLayer];
131 | fromValue = [presentationLayer strokeStart];
132 | }
133 |
134 | [self.layer removeAnimationForKey:kStrokeStartAnimationKey];
135 |
136 | self.shapeLayer.strokeStart = start;
137 |
138 | CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeStart"];
139 | animation.duration = self.animationDuration;
140 | animation.valueFunction = self.animationFunction;
141 | animation.fromValue = @(fromValue);
142 | animation.toValue = @(start);
143 | animation.removedOnCompletion = YES;
144 |
145 | [self.shapeLayer addAnimation:animation forKey:kStrokeStartAnimationKey];
146 | self.strokeStart = start;
147 | }
148 |
149 | -(void)animateStrokeEnd:(float)end
150 | {
151 | float fromValue = self.strokeEnd;
152 |
153 | if ( [self.shapeLayer animationForKey:kStrokeEndAnimationKey]!=nil)
154 | {
155 | CAShapeLayer * presentationLayer = [self.shapeLayer presentationLayer];
156 | fromValue = [presentationLayer strokeEnd];
157 | }
158 |
159 | [self.layer removeAnimationForKey:kStrokeEndAnimationKey];
160 |
161 | self.shapeLayer.strokeEnd = end;
162 |
163 | CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
164 | animation.duration = self.animationDuration;
165 | animation.valueFunction = self.animationFunction;
166 | animation.fromValue = @(fromValue);
167 | animation.toValue = @(end);
168 | animation.removedOnCompletion = YES;
169 |
170 | [self.shapeLayer addAnimation:animation forKey:kStrokeEndAnimationKey];
171 | self.strokeEnd = end;
172 | }
173 |
174 | - (void)animateToProgress:(float)progress
175 | {
176 | progress = [self normalizedProgressValueFromValue:progress];
177 |
178 | [self animateStrokeEnd:progress];
179 | }
180 |
181 | @end
182 |
--------------------------------------------------------------------------------
/Shapes/DTShapeButton.h:
--------------------------------------------------------------------------------
1 | //
2 | // DTShapeButton.h
3 | // Shapes
4 | //
5 | // Created by Denys Telezhkin on 30.08.14.
6 | // Copyright (c) 2014 Denys Telezhkin. All rights reserved.
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 |
26 | #import "DTShapeView.h"
27 |
28 | #if __has_feature(nullability) // Xcode 6.3+
29 | #pragma clang assume_nonnull begin
30 | #else
31 | #define nullable
32 | #define __nullable
33 | #endif
34 |
35 | /**
36 | ` DTShapeButton` is a UIButton, that has `DTShapedView` added as a subview. As a result, it allows manipulating UIButton shape and visual appearance by changing `DTShapedView` properties. By default, button shape is a rectangle with UIButton bounds set as it's frame.
37 | */
38 | @interface DTShapeButton : UIButton
39 |
40 | /**
41 | `DTShapeView`, added as a sublayer to UIButton's layer.
42 | */
43 | @property (nonatomic, strong, nullable) DTShapeView * shape;
44 |
45 | @end
46 |
47 | #if __has_feature(nullability)
48 | #pragma clang assume_nonnull end
49 | #endif
50 |
51 |
--------------------------------------------------------------------------------
/Shapes/DTShapeButton.m:
--------------------------------------------------------------------------------
1 | //
2 | // DTShapeButton.m
3 | // Shapes
4 | //
5 | // Created by Denys Telezhkin on 30.08.14.
6 | // Copyright (c) 2014 Denys Telezhkin. All rights reserved.
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 |
26 | #import "DTShapeButton.h"
27 |
28 | @implementation DTShapeButton
29 |
30 | -(instancetype)initWithCoder:(NSCoder *)aDecoder
31 | {
32 | if (self = [super initWithCoder:aDecoder])
33 | {
34 | [self commonSetup];
35 | }
36 | return self;
37 | }
38 |
39 | -(instancetype)initWithFrame:(CGRect)frame
40 | {
41 | if (self = [super initWithFrame:frame])
42 | {
43 | [self commonSetup];
44 | }
45 | return self;
46 | }
47 |
48 | -(void)commonSetup
49 | {
50 | DTShapeView * buttonShape = [[DTShapeView alloc] initWithFrame:self.bounds];
51 | UIBezierPath * path = [UIBezierPath bezierPathWithRect:self.bounds];
52 | buttonShape.path = path;
53 |
54 | [self addSubview:buttonShape];
55 | self.shape = buttonShape;
56 | self.shape.userInteractionEnabled = NO;
57 | self.shape.exclusiveTouch = NO;
58 |
59 | buttonShape.fillColor = [UIColor clearColor];
60 | buttonShape.strokeColor = self.tintColor;
61 | }
62 |
63 | @end
64 |
--------------------------------------------------------------------------------
/Shapes/DTShapeView.h:
--------------------------------------------------------------------------------
1 | //
2 | // DTShapeView.h
3 | // Shapes
4 | //
5 | // Created by Denys Telezhkin on 17.07.14.
6 | // Copyright (c) 2014 MLSDev. All rights reserved.
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 |
26 | #import
27 |
28 | #import "DTAnimatableShapeLayer.h"
29 |
30 | #if __has_feature(nullability) // Xcode 6.3+
31 | #pragma clang assume_nonnull begin
32 | #else
33 | #define nullable
34 | #define __nullable
35 | #endif
36 |
37 | /**
38 | `DTShapeView` is a UIView subclass, that is backed by CAShapeLayer instead of CALayer. It provides API for changing CAShapeLayer path, fill and stroke colors and other layer properties, basically allowing UIView to behave like geometric shape.
39 |
40 | All `DTShapeView` properties are automatically converted to CAShapeLayer properties or use CAShapeLayer properties directly. You can use whatever style you like, but we recommend using UIBezierPath and `DTShapeView` properties, because this allows you to completely bypass CoreFoundation objects. It also allows you to use CoreGraphics API instead of QuartzCore.
41 | */
42 | @interface DTShapeView : UIView
43 |
44 | /**
45 | Setting path property automatically converts all UIBezierPath properties to CAShapeLayer properties.
46 | */
47 | @property (nonatomic, strong, nullable) UIBezierPath * path;
48 |
49 | /**
50 | CAShapeLayer, that is backing view.
51 | */
52 | @property (nonatomic, strong, readonly) DTAnimatableShapeLayer * shapeLayer;
53 |
54 | /**
55 | Fill color, used by CAShapeLayer. UIColor is automatically converted to and from CAShapeLayer fillColor property.
56 | */
57 | @property (nonatomic, strong) IBInspectable UIColor * fillColor;
58 |
59 | /**
60 | Stroke color, used by CAShapeLayer. UIColor is automatically converted to and from CAShapeLayer strokeColor property.
61 | */
62 | @property (nonatomic, strong) IBInspectable UIColor * strokeColor;
63 |
64 | /**
65 | Fill rule, used by CAShapeLayer. Automatically converts to CAFillRule constant values on CAShapeLayer.
66 | */
67 | @property (nonatomic, assign) IBInspectable BOOL usesEvenOddFillRule;
68 |
69 | /**
70 | Set CAShapeLayer strokeStart property.
71 | */
72 | @property (nonatomic, assign) IBInspectable CGFloat strokeStart;
73 |
74 | /**
75 | Set CAShapeLayer strokeEnd property.
76 | */
77 | @property (nonatomic, assign) IBInspectable CGFloat strokeEnd;
78 |
79 | /**
80 | This property uses CAShapeLayer lineWidth property directly.
81 | */
82 | @property (nonatomic, assign) IBInspectable CGFloat lineWidth;
83 |
84 | /**
85 | This property uses CAShapeLayer miterLimit property directly.
86 | */
87 | @property (nonatomic, assign) IBInspectable CGFloat miterLimit;
88 |
89 | /**
90 | This property is automatically converted to QuartzCore line cap constant values on CAShapeLayer.
91 | */
92 | @property (nonatomic, assign) CGLineCap lineCap;
93 |
94 | /**
95 | This property is automatically converted to QuartzCore line join constant values on CAShapeLayer.
96 | */
97 | @property (nonatomic, assign) CGLineJoin lineJoin;
98 |
99 | /**
100 | This property uses CAShapeLayer lineDashPhase property directly.
101 | */
102 | @property (nonatomic, assign) CGFloat lineDashPhase;
103 |
104 | /**
105 | This property uses CAShapeLayer lineDashPattern property directly.
106 | */
107 | @property (nonatomic, copy) NSArray *lineDashPattern;
108 |
109 | /**
110 | Set this property to YES, if you want to enable hit testing inside CAShapeLayer path.
111 |
112 | Default value is NO.
113 | */
114 | @property (nonatomic, assign) BOOL hitTestInsidePath;
115 |
116 | @end
117 |
118 | #if __has_feature(nullability)
119 | #pragma clang assume_nonnull end
120 | #endif
121 |
--------------------------------------------------------------------------------
/Shapes/DTShapeView.m:
--------------------------------------------------------------------------------
1 | //
2 | // DTShapeView.m
3 | // Shapes
4 | //
5 | // Created by Denys Telezhkin on 17.07.14.
6 | // Copyright (c) 2014 MLSDev. All rights reserved.
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 |
26 | #import "DTShapeView.h"
27 | #import "CAShapeLayer+UIBezierPath.h"
28 | #import "DTGraphicsConverter.h"
29 | #import "DTAnimatableShapeLayer.h"
30 |
31 | @implementation DTShapeView
32 |
33 | @dynamic strokeStart, strokeEnd, lineWidth, miterLimit, lineDashPhase, lineDashPattern;
34 |
35 | #pragma mark - UIView methods
36 |
37 | +(Class)layerClass
38 | {
39 | return [DTAnimatableShapeLayer class];
40 | }
41 |
42 | -(CAShapeLayer *)shapeLayer
43 | {
44 | return (CAShapeLayer*)self.layer;
45 | }
46 |
47 | #pragma mark - method forwarding
48 |
49 | - (BOOL)shouldForwardSelector:(SEL)aSelector {
50 | return (![[[self.layer superclass] superclass] instancesRespondToSelector:aSelector] &&
51 | [self.layer respondsToSelector:aSelector]);
52 | }
53 |
54 | - (id)forwardingTargetForSelector:(SEL)aSelector {
55 | return (![self respondsToSelector:aSelector] && [self shouldForwardSelector:aSelector]) ? self.layer : self;
56 | }
57 |
58 | #pragma mark - getters and setters
59 |
60 | -(void)setPath:(UIBezierPath *)path
61 | {
62 | _path = path;
63 | [CATransaction begin];
64 | [CATransaction setAnimationDuration:[CATransaction animationDuration]];
65 | [CATransaction setAnimationTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut] ];
66 | [self.shapeLayer dt_updateWithBezierPath:path];
67 | [CATransaction commit];
68 | }
69 |
70 | -(void)setFillColor:(UIColor *)fillColor
71 | {
72 | [self.shapeLayer setFillColor:[fillColor CGColor]];
73 | }
74 |
75 | -(UIColor *)fillColor
76 | {
77 | return [UIColor colorWithCGColor:[self.shapeLayer fillColor]];
78 | }
79 |
80 | -(UIColor *)strokeColor
81 | {
82 | return [UIColor colorWithCGColor:[self.shapeLayer strokeColor]];
83 | }
84 |
85 | -(void)setStrokeColor:(UIColor *)strokeColor
86 | {
87 | [self.shapeLayer setStrokeColor:[strokeColor CGColor]];
88 | }
89 |
90 | -(void)setUsesEvenOddFillRule:(BOOL)usesEvenOddFillRule
91 | {
92 | self.shapeLayer.fillRule = usesEvenOddFillRule ? kCAFillRuleEvenOdd : kCAFillRuleNonZero;
93 | }
94 |
95 | -(BOOL)usesEvenOddFillRule
96 | {
97 | return self.shapeLayer.fillRule == kCAFillRuleEvenOdd;
98 | }
99 |
100 | -(void)setLineCap:(CGLineCap)lineCap
101 | {
102 | self.shapeLayer.lineCap = [DTGraphicsConverter lineCapFromCGLineCap:lineCap];
103 | }
104 |
105 | -(CGLineCap)lineCap
106 | {
107 | return [DTGraphicsConverter lineCapFromCALineCap:self.shapeLayer.lineCap];
108 | }
109 |
110 | -(void)setLineJoin:(CGLineJoin)lineJoin
111 | {
112 | self.shapeLayer.lineJoin = [DTGraphicsConverter lineJoinFromCGLineJoin:lineJoin];
113 | }
114 |
115 | -(CGLineJoin)lineJoin
116 | {
117 | return [DTGraphicsConverter lineJoinFromCALineJoin:self.shapeLayer.lineJoin];
118 | }
119 |
120 | #pragma mark - hit testing
121 |
122 | - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
123 | BOOL inside = [super pointInside:point withEvent:event];
124 | return self.hitTestInsidePath ? [self.path containsPoint:point] && inside : inside;
125 | }
126 |
127 | @end
128 |
--------------------------------------------------------------------------------
/Shapes/Shapes.h:
--------------------------------------------------------------------------------
1 | //
2 | // Shapes.h
3 | // ShapesExample
4 | //
5 | // Created by Denys Telezhkin on 20.09.14.
6 | // Copyright (c) 2014 Denys Telezhkin. All rights reserved.
7 | //
8 |
9 | #import "DTShapeView.h"
10 | #import "DTShapeButton.h"
11 |
12 | #import "DTDimmingView.h"
13 | #import "DTProgressView.h"
14 | #import "DTAnimatableShapeLayer.h"
15 |
16 | #import "CATransaction+AnimateWithDuration.h"
17 |
--------------------------------------------------------------------------------
/ShapesExample/Rakefile:
--------------------------------------------------------------------------------
1 | require 'xcpretty'
2 |
3 | scheme_name = "ShapeKitExample"
4 |
5 | def run(command, min_exit_status = 0)
6 | puts "Executing: `#{command}`"
7 | system(command)
8 | return $?.exitstatus
9 | end
10 |
11 | desc "Run #{scheme_name} tests"
12 | task :run_tests do
13 | $tests_success = run("xcodebuild -scheme \"#{scheme_name}\" -destination 'name=iPhone Retina (4-inch),OS=7.1' clean test | xcpretty -tc; exit ${PIPESTATUS[0]}")
14 | end
15 |
16 | task default: 'run_tests'
--------------------------------------------------------------------------------
/ShapesExample/ShapeKitExample/AppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.h
3 | // ShapesExample
4 | //
5 | // Created by Denys Telezhkin on 27.07.14.
6 | // Copyright (c) 2014 Denys Telezhkin. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface AppDelegate : UIResponder
12 |
13 | @property (strong, nonatomic) UIWindow *window;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/ShapesExample/ShapeKitExample/AppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.m
3 | // ShapesExample
4 | //
5 | // Created by Denys Telezhkin on 27.07.14.
6 | // Copyright (c) 2014 Denys Telezhkin. All rights reserved.
7 | //
8 |
9 | #import "AppDelegate.h"
10 |
11 | @implementation AppDelegate
12 |
13 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
14 | {
15 | return YES;
16 | }
17 |
18 | @end
19 |
--------------------------------------------------------------------------------
/ShapesExample/ShapeKitExample/Controllers/DimmingViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // DimmingViewController.h
3 | // ShapesExample
4 | //
5 | // Created by Denys Telezhkin on 10.08.14.
6 | // Copyright (c) 2014 Denys Telezhkin. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface DimmingViewController : UIViewController
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/ShapesExample/ShapeKitExample/Controllers/DimmingViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // DimmingViewController.m
3 | // ShapesExample
4 | //
5 | // Created by Denys Telezhkin on 10.08.14.
6 | // Copyright (c) 2014 Denys Telezhkin. All rights reserved.
7 | //
8 |
9 | #import "DimmingViewController.h"
10 | #import "DTDimmingView.h"
11 |
12 | @interface DimmingViewController ()
13 | @property (weak, nonatomic) IBOutlet DTDimmingView *dimmingDynamicView;
14 |
15 | @end
16 |
17 | @implementation DimmingViewController
18 |
19 | -(void)viewDidLoad
20 | {
21 | [super viewDidLoad];
22 |
23 | UIBezierPath * roundedPath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(158, 251, 100, 100)];
24 | self.dimmingDynamicView.dimmingOpacity = 0.7;
25 | self.dimmingDynamicView.visiblePath = roundedPath;
26 | [self.view addSubview:self.dimmingDynamicView];
27 | }
28 |
29 | - (IBAction)panGestureMoved:(UIPanGestureRecognizer *)sender
30 | {
31 | CGPoint location = [sender locationInView:self.view];
32 |
33 | self.dimmingDynamicView.visiblePath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(location.x-50, location.y-50,
34 | 100, 100)];
35 | }
36 |
37 | @end
38 |
--------------------------------------------------------------------------------
/ShapesExample/ShapeKitExample/Controllers/DownloadButtonViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // AnimatedShapesViewController.h
3 | // ShapesExample
4 | //
5 | // Created by Denys Telezhkin on 25.08.14.
6 | // Copyright (c) 2014 Denys Telezhkin. All rights reserved.
7 | //
8 |
9 | #import "HighlightableShapeButton.h"
10 |
11 | @interface DownloadButtonViewController : UIViewController
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/ShapesExample/ShapeKitExample/Controllers/DownloadButtonViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // AnimatedShapesViewController.m
3 | // ShapesExample
4 | //
5 | // Created by Denys Telezhkin on 25.08.14.
6 | // Copyright (c) 2014 Denys Telezhkin. All rights reserved.
7 | //
8 |
9 | #import "DownloadButtonViewController.h"
10 | #import "DTAnimatableShapeLayer.h"
11 | #import "CATransaction+AnimateWithDuration.h"
12 |
13 | @interface DownloadButtonViewController()
14 | @property (weak, nonatomic) IBOutlet DTShapeButton *progressButton;
15 | @property (weak, nonatomic) IBOutlet HighlightableShapeButton *downloadButton;
16 | @end
17 |
18 | @implementation DownloadButtonViewController
19 |
20 | -(void)viewDidLoad
21 | {
22 | [super viewDidLoad];
23 |
24 | self.downloadButton.shape.path = [UIBezierPath bezierPathWithRoundedRect:self.downloadButton.bounds cornerRadius:5.0f];
25 | self.progressButton.shape.path = [UIBezierPath bezierPathWithOvalInRect:self.progressButton.bounds];
26 |
27 | self.progressButton.shape.strokeEnd = 0.85;
28 |
29 | CABasicAnimation *spinAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
30 | spinAnimation.toValue = @(1*2*M_PI);
31 | spinAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
32 | spinAnimation.duration = 1.0;
33 | spinAnimation.repeatCount = INFINITY;
34 | [self.progressButton.shape.shapeLayer addAnimation:spinAnimation forKey:@"spin animation"];
35 | }
36 |
37 | - (IBAction)downloadTapped:(id)sender
38 | {
39 | [self.downloadButton setTitle:@"" forState:UIControlStateNormal];
40 |
41 | CGRect frame = CGRectMake(self.downloadButton.frame.origin.x - self.progressButton.frame.size.width-5,
42 | 0,
43 | self.progressButton.frame.size.width+5,
44 | self.progressButton.frame.size.height);
45 | UIBezierPath * roundedPath = [UIBezierPath bezierPathWithRoundedRect:frame
46 | cornerRadius:10.0];
47 | [CATransaction dt_animateWithDuration:0.25
48 | animations:^{
49 | [self.downloadButton.shape setPath:roundedPath];
50 | } completion:^{
51 | self.downloadButton.hidden = YES;
52 | self.progressButton.hidden = NO;
53 | }];
54 | }
55 |
56 | - (IBAction)progressButtonTapped:(id)sender
57 | {
58 | self.downloadButton.hidden = NO;
59 | self.progressButton.hidden = YES;
60 |
61 | [CATransaction dt_animateWithDuration:0.25
62 | animations:^{
63 | self.downloadButton.shape.path = [UIBezierPath bezierPathWithRoundedRect:self.downloadButton.bounds
64 | cornerRadius:5.0f];
65 | } completion:^{
66 | [self.downloadButton setTitle:@"DOWNLOAD" forState:UIControlStateNormal];
67 | }];
68 | }
69 |
70 | @end
71 |
--------------------------------------------------------------------------------
/ShapesExample/ShapeKitExample/Controllers/ProgressViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // ProgressViewController.h
3 | // ShapesExample
4 | //
5 | // Created by Denys Telezhkin on 27.07.14.
6 | // Copyright (c) 2014 Denys Telezhkin. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface ProgressViewController : UIViewController
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/ShapesExample/ShapeKitExample/Controllers/ProgressViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // ProgressViewController.m
3 | // ShapesExample
4 | //
5 | // Created by Denys Telezhkin on 27.07.14.
6 | // Copyright (c) 2014 Denys Telezhkin. All rights reserved.
7 | //
8 |
9 | #import "ProgressViewController.h"
10 | #import "DTProgressView.h"
11 |
12 | @interface ProgressViewController ()
13 | @property (weak, nonatomic) IBOutlet DTProgressView *simpleProgressView;
14 | @property (weak, nonatomic) IBOutlet DTProgressView *progressView;
15 | @property (weak, nonatomic) IBOutlet DTProgressView *infiniteProgressView;
16 | @property (weak, nonatomic) IBOutlet DTProgressView *ellipseProgressView;
17 | @property (weak, nonatomic) IBOutlet DTProgressView *verticalProgressView;
18 |
19 | @end
20 |
21 | @implementation ProgressViewController
22 |
23 | -(void)dealloc
24 | {
25 | [[self class] cancelPreviousPerformRequestsWithTarget:self];
26 | }
27 |
28 | -(void)viewDidLoad
29 | {
30 | [super viewDidLoad];
31 |
32 | [self setupSimpleProgressView];
33 | [self setupProgressView];
34 | [self setupInfiniteProgressView];
35 | [self setupEllipseProgressView];
36 | [self setupVerticalRoundedProgressView];
37 |
38 | [self increaseProgress];
39 | }
40 |
41 | -(void)setupSimpleProgressView
42 | {
43 | self.simpleProgressView.strokeColor = [UIColor greenColor];
44 | }
45 |
46 | -(void)setupProgressView
47 | {
48 | self.progressView.strokeColor = [UIColor redColor];
49 | CGFloat side = self.progressView.bounds.size.width - 5;
50 | CGRect circleRect = CGRectMake(5, 5, side-5, side-5);
51 | UIBezierPath * circlePath = [UIBezierPath bezierPathWithOvalInRect:circleRect];
52 | self.progressView.path = circlePath;
53 | self.progressView.lineWidth = 2;
54 | }
55 |
56 | -(void)setupInfiniteProgressView
57 | {
58 | // Does not seem to work properly on iOS 8.4 and iOS 9
59 |
60 |
61 | // self.infiniteProgressView.strokeColor = [UIColor blueColor];
62 | //
63 | // CGFloat side = self.infiniteProgressView.bounds.size.width - 5;
64 | // CGRect circleRect = CGRectMake(5, 5, side-5, side-5);
65 | // UIBezierPath * path = [UIBezierPath bezierPathWithOvalInRect:circleRect];
66 | // path.lineWidth = 1;
67 | // self.infiniteProgressView.path = path;
68 | // [self.infiniteProgressView setStrokeEnd:0.85 animated:NO];
69 |
70 | // CABasicAnimation *spinAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
71 | // spinAnimation.fromValue = @0;
72 | // spinAnimation.toValue = @(M_PI*2);
73 | // spinAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
74 | // spinAnimation.duration = 10.0;
75 | // spinAnimation.cumulative = YES;
76 | // spinAnimation.repeatCount = INFINITY;
77 | // [self.infiniteProgressView.shapeLayer addAnimation:spinAnimation forKey:@"spin animation"];
78 | }
79 |
80 | -(void)setupVerticalRoundedProgressView
81 | {
82 | UIBezierPath * path = [UIBezierPath bezierPath];
83 | [path moveToPoint:CGPointMake(self.verticalProgressView.bounds.size.width/2, 0)];
84 | [path addLineToPoint:CGPointMake(self.verticalProgressView.bounds.size.width/2,
85 | self.verticalProgressView.frame.size.height)];
86 |
87 | path.lineWidth = 5;
88 | self.verticalProgressView.path = path;
89 | self.verticalProgressView.lineCap = kCGLineCapRound;
90 |
91 | self.verticalProgressView.strokeColor = [UIColor grayColor];
92 | }
93 |
94 | -(void)setupEllipseProgressView
95 | {
96 | UIBezierPath * path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(self.ellipseProgressView.frame.size.width/2, self.ellipseProgressView.frame.size.height)
97 | radius:self.progressView.frame.size.height
98 | startAngle:M_PI
99 | endAngle:0
100 | clockwise:NO];
101 | path.lineWidth = 2;
102 | self.ellipseProgressView.path = path;
103 |
104 | self.ellipseProgressView.strokeColor = [UIColor magentaColor];
105 | }
106 |
107 | -(void)increaseProgress
108 | {
109 | if (self.progressView.progress == 1)
110 | {
111 | [self.progressView setProgress:0 animated:NO];
112 | [self.simpleProgressView setProgress:0 animated:NO];
113 | [self.ellipseProgressView setProgress:0 animated:NO];
114 | [self.verticalProgressView setProgress:0 animated:NO];
115 | }
116 | float random = (arc4random() % 10)/100.0;
117 |
118 | float progress = self.simpleProgressView.progress + random;
119 |
120 | [self.simpleProgressView setProgress:progress animated:YES];
121 | [self.progressView setProgress:progress animated:YES];
122 | [self.ellipseProgressView setProgress:progress animated:YES];
123 | [self.verticalProgressView setProgress:progress animated:YES];
124 |
125 | [self performSelector:@selector(increaseProgress) withObject:nil afterDelay:0.15];
126 | }
127 |
128 | @end
129 |
--------------------------------------------------------------------------------
/ShapesExample/ShapeKitExample/Controllers/VoiceMemosRecordButtonViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // VoiceMemosRecordButtonViewController.h
3 | // ShapesExample
4 | //
5 | // Created by Denys Telezhkin on 30.08.14.
6 | // Copyright (c) 2014 Denys Telezhkin. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "DTAnimatableShapeLayer.h"
11 |
12 | @interface VoiceMemosRecordButtonViewController : UIViewController
13 |
14 | @end
15 |
--------------------------------------------------------------------------------
/ShapesExample/ShapeKitExample/Controllers/VoiceMemosRecordButtonViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // VoiceMemosRecordButtonViewController.m
3 | // ShapesExample
4 | //
5 | // Created by Denys Telezhkin on 30.08.14.
6 | // Copyright (c) 2014 Denys Telezhkin. All rights reserved.
7 | //
8 |
9 | #import "VoiceMemosRecordButtonViewController.h"
10 | #import "DTShapeView.h"
11 | #import "DTShapeButton.h"
12 | #import "CATransaction+AnimateWithDuration.h"
13 |
14 | @interface VoiceMemosRecordButtonViewController ()
15 | @property (weak, nonatomic) IBOutlet DTShapeView *whiteShapeView;
16 | @property (weak, nonatomic) IBOutlet DTShapeButton *recordButton;
17 |
18 | @property (nonatomic, assign) BOOL isRecording;
19 | @end
20 |
21 | @implementation VoiceMemosRecordButtonViewController
22 |
23 | - (void)viewDidLoad
24 | {
25 | [super viewDidLoad];
26 |
27 | self.whiteShapeView.path = [UIBezierPath bezierPathWithOvalInRect:CGRectInset(self.whiteShapeView.bounds, 4, 4)];
28 | self.whiteShapeView.strokeColor = [UIColor whiteColor];
29 | self.whiteShapeView.lineWidth = 4;
30 |
31 | self.recordButton.shape.path = [UIBezierPath bezierPathWithRoundedRect:CGRectInset(self.recordButton.frame, 8, 8) cornerRadius:(self.recordButton.frame.size.width-4)/2];
32 | self.recordButton.shape.fillColor = [UIColor redColor];
33 |
34 | CAShapeLayer * maskLayer = [DTAnimatableShapeLayer layer];
35 | UIBezierPath * fromPath = [UIBezierPath bezierPathWithRoundedRect:CGRectInset(self.recordButton.frame, 0, 0)
36 | cornerRadius:4];
37 | maskLayer.path = [fromPath CGPath];
38 | self.recordButton.shape.shapeLayer.mask = maskLayer;
39 | }
40 |
41 | - (IBAction)recordTapped:(id)sender
42 | {
43 | self.isRecording = !self.isRecording;
44 |
45 | UIBezierPath * fromPath = [UIBezierPath bezierPathWithRoundedRect:CGRectInset(self.recordButton.frame, 0, 0)
46 | cornerRadius:4];
47 | UIBezierPath * toPath = [UIBezierPath bezierPathWithRoundedRect:CGRectInset(self.recordButton.frame, 18, 18)
48 | cornerRadius:4];
49 |
50 | [CATransaction dt_animateWithDuration:0.25
51 | animations:^{
52 | if (self.isRecording)
53 | {
54 | [(CAShapeLayer *)self.recordButton.shape.shapeLayer.mask setPath:[toPath CGPath]];
55 | }
56 | else {
57 | [(CAShapeLayer *)self.recordButton.shape.shapeLayer.mask setPath:[fromPath CGPath]];
58 | }
59 | } completion:nil];
60 | }
61 |
62 | @end
63 |
--------------------------------------------------------------------------------
/ShapesExample/ShapeKitExample/Controllers/cat_selfie.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MLSDev/Shapes/35d19f56082a2cde54585b14671af6f4d58ba28e/ShapesExample/ShapeKitExample/Controllers/cat_selfie.png
--------------------------------------------------------------------------------
/ShapesExample/ShapeKitExample/Controls/DimmableShapeButton.h:
--------------------------------------------------------------------------------
1 | //
2 | // DimmableShapedButton.h
3 | // ShapesExample
4 | //
5 | // Created by Denys Telezhkin on 30.08.14.
6 | // Copyright (c) 2014 Denys Telezhkin. All rights reserved.
7 | //
8 |
9 | #import "DTShapeButton.h"
10 |
11 | @interface DimmableShapeButton : DTShapeButton
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/ShapesExample/ShapeKitExample/Controls/DimmableShapeButton.m:
--------------------------------------------------------------------------------
1 | //
2 | // DimmableShapedButton.m
3 | // ShapesExample
4 | //
5 | // Created by Denys Telezhkin on 30.08.14.
6 | // Copyright (c) 2014 Denys Telezhkin. All rights reserved.
7 | //
8 |
9 | #import "DimmableShapeButton.h"
10 |
11 | @implementation DimmableShapeButton
12 |
13 | -(void)setHighlighted:(BOOL)highlighted
14 | {
15 | if (highlighted)
16 | {
17 | self.alpha = 0.3;
18 | }
19 | else {
20 | self.alpha = 1;
21 | }
22 | }
23 |
24 | @end
25 |
--------------------------------------------------------------------------------
/ShapesExample/ShapeKitExample/Controls/HighlightableShapeButton.h:
--------------------------------------------------------------------------------
1 | //
2 | // RoundCorneredButton.h
3 | // ShapesExample
4 | //
5 | // Created by Denys Telezhkin on 25.08.14.
6 | // Copyright (c) 2014 Denys Telezhkin. All rights reserved.
7 | //
8 |
9 | #import "DTShapeButton.h"
10 |
11 | @interface HighlightableShapeButton : DTShapeButton
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/ShapesExample/ShapeKitExample/Controls/HighlightableShapeButton.m:
--------------------------------------------------------------------------------
1 | //
2 | // RoundCorneredButton.m
3 | // ShapesExample
4 | //
5 | // Created by Denys Telezhkin on 25.08.14.
6 | // Copyright (c) 2014 Denys Telezhkin. All rights reserved.
7 | //
8 |
9 | #import "HighlightableShapeButton.h"
10 | #import "DTShapeView.h"
11 |
12 | @implementation HighlightableShapeButton
13 |
14 | -(void)setHighlighted:(BOOL)highlighted
15 | {
16 | if (highlighted)
17 | {
18 | self.shape.fillColor = self.tintColor;
19 | self.titleLabel.textColor = [UIColor whiteColor];
20 | }
21 | else {
22 | self.titleLabel.textColor = self.tintColor;
23 | self.shape.fillColor = [UIColor clearColor];
24 | }
25 | }
26 |
27 | @end
28 |
--------------------------------------------------------------------------------
/ShapesExample/ShapeKitExample/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" : "40x40",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "60x60",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "ipad",
20 | "size" : "29x29",
21 | "scale" : "1x"
22 | },
23 | {
24 | "idiom" : "ipad",
25 | "size" : "29x29",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "ipad",
30 | "size" : "40x40",
31 | "scale" : "1x"
32 | },
33 | {
34 | "idiom" : "ipad",
35 | "size" : "40x40",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "ipad",
40 | "size" : "76x76",
41 | "scale" : "1x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "76x76",
46 | "scale" : "2x"
47 | }
48 | ],
49 | "info" : {
50 | "version" : 1,
51 | "author" : "xcode"
52 | }
53 | }
--------------------------------------------------------------------------------
/ShapesExample/ShapeKitExample/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 | "orientation" : "portrait",
20 | "idiom" : "ipad",
21 | "extent" : "full-screen",
22 | "minimum-system-version" : "7.0",
23 | "scale" : "1x"
24 | },
25 | {
26 | "orientation" : "landscape",
27 | "idiom" : "ipad",
28 | "extent" : "full-screen",
29 | "minimum-system-version" : "7.0",
30 | "scale" : "1x"
31 | },
32 | {
33 | "orientation" : "portrait",
34 | "idiom" : "ipad",
35 | "extent" : "full-screen",
36 | "minimum-system-version" : "7.0",
37 | "scale" : "2x"
38 | },
39 | {
40 | "orientation" : "landscape",
41 | "idiom" : "ipad",
42 | "extent" : "full-screen",
43 | "minimum-system-version" : "7.0",
44 | "scale" : "2x"
45 | }
46 | ],
47 | "info" : {
48 | "version" : 1,
49 | "author" : "xcode"
50 | }
51 | }
--------------------------------------------------------------------------------
/ShapesExample/ShapeKitExample/Images.xcassets/cat_selfie.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x",
6 | "filename" : "cat_selfie.png"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | }
12 | ],
13 | "info" : {
14 | "version" : 1,
15 | "author" : "xcode"
16 | }
17 | }
--------------------------------------------------------------------------------
/ShapesExample/ShapeKitExample/Images.xcassets/cat_selfie.imageset/cat_selfie.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MLSDev/Shapes/35d19f56082a2cde54585b14671af6f4d58ba28e/ShapesExample/ShapeKitExample/Images.xcassets/cat_selfie.imageset/cat_selfie.png
--------------------------------------------------------------------------------
/ShapesExample/ShapeKitExample/ShapesExample-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 | UIMainStoryboardFile
28 | ShapesExample
29 | UIRequiredDeviceCapabilities
30 |
31 | armv7
32 |
33 | UISupportedInterfaceOrientations
34 |
35 | UIInterfaceOrientationPortrait
36 |
37 | UISupportedInterfaceOrientations~ipad
38 |
39 | UIInterfaceOrientationPortrait
40 | UIInterfaceOrientationPortraitUpsideDown
41 | UIInterfaceOrientationLandscapeLeft
42 | UIInterfaceOrientationLandscapeRight
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/ShapesExample/ShapeKitExample/ShapesExample-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_3_0
10 | #warning "This project uses features only available in iOS SDK 3.0 and later."
11 | #endif
12 |
13 | #ifdef __OBJC__
14 | #import
15 | #import
16 | #endif
17 |
--------------------------------------------------------------------------------
/ShapesExample/ShapeKitExample/ShapesExample.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 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
175 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
--------------------------------------------------------------------------------
/ShapesExample/ShapeKitExample/en.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /* Localized versions of Info.plist keys */
2 |
3 |
--------------------------------------------------------------------------------
/ShapesExample/ShapeKitExample/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // ShapesExample
4 | //
5 | // Created by Denys Telezhkin on 27.07.14.
6 | // Copyright (c) 2014 Denys Telezhkin. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | #import "AppDelegate.h"
12 |
13 | int main(int argc, char * argv[])
14 | {
15 | @autoreleasepool {
16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/ShapesExample/ShapeKitExampleTests/ShapesExampleTests-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 |
--------------------------------------------------------------------------------
/ShapesExample/ShapeKitExampleTests/Specs/ShapedView/ShapedViewGettersAndSettersTestCase.m:
--------------------------------------------------------------------------------
1 | //
2 | // ShapedViewGettersAndSettersTestCase.m
3 | // ShapesExample
4 | //
5 | // Created by Denys Telezhkin on 06.09.14.
6 | // Copyright (c) 2014 Denys Telezhkin. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "DTShapeView.h"
11 |
12 | @interface ShapedViewGettersAndSettersTestCase : XCTestCase
13 | @property (nonatomic, strong) DTShapeView * view;
14 |
15 | @end
16 |
17 | @implementation ShapedViewGettersAndSettersTestCase
18 |
19 | - (void)setUp
20 | {
21 | [super setUp];
22 | self.view = [DTShapeView new];
23 | }
24 |
25 | -(void)testFillColor
26 | {
27 | [self.view setFillColor:[UIColor redColor]];
28 | UIColor * color = [UIColor colorWithCGColor:self.view.shapeLayer.fillColor];
29 | XCTAssert([color isEqual:[UIColor redColor]]);
30 | }
31 |
32 | -(void)testStrokeColor
33 | {
34 | [self.view setStrokeColor:[UIColor blueColor]];
35 | UIColor * color = [UIColor colorWithCGColor:self.view.shapeLayer.strokeColor];
36 | XCTAssert([color isEqual:[UIColor blueColor]]);
37 | }
38 |
39 | -(void)testUsesEvenOddFillRule
40 | {
41 | [self.view setUsesEvenOddFillRule:YES];
42 | XCTAssert([self.view.shapeLayer.fillRule isEqualToString:kCAFillRuleEvenOdd]);
43 | }
44 |
45 | -(void)testFillRuleNonZero
46 | {
47 | [self.view setUsesEvenOddFillRule:NO];
48 | XCTAssert([self.view.shapeLayer.fillRule isEqualToString:kCAFillRuleNonZero]);
49 | }
50 |
51 | -(void)testLineCap
52 | {
53 | self.view.lineCap = kCGLineCapRound;
54 | XCTAssert([self.view.shapeLayer.lineCap isEqualToString:kCALineCapRound]);
55 |
56 | self.view.lineCap = kCGLineCapButt;
57 | XCTAssert([self.view.shapeLayer.lineCap isEqualToString:kCALineCapButt]);
58 | }
59 |
60 | -(void)testLineJoin
61 | {
62 | self.view.lineJoin = kCGLineJoinBevel;
63 | XCTAssert([self.view.shapeLayer.lineJoin isEqualToString:kCALineJoinBevel]);
64 |
65 | self.view.lineJoin = kCGLineJoinMiter;
66 | XCTAssert([self.view.shapeLayer.lineJoin isEqualToString:kCALineJoinMiter]);
67 | }
68 |
69 | @end
70 |
--------------------------------------------------------------------------------
/ShapesExample/ShapeKitExampleTests/Specs/ShapedView/ShapedViewPathTestCase.m:
--------------------------------------------------------------------------------
1 | //
2 | // ShapedViewTestCase.m
3 | // ShapesExample
4 | //
5 | // Created by Denys Telezhkin on 03.08.14.
6 | // Copyright (c) 2014 Denys Telezhkin. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "DTShapeView.h"
11 |
12 | @interface ShapedViewPathTestCase : XCTestCase
13 | @property (nonatomic, strong) DTShapeView * view;
14 |
15 | @end
16 |
17 | @implementation ShapedViewPathTestCase
18 |
19 | - (void)setUp
20 | {
21 | [super setUp];
22 |
23 | UIBezierPath * path = [UIBezierPath bezierPath];
24 | path.lineWidth = 2;
25 | path.lineCapStyle = kCGLineCapRound;
26 | path.lineJoinStyle = kCGLineJoinRound;
27 | path.miterLimit = 6;
28 | path.usesEvenOddFillRule = YES;
29 |
30 | self.view = [DTShapeView new];
31 | [self.view setPath:path];
32 | }
33 |
34 | -(void)testLineWidth
35 | {
36 | XCTAssert(self.view.shapeLayer.lineWidth == 2);
37 | }
38 |
39 | -(void)testLineCapStyle
40 | {
41 | XCTAssert([self.view.shapeLayer.lineCap isEqualToString:kCALineCapRound]);
42 | }
43 |
44 | -(void)testLineJoinStyle
45 | {
46 | XCTAssert([self.view.shapeLayer.lineJoin isEqualToString:kCALineJoinRound]);
47 | }
48 |
49 | -(void)testMiterLimit
50 | {
51 | XCTAssert(self.view.shapeLayer.miterLimit == 6);
52 | }
53 |
54 | -(void)testEvenOddRule
55 | {
56 | XCTAssert([self.view.shapeLayer.fillRule isEqualToString:kCAFillRuleEvenOdd]);
57 | }
58 |
59 | @end
60 |
--------------------------------------------------------------------------------
/ShapesExample/ShapeKitExampleTests/en.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /* Localized versions of Info.plist keys */
2 |
3 |
--------------------------------------------------------------------------------
/ShapesExample/ShapesExample.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 9A20D58E198E0C47005D0F7D /* ShapedViewPathTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A20D58D198E0C47005D0F7D /* ShapedViewPathTestCase.m */; };
11 | 9A2C577319D2F4990055DD9B /* CAShapeLayer+UIBezierPath.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A2C576319D2F4990055DD9B /* CAShapeLayer+UIBezierPath.m */; };
12 | 9A2C577419D2F4990055DD9B /* CATransaction+AnimateWithDuration.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A2C576519D2F4990055DD9B /* CATransaction+AnimateWithDuration.m */; };
13 | 9A2C577519D2F4990055DD9B /* DTAnimatableShapeLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A2C576719D2F4990055DD9B /* DTAnimatableShapeLayer.m */; };
14 | 9A2C577619D2F4990055DD9B /* DTDimmingView.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A2C576919D2F4990055DD9B /* DTDimmingView.m */; };
15 | 9A2C577719D2F4990055DD9B /* DTGraphicsConverter.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A2C576B19D2F4990055DD9B /* DTGraphicsConverter.m */; };
16 | 9A2C577819D2F4990055DD9B /* DTProgressView.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A2C576D19D2F4990055DD9B /* DTProgressView.m */; };
17 | 9A2C577919D2F4990055DD9B /* DTShapeButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A2C576F19D2F4990055DD9B /* DTShapeButton.m */; };
18 | 9A2C577A19D2F4990055DD9B /* DTShapeView.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A2C577119D2F4990055DD9B /* DTShapeView.m */; };
19 | 9A5DF42719854B200034FF62 /* ShapesExample.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9A5DF42619854B200034FF62 /* ShapesExample.storyboard */; };
20 | 9A5DF42A198562C80034FF62 /* ProgressViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A5DF429198562C80034FF62 /* ProgressViewController.m */; };
21 | 9A79790D19974D1700E43B41 /* DimmingViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A79790C19974D1700E43B41 /* DimmingViewController.m */; };
22 | 9AA0172A19851133001A0666 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9AA0172919851133001A0666 /* Foundation.framework */; };
23 | 9AA0172C19851133001A0666 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9AA0172B19851133001A0666 /* CoreGraphics.framework */; };
24 | 9AA0172E19851133001A0666 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9AA0172D19851133001A0666 /* UIKit.framework */; };
25 | 9AA0173419851133001A0666 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 9AA0173219851133001A0666 /* InfoPlist.strings */; };
26 | 9AA0173619851133001A0666 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 9AA0173519851133001A0666 /* main.m */; };
27 | 9AA0173A19851133001A0666 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 9AA0173919851133001A0666 /* AppDelegate.m */; };
28 | 9AA0173C19851133001A0666 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9AA0173B19851133001A0666 /* Images.xcassets */; };
29 | 9AA0174319851133001A0666 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9AA0174219851133001A0666 /* XCTest.framework */; };
30 | 9AA0174419851133001A0666 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9AA0172919851133001A0666 /* Foundation.framework */; };
31 | 9AA0174519851133001A0666 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9AA0172D19851133001A0666 /* UIKit.framework */; };
32 | 9AA0174D19851133001A0666 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 9AA0174B19851133001A0666 /* InfoPlist.strings */; };
33 | 9AA0296519B1F9FC0097AAE2 /* DimmableShapeButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 9AA0296419B1F9FC0097AAE2 /* DimmableShapeButton.m */; };
34 | 9AA0296819B200B40097AAE2 /* VoiceMemosRecordButtonViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9AA0296719B200B40097AAE2 /* VoiceMemosRecordButtonViewController.m */; };
35 | 9AAA136919BB07A90073354A /* ShapedViewGettersAndSettersTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 9AAA136819BB07A90073354A /* ShapedViewGettersAndSettersTestCase.m */; };
36 | 9AD1E75919ABA84800576928 /* DownloadButtonViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9AD1E75819ABA84800576928 /* DownloadButtonViewController.m */; };
37 | 9AD1E76119ABAD8000576928 /* HighlightableShapeButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 9AD1E76019ABAD8000576928 /* HighlightableShapeButton.m */; };
38 | /* End PBXBuildFile section */
39 |
40 | /* Begin PBXContainerItemProxy section */
41 | 9A216E8119D2F59600FF10F5 /* PBXContainerItemProxy */ = {
42 | isa = PBXContainerItemProxy;
43 | containerPortal = 9AA0171E19851133001A0666 /* Project object */;
44 | proxyType = 1;
45 | remoteGlobalIDString = 9AA0172519851133001A0666;
46 | remoteInfo = ShapesExample;
47 | };
48 | 9AA0174619851133001A0666 /* PBXContainerItemProxy */ = {
49 | isa = PBXContainerItemProxy;
50 | containerPortal = 9AA0171E19851133001A0666 /* Project object */;
51 | proxyType = 1;
52 | remoteGlobalIDString = 9AA0172519851133001A0666;
53 | remoteInfo = ShapeKitExample;
54 | };
55 | /* End PBXContainerItemProxy section */
56 |
57 | /* Begin PBXFileReference section */
58 | 9A20D58D198E0C47005D0F7D /* ShapedViewPathTestCase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ShapedViewPathTestCase.m; path = Specs/ShapedView/ShapedViewPathTestCase.m; sourceTree = ""; };
59 | 9A2C576219D2F4990055DD9B /* CAShapeLayer+UIBezierPath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "CAShapeLayer+UIBezierPath.h"; sourceTree = ""; };
60 | 9A2C576319D2F4990055DD9B /* CAShapeLayer+UIBezierPath.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "CAShapeLayer+UIBezierPath.m"; sourceTree = ""; };
61 | 9A2C576419D2F4990055DD9B /* CATransaction+AnimateWithDuration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "CATransaction+AnimateWithDuration.h"; sourceTree = ""; };
62 | 9A2C576519D2F4990055DD9B /* CATransaction+AnimateWithDuration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "CATransaction+AnimateWithDuration.m"; sourceTree = ""; };
63 | 9A2C576619D2F4990055DD9B /* DTAnimatableShapeLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DTAnimatableShapeLayer.h; sourceTree = ""; };
64 | 9A2C576719D2F4990055DD9B /* DTAnimatableShapeLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DTAnimatableShapeLayer.m; sourceTree = ""; };
65 | 9A2C576819D2F4990055DD9B /* DTDimmingView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DTDimmingView.h; sourceTree = ""; };
66 | 9A2C576919D2F4990055DD9B /* DTDimmingView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DTDimmingView.m; sourceTree = ""; };
67 | 9A2C576A19D2F4990055DD9B /* DTGraphicsConverter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DTGraphicsConverter.h; sourceTree = ""; };
68 | 9A2C576B19D2F4990055DD9B /* DTGraphicsConverter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DTGraphicsConverter.m; sourceTree = ""; };
69 | 9A2C576C19D2F4990055DD9B /* DTProgressView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DTProgressView.h; sourceTree = ""; };
70 | 9A2C576D19D2F4990055DD9B /* DTProgressView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DTProgressView.m; sourceTree = ""; };
71 | 9A2C576E19D2F4990055DD9B /* DTShapeButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DTShapeButton.h; sourceTree = ""; };
72 | 9A2C576F19D2F4990055DD9B /* DTShapeButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DTShapeButton.m; sourceTree = ""; };
73 | 9A2C577019D2F4990055DD9B /* DTShapeView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DTShapeView.h; sourceTree = ""; };
74 | 9A2C577119D2F4990055DD9B /* DTShapeView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DTShapeView.m; sourceTree = ""; };
75 | 9A2C577219D2F4990055DD9B /* Shapes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Shapes.h; sourceTree = ""; };
76 | 9A5DF42619854B200034FF62 /* ShapesExample.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = ShapesExample.storyboard; sourceTree = ""; };
77 | 9A5DF428198562C80034FF62 /* ProgressViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ProgressViewController.h; path = Controllers/ProgressViewController.h; sourceTree = ""; };
78 | 9A5DF429198562C80034FF62 /* ProgressViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ProgressViewController.m; path = Controllers/ProgressViewController.m; sourceTree = ""; };
79 | 9A79790B19974D1700E43B41 /* DimmingViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DimmingViewController.h; path = Controllers/DimmingViewController.h; sourceTree = ""; };
80 | 9A79790C19974D1700E43B41 /* DimmingViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DimmingViewController.m; path = Controllers/DimmingViewController.m; sourceTree = ""; };
81 | 9AA0172619851133001A0666 /* ShapesExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ShapesExample.app; sourceTree = BUILT_PRODUCTS_DIR; };
82 | 9AA0172919851133001A0666 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
83 | 9AA0172B19851133001A0666 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
84 | 9AA0172D19851133001A0666 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
85 | 9AA0173119851133001A0666 /* ShapesExample-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "ShapesExample-Info.plist"; sourceTree = ""; };
86 | 9AA0173319851133001A0666 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; };
87 | 9AA0173519851133001A0666 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
88 | 9AA0173719851133001A0666 /* ShapesExample-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ShapesExample-Prefix.pch"; sourceTree = ""; };
89 | 9AA0173819851133001A0666 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
90 | 9AA0173919851133001A0666 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
91 | 9AA0173B19851133001A0666 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; };
92 | 9AA0174119851133001A0666 /* ShapesTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ShapesTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
93 | 9AA0174219851133001A0666 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
94 | 9AA0174A19851133001A0666 /* ShapesExampleTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "ShapesExampleTests-Info.plist"; sourceTree = ""; };
95 | 9AA0174C19851133001A0666 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; };
96 | 9AA0296319B1F9FC0097AAE2 /* DimmableShapeButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DimmableShapeButton.h; path = Controls/DimmableShapeButton.h; sourceTree = ""; };
97 | 9AA0296419B1F9FC0097AAE2 /* DimmableShapeButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DimmableShapeButton.m; path = Controls/DimmableShapeButton.m; sourceTree = ""; };
98 | 9AA0296619B200B40097AAE2 /* VoiceMemosRecordButtonViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VoiceMemosRecordButtonViewController.h; path = Controllers/VoiceMemosRecordButtonViewController.h; sourceTree = ""; };
99 | 9AA0296719B200B40097AAE2 /* VoiceMemosRecordButtonViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = VoiceMemosRecordButtonViewController.m; path = Controllers/VoiceMemosRecordButtonViewController.m; sourceTree = ""; };
100 | 9AAA136819BB07A90073354A /* ShapedViewGettersAndSettersTestCase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ShapedViewGettersAndSettersTestCase.m; path = Specs/ShapedView/ShapedViewGettersAndSettersTestCase.m; sourceTree = ""; };
101 | 9AD1E75719ABA84800576928 /* DownloadButtonViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DownloadButtonViewController.h; path = Controllers/DownloadButtonViewController.h; sourceTree = ""; };
102 | 9AD1E75819ABA84800576928 /* DownloadButtonViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DownloadButtonViewController.m; path = Controllers/DownloadButtonViewController.m; sourceTree = ""; };
103 | 9AD1E75F19ABAD8000576928 /* HighlightableShapeButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HighlightableShapeButton.h; path = Controls/HighlightableShapeButton.h; sourceTree = ""; };
104 | 9AD1E76019ABAD8000576928 /* HighlightableShapeButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = HighlightableShapeButton.m; path = Controls/HighlightableShapeButton.m; sourceTree = ""; };
105 | /* End PBXFileReference section */
106 |
107 | /* Begin PBXFrameworksBuildPhase section */
108 | 9AA0172319851133001A0666 /* Frameworks */ = {
109 | isa = PBXFrameworksBuildPhase;
110 | buildActionMask = 2147483647;
111 | files = (
112 | 9AA0172C19851133001A0666 /* CoreGraphics.framework in Frameworks */,
113 | 9AA0172E19851133001A0666 /* UIKit.framework in Frameworks */,
114 | 9AA0172A19851133001A0666 /* Foundation.framework in Frameworks */,
115 | );
116 | runOnlyForDeploymentPostprocessing = 0;
117 | };
118 | 9AA0173E19851133001A0666 /* Frameworks */ = {
119 | isa = PBXFrameworksBuildPhase;
120 | buildActionMask = 2147483647;
121 | files = (
122 | 9AA0174319851133001A0666 /* XCTest.framework in Frameworks */,
123 | 9AA0174519851133001A0666 /* UIKit.framework in Frameworks */,
124 | 9AA0174419851133001A0666 /* Foundation.framework in Frameworks */,
125 | );
126 | runOnlyForDeploymentPostprocessing = 0;
127 | };
128 | /* End PBXFrameworksBuildPhase section */
129 |
130 | /* Begin PBXGroup section */
131 | 9A20D58C198E0C24005D0F7D /* Specs */ = {
132 | isa = PBXGroup;
133 | children = (
134 | 9A20D58D198E0C47005D0F7D /* ShapedViewPathTestCase.m */,
135 | 9AAA136819BB07A90073354A /* ShapedViewGettersAndSettersTestCase.m */,
136 | );
137 | name = Specs;
138 | sourceTree = "";
139 | };
140 | 9A2C576119D2F4990055DD9B /* Shapes */ = {
141 | isa = PBXGroup;
142 | children = (
143 | 9A2C576219D2F4990055DD9B /* CAShapeLayer+UIBezierPath.h */,
144 | 9A2C576319D2F4990055DD9B /* CAShapeLayer+UIBezierPath.m */,
145 | 9A2C576419D2F4990055DD9B /* CATransaction+AnimateWithDuration.h */,
146 | 9A2C576519D2F4990055DD9B /* CATransaction+AnimateWithDuration.m */,
147 | 9A2C576619D2F4990055DD9B /* DTAnimatableShapeLayer.h */,
148 | 9A2C576719D2F4990055DD9B /* DTAnimatableShapeLayer.m */,
149 | 9A2C576819D2F4990055DD9B /* DTDimmingView.h */,
150 | 9A2C576919D2F4990055DD9B /* DTDimmingView.m */,
151 | 9A2C576A19D2F4990055DD9B /* DTGraphicsConverter.h */,
152 | 9A2C576B19D2F4990055DD9B /* DTGraphicsConverter.m */,
153 | 9A2C576C19D2F4990055DD9B /* DTProgressView.h */,
154 | 9A2C576D19D2F4990055DD9B /* DTProgressView.m */,
155 | 9A2C576E19D2F4990055DD9B /* DTShapeButton.h */,
156 | 9A2C576F19D2F4990055DD9B /* DTShapeButton.m */,
157 | 9A2C577019D2F4990055DD9B /* DTShapeView.h */,
158 | 9A2C577119D2F4990055DD9B /* DTShapeView.m */,
159 | 9A2C577219D2F4990055DD9B /* Shapes.h */,
160 | );
161 | name = Shapes;
162 | path = ../Shapes;
163 | sourceTree = "";
164 | };
165 | 9A5DF42B198562CD0034FF62 /* Progress */ = {
166 | isa = PBXGroup;
167 | children = (
168 | 9A5DF428198562C80034FF62 /* ProgressViewController.h */,
169 | 9A5DF429198562C80034FF62 /* ProgressViewController.m */,
170 | );
171 | name = Progress;
172 | sourceTree = "";
173 | };
174 | 9A79790A19974C7D00E43B41 /* Dimming */ = {
175 | isa = PBXGroup;
176 | children = (
177 | 9A79790B19974D1700E43B41 /* DimmingViewController.h */,
178 | 9A79790C19974D1700E43B41 /* DimmingViewController.m */,
179 | );
180 | name = Dimming;
181 | sourceTree = "";
182 | };
183 | 9AA0171D19851133001A0666 = {
184 | isa = PBXGroup;
185 | children = (
186 | 9A2C576119D2F4990055DD9B /* Shapes */,
187 | 9AA0172F19851133001A0666 /* ShapesExample */,
188 | 9AA0174819851133001A0666 /* ShapesTests */,
189 | 9AA0172819851133001A0666 /* Frameworks */,
190 | 9AA0172719851133001A0666 /* Products */,
191 | );
192 | sourceTree = "";
193 | };
194 | 9AA0172719851133001A0666 /* Products */ = {
195 | isa = PBXGroup;
196 | children = (
197 | 9AA0172619851133001A0666 /* ShapesExample.app */,
198 | 9AA0174119851133001A0666 /* ShapesTests.xctest */,
199 | );
200 | name = Products;
201 | sourceTree = "";
202 | };
203 | 9AA0172819851133001A0666 /* Frameworks */ = {
204 | isa = PBXGroup;
205 | children = (
206 | 9AA0172919851133001A0666 /* Foundation.framework */,
207 | 9AA0172B19851133001A0666 /* CoreGraphics.framework */,
208 | 9AA0172D19851133001A0666 /* UIKit.framework */,
209 | 9AA0174219851133001A0666 /* XCTest.framework */,
210 | );
211 | name = Frameworks;
212 | sourceTree = "";
213 | };
214 | 9AA0172F19851133001A0666 /* ShapesExample */ = {
215 | isa = PBXGroup;
216 | children = (
217 | 9AA0173819851133001A0666 /* AppDelegate.h */,
218 | 9AA0173919851133001A0666 /* AppDelegate.m */,
219 | 9A5DF42619854B200034FF62 /* ShapesExample.storyboard */,
220 | 9A79790A19974C7D00E43B41 /* Dimming */,
221 | 9A5DF42B198562CD0034FF62 /* Progress */,
222 | 9AD1E75619ABA82900576928 /* Animated buttons */,
223 | 9AA0173B19851133001A0666 /* Images.xcassets */,
224 | 9AA0173019851133001A0666 /* Supporting Files */,
225 | );
226 | name = ShapesExample;
227 | path = ShapeKitExample;
228 | sourceTree = "";
229 | };
230 | 9AA0173019851133001A0666 /* Supporting Files */ = {
231 | isa = PBXGroup;
232 | children = (
233 | 9AA0173119851133001A0666 /* ShapesExample-Info.plist */,
234 | 9AA0173219851133001A0666 /* InfoPlist.strings */,
235 | 9AA0173519851133001A0666 /* main.m */,
236 | 9AA0173719851133001A0666 /* ShapesExample-Prefix.pch */,
237 | );
238 | name = "Supporting Files";
239 | sourceTree = "";
240 | };
241 | 9AA0174819851133001A0666 /* ShapesTests */ = {
242 | isa = PBXGroup;
243 | children = (
244 | 9A20D58C198E0C24005D0F7D /* Specs */,
245 | 9AA0174919851133001A0666 /* Supporting Files */,
246 | );
247 | name = ShapesTests;
248 | path = ShapeKitExampleTests;
249 | sourceTree = "";
250 | };
251 | 9AA0174919851133001A0666 /* Supporting Files */ = {
252 | isa = PBXGroup;
253 | children = (
254 | 9AA0174A19851133001A0666 /* ShapesExampleTests-Info.plist */,
255 | 9AA0174B19851133001A0666 /* InfoPlist.strings */,
256 | );
257 | name = "Supporting Files";
258 | sourceTree = "";
259 | };
260 | 9AD1E75619ABA82900576928 /* Animated buttons */ = {
261 | isa = PBXGroup;
262 | children = (
263 | 9AD1E75E19ABAD3B00576928 /* Buttons */,
264 | 9AD1E75719ABA84800576928 /* DownloadButtonViewController.h */,
265 | 9AD1E75819ABA84800576928 /* DownloadButtonViewController.m */,
266 | 9AA0296619B200B40097AAE2 /* VoiceMemosRecordButtonViewController.h */,
267 | 9AA0296719B200B40097AAE2 /* VoiceMemosRecordButtonViewController.m */,
268 | );
269 | name = "Animated buttons";
270 | sourceTree = "";
271 | };
272 | 9AD1E75E19ABAD3B00576928 /* Buttons */ = {
273 | isa = PBXGroup;
274 | children = (
275 | 9AD1E75F19ABAD8000576928 /* HighlightableShapeButton.h */,
276 | 9AD1E76019ABAD8000576928 /* HighlightableShapeButton.m */,
277 | 9AA0296319B1F9FC0097AAE2 /* DimmableShapeButton.h */,
278 | 9AA0296419B1F9FC0097AAE2 /* DimmableShapeButton.m */,
279 | );
280 | name = Buttons;
281 | sourceTree = "";
282 | };
283 | /* End PBXGroup section */
284 |
285 | /* Begin PBXNativeTarget section */
286 | 9AA0172519851133001A0666 /* ShapesExample */ = {
287 | isa = PBXNativeTarget;
288 | buildConfigurationList = 9AA0175219851133001A0666 /* Build configuration list for PBXNativeTarget "ShapesExample" */;
289 | buildPhases = (
290 | 9AA0172219851133001A0666 /* Sources */,
291 | 9AA0172319851133001A0666 /* Frameworks */,
292 | 9AA0172419851133001A0666 /* Resources */,
293 | );
294 | buildRules = (
295 | );
296 | dependencies = (
297 | );
298 | name = ShapesExample;
299 | productName = ShapeKitExample;
300 | productReference = 9AA0172619851133001A0666 /* ShapesExample.app */;
301 | productType = "com.apple.product-type.application";
302 | };
303 | 9AA0174019851133001A0666 /* ShapesTests */ = {
304 | isa = PBXNativeTarget;
305 | buildConfigurationList = 9AA0175519851133001A0666 /* Build configuration list for PBXNativeTarget "ShapesTests" */;
306 | buildPhases = (
307 | 9AA0173D19851133001A0666 /* Sources */,
308 | 9AA0173E19851133001A0666 /* Frameworks */,
309 | 9AA0173F19851133001A0666 /* Resources */,
310 | );
311 | buildRules = (
312 | );
313 | dependencies = (
314 | 9AA0174719851133001A0666 /* PBXTargetDependency */,
315 | 9A216E8219D2F59600FF10F5 /* PBXTargetDependency */,
316 | );
317 | name = ShapesTests;
318 | productName = ShapeKitExampleTests;
319 | productReference = 9AA0174119851133001A0666 /* ShapesTests.xctest */;
320 | productType = "com.apple.product-type.bundle.unit-test";
321 | };
322 | /* End PBXNativeTarget section */
323 |
324 | /* Begin PBXProject section */
325 | 9AA0171E19851133001A0666 /* Project object */ = {
326 | isa = PBXProject;
327 | attributes = {
328 | LastUpgradeCheck = 0700;
329 | ORGANIZATIONNAME = "Denys Telezhkin";
330 | TargetAttributes = {
331 | 9AA0174019851133001A0666 = {
332 | TestTargetID = 9AA0172519851133001A0666;
333 | };
334 | };
335 | };
336 | buildConfigurationList = 9AA0172119851133001A0666 /* Build configuration list for PBXProject "ShapesExample" */;
337 | compatibilityVersion = "Xcode 3.2";
338 | developmentRegion = English;
339 | hasScannedForEncodings = 0;
340 | knownRegions = (
341 | en,
342 | );
343 | mainGroup = 9AA0171D19851133001A0666;
344 | productRefGroup = 9AA0172719851133001A0666 /* Products */;
345 | projectDirPath = "";
346 | projectRoot = "";
347 | targets = (
348 | 9AA0172519851133001A0666 /* ShapesExample */,
349 | 9AA0174019851133001A0666 /* ShapesTests */,
350 | );
351 | };
352 | /* End PBXProject section */
353 |
354 | /* Begin PBXResourcesBuildPhase section */
355 | 9AA0172419851133001A0666 /* Resources */ = {
356 | isa = PBXResourcesBuildPhase;
357 | buildActionMask = 2147483647;
358 | files = (
359 | 9A5DF42719854B200034FF62 /* ShapesExample.storyboard in Resources */,
360 | 9AA0173419851133001A0666 /* InfoPlist.strings in Resources */,
361 | 9AA0173C19851133001A0666 /* Images.xcassets in Resources */,
362 | );
363 | runOnlyForDeploymentPostprocessing = 0;
364 | };
365 | 9AA0173F19851133001A0666 /* Resources */ = {
366 | isa = PBXResourcesBuildPhase;
367 | buildActionMask = 2147483647;
368 | files = (
369 | 9AA0174D19851133001A0666 /* InfoPlist.strings in Resources */,
370 | );
371 | runOnlyForDeploymentPostprocessing = 0;
372 | };
373 | /* End PBXResourcesBuildPhase section */
374 |
375 | /* Begin PBXSourcesBuildPhase section */
376 | 9AA0172219851133001A0666 /* Sources */ = {
377 | isa = PBXSourcesBuildPhase;
378 | buildActionMask = 2147483647;
379 | files = (
380 | 9A2C577919D2F4990055DD9B /* DTShapeButton.m in Sources */,
381 | 9A2C577519D2F4990055DD9B /* DTAnimatableShapeLayer.m in Sources */,
382 | 9A5DF42A198562C80034FF62 /* ProgressViewController.m in Sources */,
383 | 9A2C577719D2F4990055DD9B /* DTGraphicsConverter.m in Sources */,
384 | 9A2C577619D2F4990055DD9B /* DTDimmingView.m in Sources */,
385 | 9AA0296519B1F9FC0097AAE2 /* DimmableShapeButton.m in Sources */,
386 | 9A2C577319D2F4990055DD9B /* CAShapeLayer+UIBezierPath.m in Sources */,
387 | 9AD1E75919ABA84800576928 /* DownloadButtonViewController.m in Sources */,
388 | 9A2C577419D2F4990055DD9B /* CATransaction+AnimateWithDuration.m in Sources */,
389 | 9AA0173A19851133001A0666 /* AppDelegate.m in Sources */,
390 | 9AD1E76119ABAD8000576928 /* HighlightableShapeButton.m in Sources */,
391 | 9AA0296819B200B40097AAE2 /* VoiceMemosRecordButtonViewController.m in Sources */,
392 | 9A2C577A19D2F4990055DD9B /* DTShapeView.m in Sources */,
393 | 9A2C577819D2F4990055DD9B /* DTProgressView.m in Sources */,
394 | 9A79790D19974D1700E43B41 /* DimmingViewController.m in Sources */,
395 | 9AA0173619851133001A0666 /* main.m in Sources */,
396 | );
397 | runOnlyForDeploymentPostprocessing = 0;
398 | };
399 | 9AA0173D19851133001A0666 /* Sources */ = {
400 | isa = PBXSourcesBuildPhase;
401 | buildActionMask = 2147483647;
402 | files = (
403 | 9A20D58E198E0C47005D0F7D /* ShapedViewPathTestCase.m in Sources */,
404 | 9AAA136919BB07A90073354A /* ShapedViewGettersAndSettersTestCase.m in Sources */,
405 | );
406 | runOnlyForDeploymentPostprocessing = 0;
407 | };
408 | /* End PBXSourcesBuildPhase section */
409 |
410 | /* Begin PBXTargetDependency section */
411 | 9A216E8219D2F59600FF10F5 /* PBXTargetDependency */ = {
412 | isa = PBXTargetDependency;
413 | target = 9AA0172519851133001A0666 /* ShapesExample */;
414 | targetProxy = 9A216E8119D2F59600FF10F5 /* PBXContainerItemProxy */;
415 | };
416 | 9AA0174719851133001A0666 /* PBXTargetDependency */ = {
417 | isa = PBXTargetDependency;
418 | target = 9AA0172519851133001A0666 /* ShapesExample */;
419 | targetProxy = 9AA0174619851133001A0666 /* PBXContainerItemProxy */;
420 | };
421 | /* End PBXTargetDependency section */
422 |
423 | /* Begin PBXVariantGroup section */
424 | 9AA0173219851133001A0666 /* InfoPlist.strings */ = {
425 | isa = PBXVariantGroup;
426 | children = (
427 | 9AA0173319851133001A0666 /* en */,
428 | );
429 | name = InfoPlist.strings;
430 | sourceTree = "";
431 | };
432 | 9AA0174B19851133001A0666 /* InfoPlist.strings */ = {
433 | isa = PBXVariantGroup;
434 | children = (
435 | 9AA0174C19851133001A0666 /* en */,
436 | );
437 | name = InfoPlist.strings;
438 | sourceTree = "";
439 | };
440 | /* End PBXVariantGroup section */
441 |
442 | /* Begin XCBuildConfiguration section */
443 | 9AA0175019851133001A0666 /* Debug */ = {
444 | isa = XCBuildConfiguration;
445 | buildSettings = {
446 | ALWAYS_SEARCH_USER_PATHS = NO;
447 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
448 | CLANG_CXX_LIBRARY = "libc++";
449 | CLANG_ENABLE_MODULES = YES;
450 | CLANG_ENABLE_OBJC_ARC = YES;
451 | CLANG_WARN_BOOL_CONVERSION = YES;
452 | CLANG_WARN_CONSTANT_CONVERSION = YES;
453 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
454 | CLANG_WARN_EMPTY_BODY = YES;
455 | CLANG_WARN_ENUM_CONVERSION = YES;
456 | CLANG_WARN_INT_CONVERSION = YES;
457 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
458 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
459 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
460 | COPY_PHASE_STRIP = NO;
461 | ENABLE_TESTABILITY = YES;
462 | GCC_C_LANGUAGE_STANDARD = gnu99;
463 | GCC_DYNAMIC_NO_PIC = NO;
464 | GCC_OPTIMIZATION_LEVEL = 0;
465 | GCC_PREPROCESSOR_DEFINITIONS = (
466 | "DEBUG=1",
467 | "$(inherited)",
468 | );
469 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
470 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
471 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
472 | GCC_WARN_UNDECLARED_SELECTOR = YES;
473 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
474 | GCC_WARN_UNUSED_FUNCTION = YES;
475 | GCC_WARN_UNUSED_VARIABLE = YES;
476 | IPHONEOS_DEPLOYMENT_TARGET = 8;
477 | ONLY_ACTIVE_ARCH = YES;
478 | SDKROOT = iphoneos;
479 | TARGETED_DEVICE_FAMILY = "1,2";
480 | };
481 | name = Debug;
482 | };
483 | 9AA0175119851133001A0666 /* Release */ = {
484 | isa = XCBuildConfiguration;
485 | buildSettings = {
486 | ALWAYS_SEARCH_USER_PATHS = NO;
487 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
488 | CLANG_CXX_LIBRARY = "libc++";
489 | CLANG_ENABLE_MODULES = YES;
490 | CLANG_ENABLE_OBJC_ARC = YES;
491 | CLANG_WARN_BOOL_CONVERSION = YES;
492 | CLANG_WARN_CONSTANT_CONVERSION = YES;
493 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
494 | CLANG_WARN_EMPTY_BODY = YES;
495 | CLANG_WARN_ENUM_CONVERSION = YES;
496 | CLANG_WARN_INT_CONVERSION = YES;
497 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
498 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
499 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
500 | COPY_PHASE_STRIP = YES;
501 | ENABLE_NS_ASSERTIONS = NO;
502 | GCC_C_LANGUAGE_STANDARD = gnu99;
503 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
504 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
505 | GCC_WARN_UNDECLARED_SELECTOR = YES;
506 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
507 | GCC_WARN_UNUSED_FUNCTION = YES;
508 | GCC_WARN_UNUSED_VARIABLE = YES;
509 | IPHONEOS_DEPLOYMENT_TARGET = 8;
510 | SDKROOT = iphoneos;
511 | TARGETED_DEVICE_FAMILY = "1,2";
512 | VALIDATE_PRODUCT = YES;
513 | };
514 | name = Release;
515 | };
516 | 9AA0175319851133001A0666 /* Debug */ = {
517 | isa = XCBuildConfiguration;
518 | buildSettings = {
519 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
520 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
521 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
522 | GCC_PREFIX_HEADER = "ShapeKitExample/ShapesExample-Prefix.pch";
523 | INFOPLIST_FILE = "ShapeKitExample/ShapesExample-Info.plist";
524 | IPHONEOS_DEPLOYMENT_TARGET = 8;
525 | PRODUCT_BUNDLE_IDENTIFIER = "com.mlsdev.${PRODUCT_NAME:rfc1034identifier}";
526 | PRODUCT_NAME = "$(TARGET_NAME)";
527 | TARGETED_DEVICE_FAMILY = 1;
528 | WRAPPER_EXTENSION = app;
529 | };
530 | name = Debug;
531 | };
532 | 9AA0175419851133001A0666 /* Release */ = {
533 | isa = XCBuildConfiguration;
534 | buildSettings = {
535 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
536 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
537 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
538 | GCC_PREFIX_HEADER = "ShapeKitExample/ShapesExample-Prefix.pch";
539 | INFOPLIST_FILE = "ShapeKitExample/ShapesExample-Info.plist";
540 | IPHONEOS_DEPLOYMENT_TARGET = 8;
541 | PRODUCT_BUNDLE_IDENTIFIER = "com.mlsdev.${PRODUCT_NAME:rfc1034identifier}";
542 | PRODUCT_NAME = "$(TARGET_NAME)";
543 | TARGETED_DEVICE_FAMILY = 1;
544 | WRAPPER_EXTENSION = app;
545 | };
546 | name = Release;
547 | };
548 | 9AA0175619851133001A0666 /* Debug */ = {
549 | isa = XCBuildConfiguration;
550 | buildSettings = {
551 | BUNDLE_LOADER = "$(TEST_HOST)";
552 | FRAMEWORK_SEARCH_PATHS = (
553 | "$(SDKROOT)/Developer/Library/Frameworks",
554 | "$(inherited)",
555 | "$(DEVELOPER_FRAMEWORKS_DIR)",
556 | );
557 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
558 | GCC_PREFIX_HEADER = "ShapeKitExample/ShapesExample-Prefix.pch";
559 | GCC_PREPROCESSOR_DEFINITIONS = (
560 | "DEBUG=1",
561 | "$(inherited)",
562 | );
563 | INFOPLIST_FILE = "ShapeKitExampleTests/ShapesExampleTests-Info.plist";
564 | PRODUCT_BUNDLE_IDENTIFIER = "com.mlsdev.${PRODUCT_NAME:rfc1034identifier}";
565 | PRODUCT_NAME = "$(TARGET_NAME)";
566 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ShapesExample.app/ShapesExample";
567 | WRAPPER_EXTENSION = xctest;
568 | };
569 | name = Debug;
570 | };
571 | 9AA0175719851133001A0666 /* Release */ = {
572 | isa = XCBuildConfiguration;
573 | buildSettings = {
574 | BUNDLE_LOADER = "$(TEST_HOST)";
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 = "ShapeKitExample/ShapesExample-Prefix.pch";
582 | INFOPLIST_FILE = "ShapeKitExampleTests/ShapesExampleTests-Info.plist";
583 | PRODUCT_BUNDLE_IDENTIFIER = "com.mlsdev.${PRODUCT_NAME:rfc1034identifier}";
584 | PRODUCT_NAME = "$(TARGET_NAME)";
585 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ShapesExample.app/ShapesExample";
586 | WRAPPER_EXTENSION = xctest;
587 | };
588 | name = Release;
589 | };
590 | /* End XCBuildConfiguration section */
591 |
592 | /* Begin XCConfigurationList section */
593 | 9AA0172119851133001A0666 /* Build configuration list for PBXProject "ShapesExample" */ = {
594 | isa = XCConfigurationList;
595 | buildConfigurations = (
596 | 9AA0175019851133001A0666 /* Debug */,
597 | 9AA0175119851133001A0666 /* Release */,
598 | );
599 | defaultConfigurationIsVisible = 0;
600 | defaultConfigurationName = Release;
601 | };
602 | 9AA0175219851133001A0666 /* Build configuration list for PBXNativeTarget "ShapesExample" */ = {
603 | isa = XCConfigurationList;
604 | buildConfigurations = (
605 | 9AA0175319851133001A0666 /* Debug */,
606 | 9AA0175419851133001A0666 /* Release */,
607 | );
608 | defaultConfigurationIsVisible = 0;
609 | defaultConfigurationName = Release;
610 | };
611 | 9AA0175519851133001A0666 /* Build configuration list for PBXNativeTarget "ShapesTests" */ = {
612 | isa = XCConfigurationList;
613 | buildConfigurations = (
614 | 9AA0175619851133001A0666 /* Debug */,
615 | 9AA0175719851133001A0666 /* Release */,
616 | );
617 | defaultConfigurationIsVisible = 0;
618 | defaultConfigurationName = Release;
619 | };
620 | /* End XCConfigurationList section */
621 | };
622 | rootObject = 9AA0171E19851133001A0666 /* Project object */;
623 | }
624 |
--------------------------------------------------------------------------------
/ShapesExample/ShapesExample.xcodeproj/xcshareddata/xcschemes/ShapesExample.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 |
--------------------------------------------------------------------------------
/ShapesExample/ShapesExample.xcodeproj/xcshareddata/xcschemes/ShapesTests.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
14 |
15 |
17 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
39 |
40 |
41 |
42 |
48 |
49 |
51 |
52 |
55 |
56 |
57 |
--------------------------------------------------------------------------------