Skip to content
This repository
Browse code

Heavy refactor, removes the MSDraggableView class (refactoring it int…

…o the navigation controller) and allows for the navigation pane to be opened from the top and right in addition to the left
  • Loading branch information...
commit 34f59d0ced4c5c05b5614c80f8a9d0dd12e8a86a 1 parent 18599c1
Eric Horacek authored February 11, 2013
3  .gitmodules
... ...
@@ -0,0 +1,3 @@
  1
+[submodule "Vendor/PRTween"]
  2
+	path = Vendor/PRTween
  3
+	url = https://github.com/dominikhofmann/PRTween.git
38  Example/Example/Example.xcodeproj/project.pbxproj
@@ -15,7 +15,6 @@
15 15
 		3A1166AB167E8C3E00DBD12B /* MSAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A1166AA167E8C3E00DBD12B /* MSAppDelegate.m */; };
16 16
 		3A1166FE167E8DBF00DBD12B /* MSMasterViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A1166FB167E8DBF00DBD12B /* MSMasterViewController.m */; };
17 17
 		3A116729167E8EF300DBD12B /* MSNavigationPaneViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A116725167E8EF300DBD12B /* MSNavigationPaneViewController.m */; };
18  
-		3A11672A167E8EF300DBD12B /* MSDraggableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A116727167E8EF300DBD12B /* MSDraggableView.m */; };
19 18
 		3A11672C167E8F1900DBD12B /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A11672B167E8F1900DBD12B /* QuartzCore.framework */; };
20 19
 		3A11686D167EAE0E00DBD12B /* MSMonospaceViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A11686C167EAE0E00DBD12B /* MSMonospaceViewController.m */; };
21 20
 		3A5AC61E16A20575006F5A3F /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 3A5AC60F16A20575006F5A3F /* Default-568h@2x.png */; };
@@ -33,6 +32,8 @@
33 32
 		3A5AC62A16A20575006F5A3F /* iTunesArtwork@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 3A5AC61B16A20575006F5A3F /* iTunesArtwork@2x.png */; };
34 33
 		3A5AC62B16A20575006F5A3F /* MSBarButtonIconNavigationPane.png in Resources */ = {isa = PBXBuildFile; fileRef = 3A5AC61C16A20575006F5A3F /* MSBarButtonIconNavigationPane.png */; };
35 34
 		3A5AC62C16A20575006F5A3F /* MSBarButtonIconNavigationPane@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 3A5AC61D16A20575006F5A3F /* MSBarButtonIconNavigationPane@2x.png */; };
  35
+		3AE8F93B16C86D1100D724F3 /* PRTween.m in Sources */ = {isa = PBXBuildFile; fileRef = 3AE8F93816C86D1100D724F3 /* PRTween.m */; };
  36
+		3AE8F93C16C86D1100D724F3 /* PRTweenTimingFunctions.m in Sources */ = {isa = PBXBuildFile; fileRef = 3AE8F93A16C86D1100D724F3 /* PRTweenTimingFunctions.m */; };
36 37
 /* End PBXBuildFile section */
37 38
 
38 39
 /* Begin PBXFileReference section */
@@ -49,8 +50,6 @@
49 50
 		3A1166FA167E8DBF00DBD12B /* MSMasterViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MSMasterViewController.h; path = ../Example/Example/MSMasterViewController.h; sourceTree = "<group>"; };
50 51
 		3A1166FB167E8DBF00DBD12B /* MSMasterViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MSMasterViewController.m; path = ../Example/Example/MSMasterViewController.m; sourceTree = "<group>"; };
51 52
 		3A116725167E8EF300DBD12B /* MSNavigationPaneViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MSNavigationPaneViewController.m; path = ../../MSNavigationPaneViewController/MSNavigationPaneViewController.m; sourceTree = "<group>"; };
52  
-		3A116726167E8EF300DBD12B /* MSDraggableView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MSDraggableView.h; path = ../../MSNavigationPaneViewController/MSDraggableView.h; sourceTree = "<group>"; };
53  
-		3A116727167E8EF300DBD12B /* MSDraggableView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MSDraggableView.m; path = ../../MSNavigationPaneViewController/MSDraggableView.m; sourceTree = "<group>"; };
54 53
 		3A116728167E8EF300DBD12B /* MSNavigationPaneViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MSNavigationPaneViewController.h; path = ../../MSNavigationPaneViewController/MSNavigationPaneViewController.h; sourceTree = "<group>"; };
55 54
 		3A11672B167E8F1900DBD12B /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
56 55
 		3A11686B167EAE0E00DBD12B /* MSMonospaceViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MSMonospaceViewController.h; sourceTree = "<group>"; };
@@ -70,6 +69,10 @@
70 69
 		3A5AC61B16A20575006F5A3F /* iTunesArtwork@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "iTunesArtwork@2x.png"; sourceTree = "<group>"; };
71 70
 		3A5AC61C16A20575006F5A3F /* MSBarButtonIconNavigationPane.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = MSBarButtonIconNavigationPane.png; sourceTree = "<group>"; };
72 71
 		3A5AC61D16A20575006F5A3F /* MSBarButtonIconNavigationPane@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "MSBarButtonIconNavigationPane@2x.png"; sourceTree = "<group>"; };
  72
+		3AE8F93716C86D1100D724F3 /* PRTween.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PRTween.h; path = ../../Vendor/PRTween/lib/PRTween.h; sourceTree = "<group>"; };
  73
+		3AE8F93816C86D1100D724F3 /* PRTween.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PRTween.m; path = ../../Vendor/PRTween/lib/PRTween.m; sourceTree = "<group>"; };
  74
+		3AE8F93916C86D1100D724F3 /* PRTweenTimingFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PRTweenTimingFunctions.h; path = ../../Vendor/PRTween/lib/PRTweenTimingFunctions.h; sourceTree = "<group>"; };
  75
+		3AE8F93A16C86D1100D724F3 /* PRTweenTimingFunctions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PRTweenTimingFunctions.m; path = ../../Vendor/PRTween/lib/PRTweenTimingFunctions.m; sourceTree = "<group>"; };
73 76
 /* End PBXFileReference section */
74 77
 
75 78
 /* Begin PBXFrameworksBuildPhase section */
@@ -142,10 +145,8 @@
142 145
 		3A11670A167E8DD500DBD12B /* Vendor */ = {
143 146
 			isa = PBXGroup;
144 147
 			children = (
145  
-				3A116726167E8EF300DBD12B /* MSDraggableView.h */,
146  
-				3A116727167E8EF300DBD12B /* MSDraggableView.m */,
147  
-				3A116728167E8EF300DBD12B /* MSNavigationPaneViewController.h */,
148  
-				3A116725167E8EF300DBD12B /* MSNavigationPaneViewController.m */,
  148
+				3AE8F93516C86CD300D724F3 /* MSNavigationPaneViewController */,
  149
+				3AE8F93616C86CE200D724F3 /* PRTween */,
149 150
 			);
150 151
 			name = Vendor;
151 152
 			sourceTree = "<group>";
@@ -185,6 +186,26 @@
185 186
 			path = ../Images;
186 187
 			sourceTree = SOURCE_ROOT;
187 188
 		};
  189
+		3AE8F93516C86CD300D724F3 /* MSNavigationPaneViewController */ = {
  190
+			isa = PBXGroup;
  191
+			children = (
  192
+				3A116728167E8EF300DBD12B /* MSNavigationPaneViewController.h */,
  193
+				3A116725167E8EF300DBD12B /* MSNavigationPaneViewController.m */,
  194
+			);
  195
+			name = MSNavigationPaneViewController;
  196
+			sourceTree = "<group>";
  197
+		};
  198
+		3AE8F93616C86CE200D724F3 /* PRTween */ = {
  199
+			isa = PBXGroup;
  200
+			children = (
  201
+				3AE8F93716C86D1100D724F3 /* PRTween.h */,
  202
+				3AE8F93816C86D1100D724F3 /* PRTween.m */,
  203
+				3AE8F93916C86D1100D724F3 /* PRTweenTimingFunctions.h */,
  204
+				3AE8F93A16C86D1100D724F3 /* PRTweenTimingFunctions.m */,
  205
+			);
  206
+			name = PRTween;
  207
+			sourceTree = "<group>";
  208
+		};
188 209
 /* End PBXGroup section */
189 210
 
190 211
 /* Begin PBXNativeTarget section */
@@ -267,8 +288,9 @@
267 288
 				3A1166AB167E8C3E00DBD12B /* MSAppDelegate.m in Sources */,
268 289
 				3A1166FE167E8DBF00DBD12B /* MSMasterViewController.m in Sources */,
269 290
 				3A116729167E8EF300DBD12B /* MSNavigationPaneViewController.m in Sources */,
270  
-				3A11672A167E8EF300DBD12B /* MSDraggableView.m in Sources */,
271 291
 				3A11686D167EAE0E00DBD12B /* MSMonospaceViewController.m in Sources */,
  292
+				3AE8F93B16C86D1100D724F3 /* PRTween.m in Sources */,
  293
+				3AE8F93C16C86D1100D724F3 /* PRTweenTimingFunctions.m in Sources */,
272 294
 			);
273 295
 			runOnlyForDeploymentPostprocessing = 0;
274 296
 		};
3  Example/Example/Example/MSAppDelegate.m
@@ -41,6 +41,9 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
41 41
     
42 42
     self.navigationPaneViewController.masterViewController = masterViewController;
43 43
     
  44
+    self.navigationPaneViewController.openDirection = MSNavigationPaneOpenDirectionLeft;
  45
+    self.navigationPaneViewController.paneViewSlideOffAnimationEnabled = NO;
  46
+    
44 47
     [masterViewController transitionToViewController:MSPaneViewControllerTypeAppearanceNone];
45 48
     
46 49
     self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
1  Example/Example/Example/MSMasterViewController.h
@@ -33,6 +33,7 @@ typedef NS_ENUM(NSUInteger, MSPaneViewControllerType) {
33 33
     MSPaneViewControllerTypeAppearanceNone,
34 34
     MSPaneViewControllerTypeAppearanceParallax,
35 35
     MSPaneViewControllerTypeAppearanceZoom,
  36
+    MSPaneViewControllerTypeAppearanceFade,
36 37
     MSPaneViewControllerTypeMonospace,
37 38
     MSPaneViewControllerTypeCount
38 39
 };
3  Example/Example/Example/MSMasterViewController.m
@@ -59,18 +59,21 @@ - (id)initWithStyle:(UITableViewStyle)style
59 59
             @(MSPaneViewControllerTypeAppearanceNone) : @"None",
60 60
             @(MSPaneViewControllerTypeAppearanceParallax) : @"Parallax",
61 61
             @(MSPaneViewControllerTypeAppearanceZoom) : @"Zoom",
  62
+            @(MSPaneViewControllerTypeAppearanceFade) : @"Fade",
62 63
             @(MSPaneViewControllerTypeMonospace) : @"Monospace Ltd."
63 64
         };
64 65
         self.paneViewControllerClasses = @{
65 66
             @(MSPaneViewControllerTypeAppearanceNone) : UITableViewController.class,
66 67
             @(MSPaneViewControllerTypeAppearanceParallax) : UITableViewController.class,
67 68
             @(MSPaneViewControllerTypeAppearanceZoom) : UITableViewController.class,
  69
+            @(MSPaneViewControllerTypeAppearanceFade) : UITableViewController.class,
68 70
             @(MSPaneViewControllerTypeMonospace) : MSMonospaceViewController.class
69 71
         };
70 72
         self.paneViewControllerAppearanceTypes = @{
71 73
             @(MSPaneViewControllerTypeAppearanceNone) : @(MSNavigationPaneAppearanceTypeNone),
72 74
             @(MSPaneViewControllerTypeAppearanceParallax) : @(MSNavigationPaneAppearanceTypeParallax),
73 75
             @(MSPaneViewControllerTypeAppearanceZoom) : @(MSNavigationPaneAppearanceTypeZoom),
  76
+            @(MSPaneViewControllerTypeAppearanceFade) : @(MSNavigationPaneAppearanceTypeFade),
74 77
         };
75 78
         self.tableViewSectionBreaks = @[
76 79
             @(MSPaneViewControllerTypeMonospace),
12  Example/Storyboard Example/Storyboard Example.xcodeproj/project.pbxproj
@@ -17,7 +17,7 @@
17 17
 		3A116769167E904A00DBD12B /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A116768167E904A00DBD12B /* QuartzCore.framework */; };
18 18
 		3A1167B7167EAB7C00DBD12B /* MSMasterViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A1167B6167EAB7C00DBD12B /* MSMasterViewController.m */; };
19 19
 		3A1167BC167EAB9B00DBD12B /* MSNavigationPaneViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A1167B8167EAB9B00DBD12B /* MSNavigationPaneViewController.m */; };
20  
-		3A1167BD167EAB9B00DBD12B /* MSDraggableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A1167BA167EAB9B00DBD12B /* MSDraggableView.m */; };
  20
+		3A1167BD167EAB9B00DBD12B /* MSPaneView.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A1167BA167EAB9B00DBD12B /* MSPaneView.m */; };
21 21
 		3A116872167EAE2500DBD12B /* MSMonospaceViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A116871167EAE2500DBD12B /* MSMonospaceViewController.m */; };
22 22
 		3A5AC5FF16A20551006F5A3F /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 3A5AC5F016A20551006F5A3F /* Default-568h@2x.png */; };
23 23
 		3A5AC60016A20551006F5A3F /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = 3A5AC5F116A20551006F5A3F /* Default.png */; };
@@ -52,8 +52,8 @@
52 52
 		3A1167B5167EAB7C00DBD12B /* MSMasterViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MSMasterViewController.h; sourceTree = "<group>"; };
53 53
 		3A1167B6167EAB7C00DBD12B /* MSMasterViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MSMasterViewController.m; sourceTree = "<group>"; };
54 54
 		3A1167B8167EAB9B00DBD12B /* MSNavigationPaneViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MSNavigationPaneViewController.m; path = ../../MSNavigationPaneViewController/MSNavigationPaneViewController.m; sourceTree = "<group>"; };
55  
-		3A1167B9167EAB9B00DBD12B /* MSDraggableView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MSDraggableView.h; path = ../../MSNavigationPaneViewController/MSDraggableView.h; sourceTree = "<group>"; };
56  
-		3A1167BA167EAB9B00DBD12B /* MSDraggableView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MSDraggableView.m; path = ../../MSNavigationPaneViewController/MSDraggableView.m; sourceTree = "<group>"; };
  55
+		3A1167B9167EAB9B00DBD12B /* MSPaneView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MSPaneView.h; path = ../../MSNavigationPaneViewController/MSPaneView.h; sourceTree = "<group>"; };
  56
+		3A1167BA167EAB9B00DBD12B /* MSPaneView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MSPaneView.m; path = ../../MSNavigationPaneViewController/MSPaneView.m; sourceTree = "<group>"; };
57 57
 		3A1167BB167EAB9B00DBD12B /* MSNavigationPaneViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MSNavigationPaneViewController.h; path = ../../MSNavigationPaneViewController/MSNavigationPaneViewController.h; sourceTree = "<group>"; };
58 58
 		3A116870167EAE2500DBD12B /* MSMonospaceViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MSMonospaceViewController.h; path = ../../MSMonospaceViewController/MSMonospaceViewController.h; sourceTree = "<group>"; };
59 59
 		3A116871167EAE2500DBD12B /* MSMonospaceViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MSMonospaceViewController.m; path = ../../MSMonospaceViewController/MSMonospaceViewController.m; sourceTree = "<group>"; };
@@ -145,8 +145,8 @@
145 145
 		3A116787167EAA0800DBD12B /* Vendor */ = {
146 146
 			isa = PBXGroup;
147 147
 			children = (
148  
-				3A1167B9167EAB9B00DBD12B /* MSDraggableView.h */,
149  
-				3A1167BA167EAB9B00DBD12B /* MSDraggableView.m */,
  148
+				3A1167B9167EAB9B00DBD12B /* MSPaneView.h */,
  149
+				3A1167BA167EAB9B00DBD12B /* MSPaneView.m */,
150 150
 				3A1167BB167EAB9B00DBD12B /* MSNavigationPaneViewController.h */,
151 151
 				3A1167B8167EAB9B00DBD12B /* MSNavigationPaneViewController.m */,
152 152
 			);
@@ -271,7 +271,7 @@
271 271
 				3A116752167E901700DBD12B /* MSAppDelegate.m in Sources */,
272 272
 				3A1167B7167EAB7C00DBD12B /* MSMasterViewController.m in Sources */,
273 273
 				3A1167BC167EAB9B00DBD12B /* MSNavigationPaneViewController.m in Sources */,
274  
-				3A1167BD167EAB9B00DBD12B /* MSDraggableView.m in Sources */,
  274
+				3A1167BD167EAB9B00DBD12B /* MSPaneView.m in Sources */,
275 275
 				3A116872167EAE2500DBD12B /* MSMonospaceViewController.m in Sources */,
276 276
 			);
277 277
 			runOnlyForDeploymentPostprocessing = 0;
6  MSNavigationPaneViewController.podspec
@@ -3,14 +3,16 @@ Pod::Spec.new do |s|
3 3
   s.version      = '0.1.0'
4 4
   s.license      = 'MIT'
5 5
   s.platform     = :ios, '5.0'
6  
-
  6
+  
7 7
   s.summary      = 'Draggable navigation pane view controller for iPhone. Similar to the Path/Facebook navigation paradigm.'
8 8
   s.homepage     = 'https://github.com/monospacecollective/MSNavigationPaneViewController'
9 9
   s.author       = { 'Eric Horacek' => 'eric@monospacecollective.com' }
10 10
   s.source       = { :git => 'https://github.com/monospacecollective/MSNavigationPaneViewController.git', :tag => s.version.to_s }
11  
-
  11
+  
12 12
   s.source_files = 'MSNavigationPaneViewController/*.{h,m}'
13 13
   
14 14
   s.requires_arc = true
15 15
   s.frameworks   = 'QuartzCore'
  16
+  
  17
+  s.dependency 'PRTween'              , '~> 0.0.1'
16 18
 end
58  MSNavigationPaneViewController/MSDraggableView.h
... ...
@@ -1,58 +0,0 @@
1  
-//
2  
-//  MSDraggableView.h
3  
-//  MSNavigationPaneViewController
4  
-//
5  
-//  Created by Eric Horacek on 9/4/12.
6  
-//  Copyright (c) 2012 Monospace Ltd. All rights reserved.
7  
-//
8  
-//  This code is distributed under the terms and conditions of the MIT license.
9  
-//
10  
-//  Permission is hereby granted, free of charge, to any person obtaining a copy
11  
-//  of this software and associated documentation files (the "Software"), to deal
12  
-//  in the Software without restriction, including without limitation the rights
13  
-//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14  
-//  copies of the Software, and to permit persons to whom the Software is
15  
-//  furnished to do so, subject to the following conditions:
16  
-//
17  
-//  The above copyright notice and this permission notice shall be included in
18  
-//  all copies or substantial portions of the Software.
19  
-//
20  
-//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21  
-//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22  
-//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23  
-//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24  
-//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25  
-//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26  
-//  THE SOFTWARE.
27  
-//
28  
-
29  
-typedef NS_ENUM(NSUInteger, MSDraggableViewState) {
30  
-    MSDraggableViewStateOpen,
31  
-    MSDraggableViewStateClosed,
32  
-};
33  
-
34  
-@class MSNavigationPaneViewController;
35  
-@protocol MSDraggableViewDelegate;
36  
-
37  
-@interface MSDraggableView : UIView
38  
-
39  
-@property (nonatomic, weak) MSNavigationPaneViewController <MSDraggableViewDelegate> * navigationPaneViewController;
40  
-@property (nonatomic, weak) id <MSDraggableViewDelegate> delegate;
41  
-
42  
-@property (nonatomic, assign) MSDraggableViewState state;
43  
-@property (nonatomic, assign) BOOL draggingEnabled;
44  
-
45  
-// Classes that the draggable view should forward dragging through to (UISlider by default)
46  
-@property (nonatomic, readonly) NSMutableSet *touchForwardingClasses;
47  
-
48  
-@end
49  
-
50  
-@protocol MSDraggableViewDelegate <NSObject>
51  
-
52  
-@optional
53  
-
54  
-- (void)draggableView:(MSDraggableView *)draggableView wasDraggedToState:(MSDraggableViewState)state;
55  
-- (void)draggableView:(MSDraggableView *)draggableView wasDraggedToFraction:(CGFloat)fraction;
56  
-
57  
-@end
58  
-
354  MSNavigationPaneViewController/MSDraggableView.m
... ...
@@ -1,354 +0,0 @@
1  
-//
2  
-//  MSDraggableView.m
3  
-//  MSNavigationPaneViewController
4  
-//
5  
-//  Created by Eric Horacek on 9/4/12.
6  
-//  Copyright (c) 2012 Monospace Ltd. All rights reserved.
7  
-//
8  
-//  This code is distributed under the terms and conditions of the MIT license.
9  
-//
10  
-//  Permission is hereby granted, free of charge, to any person obtaining a copy
11  
-//  of this software and associated documentation files (the "Software"), to deal
12  
-//  in the Software without restriction, including without limitation the rights
13  
-//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14  
-//  copies of the Software, and to permit persons to whom the Software is
15  
-//  furnished to do so, subject to the following conditions:
16  
-//
17  
-//  The above copyright notice and this permission notice shall be included in
18  
-//  all copies or substantial portions of the Software.
19  
-//
20  
-//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21  
-//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22  
-//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23  
-//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24  
-//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25  
-//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26  
-//  THE SOFTWARE.
27  
-//
28  
-
29  
-#import "MSDraggableView.h"
30  
-#import "MSNavigationPaneViewController.h"
31  
-#import <QuartzCore/QuartzCore.h>
32  
-
33  
-const CGFloat MSDraggableViewXYMinimumThreshold = 5.0;
34  
-const CGFloat MSDraggableViewXVelocityThreshold = 8.0;
35  
-const CGFloat MSDraggableViewXVelocitySlide = 15.0;
36  
-
37  
-typedef void (^ViewActionBlock)(UIView *view);
38  
-
39  
-@interface UIView (ViewHierarchyAction)
40  
-
41  
-- (void)superviewHierarchyAction:(ViewActionBlock)viewAction;
42  
-
43  
-@end
44  
-
45  
-@implementation UIView (ViewHierarchyAction)
46  
-
47  
-- (void)superviewHierarchyAction:(ViewActionBlock)viewAction
48  
-{
49  
-    viewAction(self);
50  
-    [self.superview superviewHierarchyAction:viewAction];
51  
-}
52  
-
53  
-@end
54  
-
55  
-@interface MSDraggableView() <UIGestureRecognizerDelegate> {
56  
-    
57  
-    MSDraggableViewState _state;
58  
-}
59  
-
60  
-@property (nonatomic, assign) BOOL animating;
61  
-@property (nonatomic, assign) CGPoint startLocation;
62  
-@property (nonatomic, assign) CGPoint startLocationInSuperview;
63  
-@property (nonatomic, assign) CGFloat xVelocity;
64  
-
65  
-@property (nonatomic, strong) UIPanGestureRecognizer *panGestureRecognizer;
66  
-@property (nonatomic, strong) UITapGestureRecognizer *tapGestureRecognizer;
67  
-
68  
-- (void)setSubviewUserInteractionEnabled:(BOOL)interactionEnabled;
69  
-
70  
-- (void)tapped:(UIPanGestureRecognizer *)gesureRecognizer;
71  
-- (void)panned:(UITapGestureRecognizer *)gesureRecognizer;
72  
-
73  
-- (void)bounceToCompletionWithDuration:(CGFloat)duration velocty:(CGFloat)velocity;
74  
-- (void)bounceBackWithDuration:(CGFloat)duration velocty:(CGFloat)velocity;
75  
-- (void)slideToCompletionWithDuration:(CGFloat)duration;
76  
-- (void)slideBackWithDuration:(CGFloat)duration;
77  
-
78  
-@end
79  
-
80  
-@implementation MSDraggableView
81  
-
82  
-@dynamic state;
83  
-
84  
-#pragma mark - UIView
85  
-
86  
-- (id)initWithFrame:(CGRect)frame
87  
-{
88  
-    self = [super initWithFrame:frame];
89  
-    if (self) {
90  
-        
91  
-        self.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
92  
-		self.backgroundColor = [UIColor clearColor];
93  
-        
94  
-        // Ensure that the shadow extends beyond the edges of the screen
95  
-        self.layer.shadowPath = [[UIBezierPath bezierPathWithRect:CGRectInset(frame, 0.0, -40.0)] CGPath];
96  
-        self.layer.shadowColor = [UIColor blackColor].CGColor;
97  
-        self.layer.shadowOpacity = 1.0;
98  
-        self.layer.shadowRadius = 10.0;
99  
-        self.layer.masksToBounds = NO;
100  
-        
101  
-        self.animating = NO;
102  
-        self.xVelocity = 0.0;
103  
-        
104  
-        _touchForwardingClasses = [NSMutableSet setWithObjects:UISlider.class, UISwitch.class, nil];
105  
-        
106  
-        self.panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panned:)];
107  
-        _panGestureRecognizer.minimumNumberOfTouches = 1;
108  
-        _panGestureRecognizer.maximumNumberOfTouches = 1;
109  
-        _panGestureRecognizer.delegate = self;
110  
-        [self addGestureRecognizer:_panGestureRecognizer];
111  
-        
112  
-        // Start at the "closed" state
113  
-        self.state = MSDraggableViewStateClosed;
114  
-        
115  
-        // Start with dragging enabled
116  
-        self.draggingEnabled = YES;
117  
-    }
118  
-    return self;
119  
-}
120  
-
121  
-- (void)setFrame:(CGRect)frame
122  
-{
123  
-    [super setFrame:frame];
124  
-    
125  
-    CGFloat fraction = ((MSNavigationPaneOpenStateMasterDisplayWidth - self.frame.origin.x) / MSNavigationPaneOpenStateMasterDisplayWidth);
126  
-    
127  
-    // Clip to 0.0 < fraction < 1.0
128  
-    fraction = (fraction < 0.0) ? 0.0 : fraction;
129  
-    fraction = (fraction > 1.0) ? 1.0 : fraction;
130  
-    
131  
-    if ([self.delegate respondsToSelector:@selector(draggableView:wasDraggedToFraction:)]) {
132  
-        [self.delegate draggableView:self wasDraggedToFraction:fraction];
133  
-    }
134  
-    if ([self.navigationPaneViewController respondsToSelector:@selector(draggableView:wasDraggedToFraction:)]) {
135  
-        [self.navigationPaneViewController draggableView:self wasDraggedToFraction:fraction];
136  
-    }
137  
-}
138  
-
139  
-#pragma mark - MSDraggableView
140  
-
141  
-- (void)tapped:(UIPanGestureRecognizer *)gestureRecognizer
142  
-{
143  
-    [self slideToCompletionWithDuration:MSNavigationPaneAnimationDurationOpenToClosed];
144  
-}
145  
-
146  
-- (void)panned:(UIPanGestureRecognizer *)gestureRecognizer
147  
-{
148  
-    if (!self.draggingEnabled) {
149  
-        return;
150  
-    }
151  
-    
152  
-    switch (gestureRecognizer.state) {
153  
-        case UIGestureRecognizerStateBegan: {
154  
-            
155  
-            self.startLocation = [gestureRecognizer locationInView:self];
156  
-            self.xVelocity = 0.0;
157  
-            break;
158  
-            
159  
-        } case UIGestureRecognizerStateChanged: {
160  
-            
161  
-            if (!self.animating) {
162  
-                
163  
-                CGPoint locationInSelf = [gestureRecognizer locationInView:self];
164  
-                self.xVelocity = self.startLocation.x - locationInSelf.x;
165  
-                
166  
-                CGRect newFrame = self.frame;
167  
-                newFrame.origin.x += (locationInSelf.x - self.startLocation.x);
168  
-                
169  
-                if ((newFrame.origin.x > 0.0) && (newFrame.origin.x < MSNavigationPaneOpenStateMasterDisplayWidth)) {
170  
-                    self.frame = newFrame;
171  
-                }
172  
-            }
173  
-            break;
174  
-            
175  
-        } case UIGestureRecognizerStateEnded: {
176  
-            
177  
-            CGFloat halfWay = (MSNavigationPaneOpenStateMasterDisplayWidth / 2.0);
178  
-            BOOL pastHalfWay = NO;
179  
-            if (self.state == MSDraggableViewStateClosed) {
180  
-                pastHalfWay = (self.frame.origin.x > halfWay);
181  
-            } else if (self.state == MSDraggableViewStateOpen) {
182  
-                pastHalfWay = (self.frame.origin.x < halfWay);
183  
-            }
184  
-            
185  
-            // We've reached the velocity threshold
186  
-            if (fabsf(_xVelocity) > MSDraggableViewXVelocityThreshold) {
187  
-                // Velocity is positive
188  
-                if (_xVelocity > 0) {
189  
-                    if (_state == MSDraggableViewStateOpen) {
190  
-                        [self bounceToCompletionWithDuration:MSNavigationPaneAnimationDurationSnap velocty:_xVelocity];
191  
-                    } else if (_state == MSDraggableViewStateClosed) {
192  
-                        if (self.frame.origin.x > 0.0) {
193  
-                            [self bounceBackWithDuration:MSNavigationPaneAnimationDurationSnap velocty:_xVelocity];
194  
-                        }
195  
-                    }
196  
-                }
197  
-                // Velocity is negative
198  
-                else if (_xVelocity < 0) {
199  
-                    if (_state == MSDraggableViewStateOpen) {
200  
-                        [self bounceBackWithDuration:MSNavigationPaneAnimationDurationSnap velocty:_xVelocity];
201  
-                    } else if (_state == MSDraggableViewStateClosed) {
202  
-                        [self bounceToCompletionWithDuration:MSNavigationPaneAnimationDurationSnap velocty:_xVelocity];
203  
-                    }
204  
-                }
205  
-            }
206  
-            // If we're released past half-way, snap to completion with no bounce
207  
-            else if (pastHalfWay) {
208  
-                [self bounceToCompletionWithDuration:MSNavigationPaneAnimationDurationSnap velocty:MSDraggableViewXVelocitySlide];
209  
-            }
210  
-            // Othwersie, snap to back to starting position with no bounce
211  
-            else {
212  
-                [self bounceBackWithDuration:MSNavigationPaneAnimationDurationSnap velocty:MSDraggableViewXVelocitySlide];
213  
-            }
214  
-            break;
215  
-            
216  
-        } default:
217  
-            break;
218  
-    }
219  
-}
220  
-
221  
-- (MSDraggableViewState)state
222  
-{
223  
-    return _state;
224  
-}
225  
-
226  
-- (void)setState:(MSDraggableViewState)aState
227  
-{
228  
-    _state = aState;
229  
-    if (_state == MSDraggableViewStateOpen) {
230  
-        self.tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapped:)];
231  
-        _tapGestureRecognizer.numberOfTouchesRequired = 1;
232  
-        _tapGestureRecognizer.numberOfTapsRequired = 1;
233  
-        [self addGestureRecognizer:_tapGestureRecognizer];
234  
-    } else if (_state == MSDraggableViewStateClosed) {
235  
-        [self removeGestureRecognizer:self.tapGestureRecognizer];
236  
-    }
237  
-    
238  
-    [self setSubviewUserInteractionEnabled:(self.state == MSDraggableViewStateClosed)];
239  
-}
240  
-
241  
-- (void)setSubviewUserInteractionEnabled:(BOOL)interactionEnabled
242  
-{
243  
-    for (UIView *subview in self.subviews) {
244  
-        subview.userInteractionEnabled = interactionEnabled;
245  
-    }
246  
-}
247  
-
248  
-- (void)bounceToCompletionWithDuration:(CGFloat)duration velocty:(CGFloat)velocity;
249  
-{
250  
-    CGFloat xLocation = ((self.state == MSDraggableViewStateClosed) ? MSNavigationPaneOpenStateMasterDisplayWidth : 0.0);
251  
-    CGFloat velocityOvershot = sqrtf(fabsf(velocity * 1.5));
252  
-    xLocation = ((self.state == MSDraggableViewStateClosed) ? (xLocation + velocityOvershot) : (xLocation - velocityOvershot));
253  
-    CGRect newFrame = self.frame;
254  
-    newFrame.origin.x = xLocation;
255  
-    
256  
-    // Bounce over the location, and then slide to completion
257  
-    _animating = YES;
258  
-    [UIView animateWithDuration:duration
259  
-                          delay:0.0
260  
-                        options:UIViewAnimationOptionCurveEaseOut
261  
-                     animations:^{
262  
-                         self.frame = newFrame;
263  
-                     } completion:^(BOOL finished) {
264  
-                         [self slideToCompletionWithDuration:MSNavigationPaneAnimationDurationSnapBack];
265  
-                     }];
266  
-}
267  
-
268  
-- (void)bounceBackWithDuration:(CGFloat)duration velocty:(CGFloat)velocity;
269  
-{
270  
-    CGFloat xLocation = ((self.state == MSDraggableViewStateClosed) ? 0.0 : MSNavigationPaneOpenStateMasterDisplayWidth);
271  
-    CGFloat velocityOvershot = sqrtf(fabsf(velocity * 1.5));
272  
-    xLocation = ((self.state == MSDraggableViewStateClosed) ? (xLocation - velocityOvershot) : (xLocation + velocityOvershot));
273  
-    CGRect newFrame = self.frame;
274  
-    newFrame.origin.x = xLocation;
275  
-    
276  
-    // Bounce over the location, and then slide to completion
277  
-    _animating = YES;
278  
-    [UIView animateWithDuration:duration
279  
-                          delay:0.0
280  
-                        options:UIViewAnimationOptionCurveEaseOut
281  
-                     animations:^{
282  
-                         self.frame = newFrame;
283  
-                     } completion:^(BOOL finished) {
284  
-                         [self slideBackWithDuration:MSNavigationPaneAnimationDurationSnapBack];
285  
-                     }];
286  
-}
287  
-
288  
-- (void)slideToCompletionWithDuration:(CGFloat)duration
289  
-{
290  
-    CGFloat xLocation = ((self.state == MSDraggableViewStateClosed) ? MSNavigationPaneOpenStateMasterDisplayWidth : 0.0);
291  
-    CGRect newFrame = self.frame;
292  
-    newFrame.origin.x = xLocation;
293  
-    
294  
-    _animating = YES;
295  
-    [UIView animateWithDuration:duration
296  
-                     animations:^{
297  
-                         self.frame = newFrame;
298  
-                     }
299  
-                     completion:^(BOOL finished) {
300  
-                         _animating = NO;
301  
-                         self.state = !self.state;
302  
-                         if ([self.delegate respondsToSelector:@selector(draggableView:wasDraggedToState:)]) {
303  
-                             [self.delegate draggableView:self wasDraggedToState:_state];
304  
-                         }
305  
-                         if ([self.navigationPaneViewController respondsToSelector:@selector(draggableView:wasDraggedToState:)]) {
306  
-                             [self.navigationPaneViewController draggableView:self wasDraggedToState:_state];
307  
-                         }
308  
-                     }];
309  
-}
310  
-
311  
-- (void)slideBackWithDuration:(CGFloat)duration
312  
-{   
313  
-    CGFloat xLocation = ((self.state == MSDraggableViewStateClosed) ? 0.0 : MSNavigationPaneOpenStateMasterDisplayWidth);
314  
-    CGRect newFrame = self.frame;
315  
-    newFrame.origin.x = xLocation;
316  
-    
317  
-    _animating = YES;
318  
-    [UIView animateWithDuration:duration
319  
-                     animations:^{
320  
-                         self.frame = newFrame;
321  
-                     }
322  
-                     completion:^(BOOL finished) {
323  
-                         _animating = NO;
324  
-                     }];
325  
-}
326  
-
327  
-#pragma mark - UIGestureRecognizerDelegate
328  
-
329  
-- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
330  
-{
331  
-    if (!self.draggingEnabled) {
332  
-        return NO;
333  
-    }
334  
-    
335  
-    // If the touch was in a touch forwarding view, don't handle the gesture
336  
-    __block BOOL shouldReceiveTouch = YES;
337  
-    
338  
-    // Enumerate the view's superviews, checking for a touch-forwarding class
339  
-    [touch.view superviewHierarchyAction:^(UIView *view) {
340  
-        // Only enumerate while still receiving the touch
341  
-        if (shouldReceiveTouch) {
342  
-            [self.touchForwardingClasses enumerateObjectsUsingBlock:^(Class touchForwardingClass, BOOL *stop) {
343  
-                if ([view isKindOfClass:touchForwardingClass]) {
344  
-                    shouldReceiveTouch = NO;
345  
-                    *stop = YES;
346  
-                }
347  
-            }];
348  
-        }
349  
-    }];
350  
-    
351  
-    return shouldReceiveTouch;
352  
-}
353  
-
354  
-@end
35  MSNavigationPaneViewController/MSNavigationPaneViewController.h
@@ -26,18 +26,16 @@
26 26
 //  THE SOFTWARE.
27 27
 //
28 28
 
29  
-#import "MSDraggableView.h"
30  
-
31 29
 // Sizes
32  
-extern const CGFloat MSNavigationPaneOpenStateMasterDisplayWidth;
33  
-
34  
-// Animation Durations
35  
-extern const CGFloat MSNavigationPaneAnimationDurationOpenToSide;
36  
-extern const CGFloat MSNavigationPaneAnimationDurationSideToClosed;
37  
-extern const CGFloat MSNavigationPaneAnimationDurationOpenToClosed;
38  
-extern const CGFloat MSNavigationPaneAnimationDurationClosedToOpen;
39  
-extern const CGFloat MSNavigationPaneAnimationDurationSnap;
40  
-extern const CGFloat MSNavigationPaneAnimationDurationSnapBack;
  30
+extern const CGFloat MSNavigationPaneDefaultOpenStateRevealWidthLeft;
  31
+extern const CGFloat MSNavigationPaneDefaultOpenStateRevealWidthRight;
  32
+extern const CGFloat MSNavigationPaneDefaultOpenStateRevealWidthTop;
  33
+
  34
+typedef NS_ENUM(NSUInteger, MSNavigationPaneOpenDirection) {
  35
+    MSNavigationPaneOpenDirectionLeft,
  36
+    MSNavigationPaneOpenDirectionTop,
  37
+    MSNavigationPaneOpenDirectionRight,
  38
+};
41 39
 
42 40
 typedef NS_ENUM(NSUInteger, MSNavigationPaneState) {
43 41
     MSNavigationPaneStateOpen,
@@ -48,6 +46,7 @@ typedef NS_ENUM(NSUInteger, MSNavigationPaneAppearanceType) {
48 46
     MSNavigationPaneAppearanceTypeNone,
49 47
     MSNavigationPaneAppearanceTypeZoom,
50 48
     MSNavigationPaneAppearanceTypeParallax,
  49
+    MSNavigationPaneAppearanceTypeFade,
51 50
 };
52 51
 
53 52
 @protocol MSNavigationPaneViewControllerDelegate;
@@ -56,14 +55,25 @@ typedef NS_ENUM(NSUInteger, MSNavigationPaneAppearanceType) {
56 55
 
57 56
 @property (nonatomic, assign) id<MSNavigationPaneViewControllerDelegate> delegate;
58 57
 
  58
+@property (nonatomic, assign) MSNavigationPaneOpenDirection openDirection;
59 59
 @property (nonatomic, assign) MSNavigationPaneState paneState;
60 60
 @property (nonatomic, assign) MSNavigationPaneAppearanceType appearanceType;
  61
+@property (nonatomic, assign) CGFloat openStateRevealWidth;
61 62
 
62 63
 @property (nonatomic, strong) UIViewController *paneViewController;
63 64
 @property (nonatomic, strong) UIViewController *masterViewController;
64 65
 
65 66
 @property (nonatomic, readonly) UIView *masterView;
66  
-@property (nonatomic, readonly) MSDraggableView *paneView;
  67
+@property (nonatomic, readonly) UIView *paneView;
  68
+
  69
+// If a pan gesture on the pane view should slide the pane view
  70
+@property (nonatomic, assign) BOOL paneDraggingEnabled;
  71
+
  72
+// If setting a new pane view controller should cause an animation that slides off the old view controller before animating the new one back on
  73
+@property (nonatomic, assign) BOOL paneViewSlideOffAnimationEnabled;
  74
+
  75
+// Classes that the pane view should forward dragging through to (UISlider, UISwitch by default)
  76
+@property (nonatomic, readonly) NSMutableSet *touchForwardingClasses;
67 77
 
68 78
 - (void)setPaneViewController:(UIViewController *)paneViewController animated:(BOOL)animated completion:(void (^)(void))completion;
69 79
 - (void)setPaneState:(MSNavigationPaneState)paneState animated:(BOOL)animated;
@@ -76,5 +86,6 @@ typedef NS_ENUM(NSUInteger, MSNavigationPaneAppearanceType) {
76 86
 
77 87
 - (void)navigationPaneViewController:(MSNavigationPaneViewController *)navigationPaneViewController willAnimateToPane:(UIViewController *)paneViewController;
78 88
 - (void)navigationPaneViewController:(MSNavigationPaneViewController *)navigationPaneViewController didAnimateToPane:(UIViewController *)paneViewController;
  89
+- (void)paneView:(UIView *)paneView wasDraggedToState:(MSNavigationPaneState)state;
79 90
 
80 91
 @end
522  MSNavigationPaneViewController/MSNavigationPaneViewController.m
@@ -27,14 +27,20 @@
27 27
 //
28 28
 
29 29
 #import "MSNavigationPaneViewController.h"
30  
-#import "MSDraggableView.h"
31  
-
  30
+#import "PRTween.h"
32 31
 #import <QuartzCore/QuartzCore.h>
33 32
 
34 33
 //#define LAYOUT_DEBUG
35 34
 
36 35
 // Sizes
37  
-const CGFloat MSNavigationPaneOpenStateMasterDisplayWidth = 267.0f;
  36
+const CGFloat MSNavigationPaneDefaultOpenStateRevealWidthLeft = 267.0;
  37
+const CGFloat MSNavigationPaneDefaultOpenStateRevealWidthRight = 267.0;
  38
+const CGFloat MSNavigationPaneDefaultOpenStateRevealWidthTop = 200.0;
  39
+const CGFloat MSNavigationPaneOpenAnimationOvershot = 20.0;
  40
+
  41
+// Appearance Type Constants
  42
+const CGFloat MSNavigationPaneAppearanceTypeZoomScaleFraction = 0.075;
  43
+const CGFloat MSNavigationPaneAppearanceTypeParallaxOffsetFraction = 0.35;
38 44
 
39 45
 // Animation Durations
40 46
 const CGFloat MSNavigationPaneAnimationDurationOpenToSide = 0.2;
@@ -42,21 +48,52 @@
42 48
 const CGFloat MSNavigationPaneAnimationDurationSideToClosed = 0.45;
43 49
 const CGFloat MSNavigationPaneAnimationDurationOpenToClosed = 0.3;
44 50
 const CGFloat MSNavigationPaneAnimationDurationClosedToOpen = 0.3;
45  
-const CGFloat MSNavigationPaneAnimationDurationSnap = 0.15;
46  
-const CGFloat MSNavigationPaneAnimationDurationSnapBack = 0.12;
  51
+const CGFloat MSNavigationPaneAnimationDurationSnap = 0.2;
47 52
 
48  
-// Appearance Type Constants
49  
-const CGFloat MSNavigationPaneAppearanceTypeZoomScaleFraction = 0.075;
50  
-const CGFloat MSNavigationPaneAppearanceTypeParallaxOffsetFraction = 0.35;
  53
+// Velocity Thresholds
  54
+const CGFloat MSDraggableViewVelocityThreshold = 8.0;
  55
+
  56
+typedef void (^ViewActionBlock)(UIView *view);
  57
+
  58
+@interface UIView (ViewHierarchyAction)
  59
+
  60
+- (void)superviewHierarchyAction:(ViewActionBlock)viewAction;
  61
+
  62
+@end
  63
+
  64
+@implementation UIView (ViewHierarchyAction)
  65
+
  66
+- (void)superviewHierarchyAction:(ViewActionBlock)viewAction
  67
+{
  68
+    viewAction(self);
  69
+    [self.superview superviewHierarchyAction:viewAction];
  70
+}
  71
+
  72
+@end
51 73
 
52  
-@interface MSNavigationPaneViewController () <MSDraggableViewDelegate> {
  74
+@interface MSNavigationPaneViewController () <UIGestureRecognizerDelegate> {
53 75
     
54 76
     UIViewController *_masterViewController;
55 77
     UIViewController *_paneViewController;
56 78
     MSNavigationPaneAppearanceType _appearanceType;
  79
+    MSNavigationPaneState _paneState;
  80
+    MSNavigationPaneOpenDirection _openDirection;
57 81
 }
58 82
 
  83
+@property (nonatomic, assign) BOOL animatingPane;
  84
+@property (nonatomic, assign) CGPoint paneStartLocation;
  85
+@property (nonatomic, assign) CGPoint paneStartLocationInSuperview;
  86
+@property (nonatomic, assign) CGFloat paneVelocity;
  87
+
  88
+@property (nonatomic, strong) UIPanGestureRecognizer *panePanGestureRecognizer;
  89
+@property (nonatomic, strong) UITapGestureRecognizer *paneTapGestureRecognizer;
  90
+
59 91
 - (void)initialize;
  92
+- (void)animatePaneToState:(MSNavigationPaneState)state duration:(CGFloat)duration bounce:(BOOL)bounce;
  93
+- (void)paneViewFrameChanged;
  94
+- (CGFloat)paneViewClosedFraction;
  95
+- (void)paneTapped:(UIPanGestureRecognizer *)gesureRecognizer;
  96
+- (void)panePanned:(UITapGestureRecognizer *)gesureRecognizer;
60 97
 
61 98
 @end
62 99
 
@@ -66,7 +103,13 @@ @implementation MSNavigationPaneViewController
66 103
 @dynamic paneViewController;
67 104
 @dynamic paneState;
68 105
 @dynamic appearanceType;
69  
-@synthesize delegate;
  106
+
  107
+#pragma mark - NSObject
  108
+
  109
+- (void)dealloc
  110
+{
  111
+    [self.paneView removeObserver:self forKeyPath:@"frame"];
  112
+}
70 113
 
71 114
 #pragma mark - UIViewController
72 115
 
@@ -93,48 +136,57 @@ - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interface
93 136
     return UIInterfaceOrientationIsPortrait(interfaceOrientation);
94 137
 }
95 138
 
96  
-#pragma mark - ERNavigationPaneViewController
  139
+#pragma mark - MSNavigationPaneViewController
97 140
 
98 141
 - (void)initialize
99 142
 {
100 143
     self.view.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
101 144
     
102 145
     _appearanceType = MSNavigationPaneAppearanceTypeNone;
  146
+    _openDirection = MSNavigationPaneOpenDirectionTop;
  147
+    _openStateRevealWidth = MSNavigationPaneDefaultOpenStateRevealWidthLeft;
  148
+    _paneDraggingEnabled = YES;
  149
+    _paneViewSlideOffAnimationEnabled = YES;
  150
+    
  151
+    _touchForwardingClasses = [NSMutableSet setWithObjects:UISlider.class, UISwitch.class, nil];
103 152
     
104 153
     _masterView = [[UIView alloc] initWithFrame:self.view.bounds];
105 154
     _masterView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
106 155
     _masterView.backgroundColor = [UIColor clearColor];
107 156
     [self.view addSubview:_masterView];
108 157
     
109  
-    _paneView = [[MSDraggableView alloc] initWithFrame:self.view.bounds];
110  
-    _paneView.navigationPaneViewController = self;
111  
-    _paneView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
112  
-    _paneView.backgroundColor = [UIColor clearColor];
113  
-    [self.view addSubview:_paneView];
  158
+    _paneView = [[UIView alloc] initWithFrame:self.view.bounds];
  159
+    self.paneView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
  160
+    self.paneView.backgroundColor = [UIColor clearColor];
  161
+    
  162
+    // Ensure that the shadow extends beyond the edges of the screen
  163
+    self.paneView.layer.shadowPath = [[UIBezierPath bezierPathWithRect:CGRectInset(self.paneView.frame, -40.0, 0.0)] CGPath];
  164
+    self.paneView.layer.shadowColor = [UIColor blackColor].CGColor;
  165
+    self.paneView.layer.shadowOpacity = 1.0;
  166
+    self.paneView.layer.shadowRadius = 10.0;
  167
+    self.paneView.layer.masksToBounds = NO;
  168
+    
  169
+    [self.view addSubview:self.paneView];
  170
+    
  171
+    [self.paneView addObserver:self forKeyPath:@"frame" options:NULL context:NULL];
  172
+    
  173
+    self.panePanGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panePanned:)];
  174
+    self.panePanGestureRecognizer.minimumNumberOfTouches = 1;
  175
+    self.panePanGestureRecognizer.maximumNumberOfTouches = 1;
  176
+    self.panePanGestureRecognizer.delegate = self;
  177
+    [self.paneView addGestureRecognizer:self.panePanGestureRecognizer];
114 178
     
115 179
 #if defined(LAYOUT_DEBUG)
116 180
     _masterView.backgroundColor = [[UIColor blueColor] colorWithAlphaComponent:0.1];
117 181
     _masterView.layer.borderColor = [[UIColor blueColor] CGColor];
118 182
     _masterView.layer.borderWidth = 2.0;
119 183
     
120  
-    _paneView.backgroundColor = [[UIColor redColor] colorWithAlphaComponent:0.1];
121  
-    _paneView.layer.borderColor = [[UIColor redColor] CGColor];
122  
-    _paneView.layer.borderWidth = 2.0;
  184
+    self.paneView.backgroundColor = [[UIColor redColor] colorWithAlphaComponent:0.1];
  185
+    self.paneView.layer.borderColor = [[UIColor redColor] CGColor];
  186
+    self.paneView.layer.borderWidth = 2.0;
123 187
 #endif
124 188
 }
125 189
 
126  
-#pragma mark Pane State
127  
-
128  
-- (MSNavigationPaneState)paneState
129  
-{
130  
-    return _paneView.state;
131  
-}
132  
-
133  
-- (void)setPaneState:(MSNavigationPaneState)paneState
134  
-{
135  
-    [self setPaneState:paneState animated:NO];
136  
-}
137  
-
138 190
 #pragma mark View Controller Accessors
139 191
 
140 192
 - (UIViewController *)masterViewController
@@ -144,27 +196,27 @@ - (UIViewController *)masterViewController
144 196
 
145 197
 - (void)setMasterViewController:(UIViewController *)masterViewController
146 198
 {
147  
-	if (_masterViewController == nil) {
  199
+	if (self.masterViewController == nil) {
148 200
         
149 201
         masterViewController.view.frame = _masterView.bounds;
150 202
 		_masterViewController = masterViewController;
151  
-		[self addChildViewController:_masterViewController];
152  
-		[_masterView addSubview:_masterViewController.view];
153  
-		[_masterViewController didMoveToParentViewController:self];
  203
+		[self addChildViewController:self.masterViewController];
  204
+		[_masterView addSubview:self.masterViewController.view];
  205
+		[self.masterViewController didMoveToParentViewController:self];
154 206
         
155  
-	} else if (_masterViewController != masterViewController) {
  207
+	} else if (self.masterViewController != masterViewController) {
156 208
         
157 209
 		masterViewController.view.frame = _masterView.bounds;
158  
-		[_masterViewController willMoveToParentViewController:nil];
  210
+		[self.masterViewController willMoveToParentViewController:nil];
159 211
 		[self addChildViewController:masterViewController];
160 212
         
161 213
         void(^transitionCompletion)(BOOL finished) = ^(BOOL finished) {
162  
-            [_masterViewController removeFromParentViewController];
  214
+            [self.masterViewController removeFromParentViewController];
163 215
             [masterViewController didMoveToParentViewController:self];
164 216
             _masterViewController = masterViewController;
165 217
         };
166 218
         
167  
-		[self transitionFromViewController:_masterViewController
  219
+		[self transitionFromViewController:self.masterViewController
168 220
 						  toViewController:masterViewController
169 221
 								  duration:0
170 222
 								   options:UIViewAnimationOptionTransitionNone
@@ -180,27 +232,27 @@ - (UIViewController *)paneViewController
180 232
 
181 233
 - (void)setPaneViewController:(UIViewController *)paneViewController
182 234
 {
183  
-	if (_paneViewController == nil) {
  235
+	if (self.paneViewController == nil) {
184 236
         
185  
-		paneViewController.view.frame = _paneView.bounds;
  237
+		paneViewController.view.frame = self.paneView.bounds;
186 238
 		_paneViewController = paneViewController;
187  
-		[self addChildViewController:_paneViewController];
188  
-		[_paneView addSubview:_paneViewController.view];
189  
-		[_paneViewController didMoveToParentViewController:self];
  239
+		[self addChildViewController:self.paneViewController];
  240
+		[self.paneView addSubview:self.paneViewController.view];
  241
+		[self.paneViewController didMoveToParentViewController:self];
190 242
         
191  
-	} else if (_paneViewController != paneViewController) {
  243
+	} else if (self.paneViewController != paneViewController) {
192 244
         
193  
-		paneViewController.view.frame = _paneView.bounds;
194  
-		[_paneViewController willMoveToParentViewController:nil];
  245
+		paneViewController.view.frame = self.paneView.bounds;
  246
+		[self.paneViewController willMoveToParentViewController:nil];
195 247
 		[self addChildViewController:paneViewController];
196 248
         
197 249
         void(^transitionCompletion)(BOOL finished) = ^(BOOL finished) {
198  
-            [_paneViewController removeFromParentViewController];
  250
+            [self.paneViewController removeFromParentViewController];
199 251
             [paneViewController didMoveToParentViewController:self];
200 252
             _paneViewController = paneViewController;
201 253
         };
202 254
         
203  
-		[self transitionFromViewController:_paneViewController
  255
+		[self transitionFromViewController:self.paneViewController
204 256
 						  toViewController:paneViewController
205 257
 								  duration:0
206 258
 								   options:UIViewAnimationOptionTransitionNone
@@ -209,8 +261,6 @@ - (void)setPaneViewController:(UIViewController *)paneViewController
209 261
 	}
210 262
 }
211 263
 
212  
-#pragma mark Navigation Pane View Controller Methods
213  
-
214 264
 - (void)setPaneViewController:(UIViewController *)paneViewController animated:(BOOL)animated completion:(void (^)(void))completion
215 265
 {
216 266
     // Make sure that we don't have a nil completion block
@@ -233,15 +283,25 @@ - (void)setPaneViewController:(UIViewController *)paneViewController animated:(B
233 283
     self.view.userInteractionEnabled = NO;
234 284
     
235 285
     void(^movePaneToSide)() = ^{
236  
-        CGRect paneViewFrame = _paneView.frame;
237  
-        paneViewFrame.origin.x = CGRectGetWidth(self.view.frame) + 20.0;
238  
-        _paneView.frame = paneViewFrame;
  286
+        CGRect paneViewFrame = self.paneView.frame;
  287
+        switch (self.openDirection) {
  288
+            case MSNavigationPaneOpenDirectionLeft:
  289
+                paneViewFrame.origin.x = CGRectGetWidth(self.view.frame) + MSNavigationPaneOpenAnimationOvershot;
  290
+                break;
  291
+            case MSNavigationPaneOpenDirectionTop:
  292
+                paneViewFrame.origin.y = CGRectGetHeight(self.view.frame) + MSNavigationPaneOpenAnimationOvershot;
  293
+                break;
  294
+            case MSNavigationPaneOpenDirectionRight:
  295
+                paneViewFrame.origin.x = -MSNavigationPaneOpenAnimationOvershot;
  296
+                break;
  297
+        }
  298
+        self.paneView.frame = paneViewFrame;
239 299
     };
240 300
     
241 301
     void(^movePaneToClosed)() = ^{
242  
-        CGRect paneViewFrame = _paneView.frame;
243  
-        paneViewFrame.origin.x = 0.0;
244  
-        _paneView.frame = paneViewFrame;
  302
+        CGRect paneViewFrame = self.paneView.frame;
  303
+        paneViewFrame.origin = CGPointMake(0.0, 0.0);
  304
+        self.paneView.frame = paneViewFrame;
245 305
     };
246 306
     
247 307
     // If we're trying to animate to the currently visible pane view controller, just close
@@ -252,7 +312,7 @@ - (void)setPaneViewController:(UIViewController *)paneViewController animated:(B
252 312
                             options:UIViewAnimationOptionCurveEaseOut
253 313
                          animations:movePaneToClosed
254 314
                          completion:^(BOOL animationFinished) {
255  
-                             _paneView.state = MSDraggableViewStateClosed;
  315
+                             self.paneState = MSNavigationPaneStateClosed;
256 316
                              localCompletion();
257 317
                          }];
258 318
     }
@@ -264,7 +324,7 @@ - (void)setPaneViewController:(UIViewController *)paneViewController animated:(B
264 324
             self.paneViewController = paneViewController;
265 325
             
266 326
             // Force redraw of the pane view (for smooth animation)
267  
-            [_paneView setNeedsDisplay];
  327
+            [self.paneView setNeedsDisplay];
268 328
             [CATransaction flush];
269 329
             
270 330
             dispatch_async(dispatch_get_main_queue(), ^{
@@ -275,7 +335,7 @@ - (void)setPaneViewController:(UIViewController *)paneViewController animated:(B