├── .gitignore ├── .project ├── .settings └── com.aptana.editor.common.prefs ├── CHANGELOG.txt ├── Classes ├── .gitignore ├── DeMarcelpociotSidemenuModule.h ├── DeMarcelpociotSidemenuModule.m ├── DeMarcelpociotSidemenuModuleAssets.h ├── DeMarcelpociotSidemenuModuleAssets.m ├── DeMarcelpociotSidemenuSideMenu.h ├── DeMarcelpociotSidemenuSideMenu.m ├── DeMarcelpociotSidemenuSideMenuProxy.h ├── DeMarcelpociotSidemenuSideMenuProxy.m └── RESideMenu │ ├── RECommonFunctions.h │ ├── RECommonFunctions.m │ ├── RESideMenu.h │ ├── RESideMenu.m │ ├── UIViewController+RESideMenu.h │ └── UIViewController+RESideMenu.m ├── DeMarcelpociotSidemenu_Prefix.pch ├── Demo.gif ├── FXBlurView ├── FXBlurView.h └── FXBlurView.m ├── LICENSE ├── README.md ├── TiSideMenu.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ └── TiSideMenu.xccheckout │ └── xcuserdata │ │ └── marcelpociot.xcuserdatad │ │ ├── UserInterfaceState.xcuserstate │ │ └── WorkspaceSettings.xcsettings └── xcuserdata │ └── marcelpociot.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ ├── Build & Test.xcscheme │ ├── TiSideMenu.xcscheme │ └── xcschememanagement.plist ├── assets └── README ├── build.py ├── dist ├── de.marcelpociot.sidemenu-iphone-1.0.zip ├── de.marcelpociot.sidemenu-iphone-1.1.zip ├── de.marcelpociot.sidemenu-iphone-1.2.1.zip ├── de.marcelpociot.sidemenu-iphone-1.2.zip ├── de.marcelpociot.sidemenu-iphone-2.0.zip ├── de.marcelpociot.sidemenu-iphone-2.1.zip └── de.marcelpociot.sidemenu-iphone-2.2.zip ├── documentation └── index.md ├── example ├── app.js └── stars.png ├── hooks ├── README ├── add.py ├── install.py ├── remove.py └── uninstall.py ├── manifest ├── module.xcconfig ├── platform └── README ├── timodule.xml └── titanium.xcconfig /.gitignore: -------------------------------------------------------------------------------- 1 | tmp 2 | bin 3 | build 4 | *.class 5 | *.pyc 6 | *.pyo 7 | .DS_Store 8 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | TiSideMenu 4 | 5 | 6 | 7 | 8 | 9 | com.appcelerator.titanium.core.builder 10 | 11 | 12 | 13 | 14 | com.aptana.ide.core.unifiedBuilder 15 | 16 | 17 | 18 | 19 | 20 | com.appcelerator.titanium.mobile.module.nature 21 | com.aptana.projects.webnature 22 | 23 | 24 | -------------------------------------------------------------------------------- /.settings/com.aptana.editor.common.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | selectUserAgents=com.appcelerator.titanium.mobile.module.nature\:iphone 3 | -------------------------------------------------------------------------------- /CHANGELOG.txt: -------------------------------------------------------------------------------- 1 | Place your change log text here. This file will be incorporated with your app at package time. -------------------------------------------------------------------------------- /Classes/.gitignore: -------------------------------------------------------------------------------- 1 | DeMarcelpociotSidemenu.h 2 | DeMarcelpociotSidemenu.m 3 | -------------------------------------------------------------------------------- /Classes/DeMarcelpociotSidemenuModule.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Your Copyright Here 3 | * 4 | * Appcelerator Titanium is Copyright (c) 2009-2010 by Appcelerator, Inc. 5 | * and licensed under the Apache Public License (version 2) 6 | */ 7 | #import "TiModule.h" 8 | 9 | @interface DeMarcelpociotSidemenuModule : TiModule 10 | { 11 | } 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Classes/DeMarcelpociotSidemenuModule.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Your Copyright Here 3 | * 4 | * Appcelerator Titanium is Copyright (c) 2009-2010 by Appcelerator, Inc. 5 | * and licensed under the Apache Public License (version 2) 6 | */ 7 | #import "DeMarcelpociotSidemenuModule.h" 8 | #import "TiBase.h" 9 | #import "TiHost.h" 10 | #import "TiApp.h" 11 | #import "TiUtils.h" 12 | #import "RESideMenu.h" 13 | 14 | @implementation DeMarcelpociotSidemenuModule 15 | 16 | #pragma mark Internal 17 | 18 | // this is generated for your module, please do not change it 19 | -(id)moduleGUID 20 | { 21 | return @"544290ca-7102-4cf4-8b20-feedb53f2045"; 22 | } 23 | 24 | // this is generated for your module, please do not change it 25 | -(NSString*)moduleId 26 | { 27 | return @"de.marcelpociot.sidemenu"; 28 | } 29 | 30 | #pragma mark Lifecycle 31 | 32 | -(void)startup 33 | { 34 | // this method is called when the module is first loaded 35 | // you *must* call the superclass 36 | [super startup]; 37 | 38 | NSLog(@"[INFO] %@ loaded",self); 39 | } 40 | 41 | -(void)shutdown:(id)sender 42 | { 43 | // this method is called when the module is being unloaded 44 | // typically this is during shutdown. make sure you don't do too 45 | // much processing here or the app will be quit forceably 46 | 47 | // you *must* call the superclass 48 | [super shutdown:sender]; 49 | } 50 | 51 | #pragma mark Internal Memory Management 52 | 53 | -(void)didReceiveMemoryWarning:(NSNotification*)notification 54 | { 55 | // optionally release any resources that can be dynamically 56 | // reloaded once memory is available - such as caches 57 | [super didReceiveMemoryWarning:notification]; 58 | } 59 | 60 | #pragma mark Listener Notifications 61 | 62 | -(void)_listenerAdded:(NSString *)type count:(int)count 63 | { 64 | if (count == 1 && [type isEqualToString:@"my_event"]) 65 | { 66 | // the first (of potentially many) listener is being added 67 | // for event named 'my_event' 68 | } 69 | } 70 | 71 | -(void)_listenerRemoved:(NSString *)type count:(int)count 72 | { 73 | if (count == 0 && [type isEqualToString:@"my_event"]) 74 | { 75 | // the last listener called for event named 'my_event' has 76 | // been removed, we can optionally clean up any resources 77 | // since no body is listening at this point for that event 78 | } 79 | } 80 | 81 | #pragma Public APIs 82 | 83 | 84 | @end 85 | -------------------------------------------------------------------------------- /Classes/DeMarcelpociotSidemenuModuleAssets.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This is a generated file. Do not edit or your changes will be lost 3 | */ 4 | 5 | @interface DeMarcelpociotSidemenuModuleAssets : NSObject 6 | { 7 | } 8 | - (NSData*) moduleAsset; 9 | - (NSData*) resolveModuleAsset:(NSString*)path; 10 | 11 | @end 12 | -------------------------------------------------------------------------------- /Classes/DeMarcelpociotSidemenuModuleAssets.m: -------------------------------------------------------------------------------- 1 | /** 2 | * This is a generated file. Do not edit or your changes will be lost 3 | */ 4 | #import "DeMarcelpociotSidemenuModuleAssets.h" 5 | 6 | extern NSData* filterDataInRange(NSData* thedata, NSRange range); 7 | 8 | @implementation DeMarcelpociotSidemenuModuleAssets 9 | 10 | - (NSData*) moduleAsset 11 | { 12 | //##TI_AUTOGEN_BEGIN asset 13 | //Compiler generates code for asset here 14 | return nil; // DEFAULT BEHAVIOR 15 | //##TI_AUTOGEN_END asset 16 | } 17 | 18 | - (NSData*) resolveModuleAsset:(NSString*)path 19 | { 20 | //##TI_AUTOGEN_BEGIN resolve_asset 21 | //Compiler generates code for asset resolution here 22 | return nil; // DEFAULT BEHAVIOR 23 | //##TI_AUTOGEN_END resolve_asset 24 | } 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /Classes/DeMarcelpociotSidemenuSideMenu.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Appcelerator Titanium Mobile 3 | * Copyright (c) 2009-2013 by Appcelerator, Inc. All Rights Reserved. 4 | * Licensed under the terms of the Apache Public License 5 | * Please see the LICENSE included with this distribution for details. 6 | */ 7 | #import "TiUIView.h" 8 | #import "TiBase.h" 9 | #import "RESideMenu.h" 10 | 11 | UIViewController * ControllerForProxy(TiViewProxy * proxy); 12 | 13 | @interface DeMarcelpociotSidemenuSideMenu : TiUIView { 14 | 15 | @private 16 | RESideMenu *controller; 17 | } 18 | -(RESideMenu*)controller; 19 | 20 | -(void)presentLeftMenuViewController:(id)args; 21 | -(void)presentRightMenuViewController:(id)args; 22 | -(void)hideMenuViewController:(id)args; 23 | 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /Classes/DeMarcelpociotSidemenuSideMenu.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Appcelerator Titanium Mobile 3 | * Copyright (c) 2009-2013 by Appcelerator, Inc. All Rights Reserved. 4 | * Licensed under the terms of the Apache Public License 5 | * Please see the LICENSE included with this distribution for details. 6 | */ 7 | 8 | #import "DeMarcelpociotSidemenuSideMenu.h" 9 | #import "DeMarcelpociotSidemenuSideMenuProxy.h" 10 | #import "TiUtils.h" 11 | #import "TiApp.h" 12 | #import "TiViewController.h" 13 | #import "TiUIiOSNavWindowProxy.h" 14 | 15 | UIViewController * TiSideMenuControllerForViewProxy(TiViewProxy * proxy); 16 | 17 | UIViewController * TiSideMenuControllerForViewProxy(TiViewProxy * proxy) 18 | { 19 | [[proxy view] setAutoresizingMask:UIViewAutoresizingNone]; 20 | 21 | //make the proper resize ! 22 | TiThreadPerformOnMainThread(^{ 23 | [proxy windowWillOpen]; 24 | [proxy reposition]; 25 | [proxy windowDidOpen]; 26 | },YES); 27 | return [[TiViewController alloc] initWithViewProxy:proxy]; 28 | } 29 | 30 | UINavigationController * TiSideMenuNavigationControllerForViewProxy(TiUIiOSNavWindowProxy *proxy) 31 | { 32 | return [proxy controller]; 33 | } 34 | 35 | @implementation DeMarcelpociotSidemenuSideMenu 36 | 37 | 38 | -(RESideMenu*)controller 39 | { 40 | if (controller==nil) 41 | { 42 | // Check in centerWindow is a UINavigationController 43 | BOOL useNavController = FALSE; 44 | if([[[[self.proxy valueForUndefinedKey:@"contentView"] class] description] isEqualToString:@"TiUIiOSNavWindowProxy"]) { 45 | useNavController = TRUE; 46 | } 47 | 48 | // navController or TiWindow ? 49 | UIViewController *centerWindow = useNavController ? TiSideMenuNavigationControllerForViewProxy([self.proxy valueForUndefinedKey:@"contentView"]) : TiSideMenuControllerForViewProxy([self.proxy valueForUndefinedKey:@"contentView"]); 50 | 51 | TiViewProxy *leftWindow = [self.proxy valueForUndefinedKey:@"leftMenuView"]; 52 | TiViewProxy *rightWindow = [self.proxy valueForUndefinedKey:@"rightMenuView"]; 53 | UIViewController *leftMenuViewController = TiSideMenuControllerForViewProxy(leftWindow); 54 | UIViewController *rightMenuViewController = TiSideMenuControllerForViewProxy(rightWindow); 55 | 56 | controller = [[RESideMenu alloc] initWithContentViewController:centerWindow 57 | leftMenuViewController:leftMenuViewController 58 | rightMenuViewController:rightMenuViewController]; 59 | 60 | 61 | bool blurView = [TiUtils boolValue:[self.proxy valueForUndefinedKey:@"blurBackground"] def:NO]; 62 | UIImage *backgroundImageView = [TiUtils image:[self.proxy valueForUndefinedKey:@"backgroundImage"] proxy:self.proxy]; 63 | controller.tintColor = [TiUtils colorValue:[self.proxy valueForUndefinedKey:@"tintColor"]].color; 64 | controller.backgroundImage = backgroundImageView; 65 | 66 | // Check creation time parameters 67 | // setContentViewScaleValue 68 | [controller setContentViewScaleValue:[TiUtils floatValue:[self.proxy valueForUndefinedKey:@"contentViewScaleValue"] def:0.5]]; 69 | 70 | [controller setScaleContentView:[TiUtils boolValue:[self.proxy valueForUndefinedKey:@"scaleContentView"] def:YES]]; 71 | 72 | [controller setPanGestureEnabled:[TiUtils boolValue:[self.proxy valueForUndefinedKey:@"panGestureEnabled"] def:YES]]; 73 | 74 | [controller setLeftPanEnabled:[TiUtils boolValue:[self.proxy valueForUndefinedKey:@"leftPanEnabled"] def:YES]]; 75 | 76 | [controller setRightPanEnabled:[TiUtils boolValue:[self.proxy valueForUndefinedKey:@"rightPanEnabled"] def:YES]]; 77 | 78 | [controller setScaleBackgroundImageView:[TiUtils boolValue:[self.proxy valueForUndefinedKey:@"scaleBackgroundImageView"] def:YES]]; 79 | 80 | [controller setScaleMenuView:[TiUtils boolValue:[self.proxy valueForUndefinedKey:@"scaleMenuView"] def:YES]]; 81 | 82 | [controller setParallaxEnabled:[TiUtils boolValue:[self.proxy valueForUndefinedKey:@"parallaxEnabled"] def:YES]]; 83 | 84 | UIView * controllerView = [controller view]; 85 | [controllerView setFrame:[self bounds]]; 86 | [self addSubview:controllerView]; 87 | 88 | [controller setDelegate:(DeMarcelpociotSidemenuSideMenuProxy *)[self proxy]]; 89 | 90 | [controller viewWillAppear:NO]; 91 | [controller viewDidAppear:NO]; 92 | } 93 | return controller; 94 | } 95 | 96 | -(void)frameSizeChanged:(CGRect)frame bounds:(CGRect)bounds 97 | { 98 | [[[self controller] view] setFrame:bounds]; 99 | [super frameSizeChanged:frame bounds:bounds]; 100 | } 101 | 102 | 103 | -(void)setContentWindow_:(id)args 104 | { 105 | ENSURE_UI_THREAD(setContentWindow_, args); 106 | id window; 107 | BOOL animated = FALSE; 108 | if( [args respondsToSelector:@selector(objectForKey:)] ) 109 | { 110 | window = [args objectForKey:@"window"]; 111 | animated = [TiUtils boolValue:[args objectForKey:@"animated"] def:FALSE]; 112 | } else { 113 | window = args; 114 | } 115 | BOOL useNavController = FALSE; 116 | if([[[window class] description] isEqualToString:@"TiUIiOSNavWindowProxy"]) { 117 | useNavController = TRUE; 118 | } 119 | UIViewController *centerWindow = useNavController ? TiSideMenuNavigationControllerForViewProxy(window) : TiSideMenuControllerForViewProxy(window); 120 | [controller setContentViewController:centerWindow animated:animated]; 121 | } 122 | 123 | -(void)setLeftMenuWindow_:(id)args 124 | { 125 | ENSURE_UI_THREAD(setLeftMenuWindow_, args); 126 | ENSURE_SINGLE_ARG(args, TiViewProxy); 127 | [controller setLeftMenuViewController:args]; 128 | } 129 | 130 | -(void)setRightMenuWindow_:(id)args 131 | { 132 | ENSURE_UI_THREAD(setRightMenuWindow_, args); 133 | ENSURE_SINGLE_ARG(args, TiViewProxy); 134 | [controller setRightMenuViewController:args]; 135 | } 136 | 137 | -(void)setContentViewScaleValue_:(id)args 138 | { 139 | ENSURE_UI_THREAD(setContentViewScaleValue_, args); 140 | [controller setContentViewScaleValue:[TiUtils floatValue:args def:0.5]]; 141 | } 142 | 143 | -(void)setScaleContentView_:(id)args 144 | { 145 | ENSURE_UI_THREAD(setScaleContentView_, args); 146 | [controller setScaleContentView:[TiUtils boolValue:args]]; 147 | } 148 | 149 | -(void)setPanGestureEnabled_:(id)args 150 | { 151 | ENSURE_UI_THREAD(setPanGestureEnabled_, args); 152 | [controller setPanGestureEnabled:[TiUtils boolValue:args]]; 153 | } 154 | 155 | -(void)setPanFromEdge_:(id)args 156 | { 157 | ENSURE_UI_THREAD(setPanFromEdge_, args); 158 | [controller setPanFromEdge:[TiUtils boolValue:args]]; 159 | } 160 | 161 | -(void)setMenuPrefersStatusBarHidden_:(id)args 162 | { 163 | ENSURE_UI_THREAD(setMenuPrefersStatusBarHidden_, args); 164 | [controller setMenuPrefersStatusBarHidden:[TiUtils boolValue:args]]; 165 | } 166 | 167 | 168 | -(void)setScaleBackgroundImageView_:(id)args 169 | { 170 | ENSURE_UI_THREAD(setScaleBackgroundImageView_, args); 171 | [controller setScaleBackgroundImageView:[TiUtils boolValue:args]]; 172 | } 173 | 174 | -(void)setScaleMenuView_:(id)args 175 | { 176 | ENSURE_UI_THREAD(setScaleMenuView_, args); 177 | [controller setScaleMenuView:[TiUtils boolValue:args]]; 178 | } 179 | 180 | -(void)setParallaxEnabled_:(id)args 181 | { 182 | ENSURE_UI_THREAD(setParallaxEnabled_, args); 183 | [controller setParallaxEnabled:[TiUtils boolValue:args]]; 184 | } 185 | 186 | -(void)setLeftPanEnabled_:(id)args 187 | { 188 | ENSURE_UI_THREAD(setLeftPanEnabled_, args); 189 | [controller setLeftPanEnabled:[TiUtils boolValue:args]]; 190 | } 191 | 192 | -(void)setRightPanEnabled_:(id)args 193 | { 194 | ENSURE_UI_THREAD(setRightPanEnabled_, args); 195 | [controller setRightPanEnabled:[TiUtils boolValue:args]]; 196 | } 197 | 198 | #pragma API 199 | -(void)presentLeftMenuViewController:(id)args 200 | { 201 | ENSURE_UI_THREAD(presentLeftMenuViewController,args); 202 | [controller presentLeftMenuViewController]; 203 | } 204 | -(void)presentRightMenuViewController:(id)args 205 | { 206 | ENSURE_UI_THREAD(presentRightMenuViewController,args); 207 | [controller presentRightMenuViewController]; 208 | } 209 | 210 | -(void)hideMenuViewController:(id)args 211 | { 212 | ENSURE_UI_THREAD(hideMenuViewController, args); 213 | [controller hideMenuViewController]; 214 | } 215 | 216 | 217 | @end 218 | -------------------------------------------------------------------------------- /Classes/DeMarcelpociotSidemenuSideMenuProxy.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Appcelerator Titanium Mobile 3 | * Copyright (c) 2009-2013 by Appcelerator, Inc. All Rights Reserved. 4 | * Licensed under the terms of the Apache Public License 5 | * Please see the LICENSE included with this distribution for details. 6 | */ 7 | #import "TiBase.h" 8 | #import "TiWindowProxy.h" 9 | #import "RESideMenu.h" 10 | #import "DeMarcelpociotSidemenuSideMenu.h" 11 | 12 | @interface DeMarcelpociotSidemenuSideMenuProxy : TiWindowProxy { 13 | 14 | } 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Classes/DeMarcelpociotSidemenuSideMenuProxy.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Appcelerator Titanium Mobile 3 | * Copyright (c) 2009-2013 by Appcelerator, Inc. All Rights Reserved. 4 | * Licensed under the terms of the Apache Public License 5 | * Please see the LICENSE included with this distribution for details. 6 | */ 7 | 8 | #import "DeMarcelpociotSidemenuSideMenuProxy.h" 9 | #import "TiBase.h" 10 | #import "TiApp.h" 11 | #import "TiUtils.h" 12 | 13 | @implementation DeMarcelpociotSidemenuSideMenuProxy 14 | 15 | -(void)windowDidOpen { 16 | [super windowDidOpen]; 17 | [self reposition]; 18 | } 19 | 20 | -(UIViewController *)_controller { 21 | return [(DeMarcelpociotSidemenuSideMenu*)[self view] controller]; 22 | } 23 | 24 | -(TiUIView*)newView { 25 | return [[DeMarcelpociotSidemenuSideMenu alloc] init]; 26 | } 27 | 28 | # pragma API 29 | 30 | -(void)presentLeftMenuViewController:(id)args { 31 | TiThreadPerformOnMainThread(^{[(DeMarcelpociotSidemenuSideMenu*)[self view] presentLeftMenuViewController:args];}, NO); 32 | } 33 | -(void)presentRightMenuViewController:(id)args { 34 | TiThreadPerformOnMainThread(^{[(DeMarcelpociotSidemenuSideMenu*)[self view] presentRightMenuViewController:args];}, NO); 35 | } 36 | 37 | -(void)hideMenuViewController:(id)args { 38 | TiThreadPerformOnMainThread(^{[(DeMarcelpociotSidemenuSideMenu*)[self view] hideMenuViewController:args];}, NO); 39 | } 40 | 41 | # pragma Deleagte methods 42 | 43 | 44 | - (void)sideMenu:(RESideMenu *)sideMenu willShowMenuViewController:(UIViewController *)menuViewController 45 | { 46 | if ([self _hasListeners:@"willShowMenuViewController"]) { 47 | [self fireEvent:@"willShowMenuViewController" withObject:@{} propagate:YES]; 48 | } 49 | } 50 | - (void)sideMenu:(RESideMenu *)sideMenu didShowMenuViewController:(UIViewController *)menuViewController 51 | { 52 | if ([self _hasListeners:@"didShowMenuViewController"]) { 53 | [self fireEvent:@"didShowMenuViewController" withObject:@{} propagate:YES]; 54 | } 55 | } 56 | - (void)sideMenu:(RESideMenu *)sideMenu willHideMenuViewController:(UIViewController *)menuViewController 57 | { 58 | if ([self _hasListeners:@"willHideMenuViewController"]) { 59 | [self fireEvent:@"willHideMenuViewController" withObject:@{} propagate:YES]; 60 | } 61 | } 62 | - (void)sideMenu:(RESideMenu *)sideMenu didHideMenuViewController:(UIViewController *)menuViewController 63 | { 64 | if ([self _hasListeners:@"didHideMenuViewController"]) { 65 | [self fireEvent:@"didHideMenuViewController" withObject:@{} propagate:YES]; 66 | } 67 | } 68 | @end 69 | -------------------------------------------------------------------------------- /Classes/RESideMenu/RECommonFunctions.h: -------------------------------------------------------------------------------- 1 | // 2 | // RECommonFunctions.h 3 | // RESideMenu 4 | // 5 | // Copyright (c) 2013-2014 Roman Efimov (https://github.com/romaonthego) 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | // 25 | 26 | #import 27 | 28 | 29 | #ifndef REUIKitIsFlatMode 30 | #define REUIKitIsFlatMode() RESideMenuUIKitIsFlatMode() 31 | #endif 32 | 33 | #ifndef kCFCoreFoundationVersionNumber_iOS_6_1 34 | #define kCFCoreFoundationVersionNumber_iOS_6_1 793.00 35 | #endif 36 | 37 | #if __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_6_1 38 | #define IF_IOS7_OR_GREATER(...) \ 39 | if (kCFCoreFoundationVersionNumber > kCFCoreFoundationVersionNumber_iOS_6_1) \ 40 | { \ 41 | __VA_ARGS__ \ 42 | } 43 | #else 44 | #define IF_IOS7_OR_GREATER(...) 45 | #endif 46 | 47 | BOOL RESideMenuUIKitIsFlatMode(void); -------------------------------------------------------------------------------- /Classes/RESideMenu/RECommonFunctions.m: -------------------------------------------------------------------------------- 1 | // 2 | // RECommonFunctions.m 3 | // RESideMenu 4 | // 5 | // Copyright (c) 2013-2014 Roman Efimov (https://github.com/romaonthego) 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | // 25 | 26 | #import "RECommonFunctions.h" 27 | #import 28 | 29 | BOOL RESideMenuUIKitIsFlatMode(void) 30 | { 31 | static BOOL isUIKitFlatMode = NO; 32 | static dispatch_once_t onceToken; 33 | dispatch_once(&onceToken, ^{ 34 | if (floor(NSFoundationVersionNumber) > 993.0) { 35 | // If your app is running in legacy mode, tintColor will be nil - else it must be set to some color. 36 | if (UIApplication.sharedApplication.keyWindow) { 37 | isUIKitFlatMode = [UIApplication.sharedApplication.delegate.window performSelector:@selector(tintColor)] != nil; 38 | } else { 39 | // Possible that we're called early on (e.g. when used in a Storyboard). Adapt and use a temporary window. 40 | isUIKitFlatMode = [[UIWindow new] performSelector:@selector(tintColor)] != nil; 41 | } 42 | } 43 | }); 44 | return isUIKitFlatMode; 45 | } -------------------------------------------------------------------------------- /Classes/RESideMenu/RESideMenu.h: -------------------------------------------------------------------------------- 1 | // 2 | // REFrostedViewController.h 3 | // RESideMenu 4 | // 5 | // Copyright (c) 2013-2014 Roman Efimov (https://github.com/romaonthego) 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | // 25 | 26 | #import 27 | #import "UIViewController+RESideMenu.h" 28 | 29 | #ifndef IBInspectable 30 | #define IBInspectable 31 | #endif 32 | 33 | 34 | @protocol RESideMenuDelegate; 35 | 36 | @interface RESideMenu : UIViewController 37 | 38 | #if __IPHONE_8_0 39 | @property (strong, readwrite, nonatomic) IBInspectable NSString *contentViewStoryboardID; 40 | @property (strong, readwrite, nonatomic) IBInspectable NSString *leftMenuViewStoryboardID; 41 | @property (strong, readwrite, nonatomic) IBInspectable NSString *rightMenuViewStoryboardID; 42 | #endif 43 | 44 | @property (strong, readwrite, nonatomic) UIViewController *contentViewController; 45 | @property (strong, readwrite, nonatomic) UIViewController *leftMenuViewController; 46 | @property (strong, readwrite, nonatomic) UIViewController *rightMenuViewController; 47 | @property (weak, readwrite, nonatomic) id delegate; 48 | 49 | @property (assign, readwrite, nonatomic) NSTimeInterval animationDuration; 50 | @property (strong, readwrite, nonatomic) UIImage *backgroundImage; 51 | @property (assign, readwrite, nonatomic) BOOL panGestureEnabled; 52 | @property (assign, readwrite, nonatomic) BOOL leftPanEnabled; 53 | @property (assign, readwrite, nonatomic) BOOL rightPanEnabled; 54 | @property (assign, readwrite, nonatomic) BOOL panFromEdge; 55 | @property (assign, readwrite, nonatomic) NSUInteger panMinimumOpenThreshold; 56 | @property (assign, readwrite, nonatomic) IBInspectable BOOL interactivePopGestureRecognizerEnabled; 57 | @property (assign, readwrite, nonatomic) IBInspectable BOOL fadeMenuView; 58 | @property (assign, readwrite, nonatomic) IBInspectable BOOL scaleContentView; 59 | @property (assign, readwrite, nonatomic) IBInspectable BOOL scaleBackgroundImageView; 60 | @property (assign, readwrite, nonatomic) IBInspectable BOOL scaleMenuView; 61 | @property (assign, readwrite, nonatomic) IBInspectable BOOL contentViewShadowEnabled; 62 | @property (strong, readwrite, nonatomic) IBInspectable UIColor *contentViewShadowColor; 63 | @property (assign, readwrite, nonatomic) IBInspectable CGSize contentViewShadowOffset; 64 | @property (assign, readwrite, nonatomic) IBInspectable CGFloat contentViewShadowOpacity; 65 | @property (assign, readwrite, nonatomic) IBInspectable CGFloat contentViewShadowRadius; 66 | @property (assign, readwrite, nonatomic) IBInspectable CGFloat contentViewScaleValue; 67 | @property (assign, readwrite, nonatomic) IBInspectable CGFloat contentViewInLandscapeOffsetCenterX; 68 | @property (assign, readwrite, nonatomic) IBInspectable CGFloat contentViewInPortraitOffsetCenterX; 69 | @property (assign, readwrite, nonatomic) IBInspectable CGFloat parallaxMenuMinimumRelativeValue; 70 | @property (assign, readwrite, nonatomic) IBInspectable CGFloat parallaxMenuMaximumRelativeValue; 71 | @property (assign, readwrite, nonatomic) IBInspectable CGFloat parallaxContentMinimumRelativeValue; 72 | @property (assign, readwrite, nonatomic) IBInspectable CGFloat parallaxContentMaximumRelativeValue; 73 | @property (assign, readwrite, nonatomic) CGAffineTransform menuViewControllerTransformation; 74 | @property (assign, readwrite, nonatomic) IBInspectable BOOL parallaxEnabled; 75 | @property (assign, readwrite, nonatomic) IBInspectable BOOL bouncesHorizontally; 76 | @property (assign, readwrite, nonatomic) UIStatusBarStyle menuPreferredStatusBarStyle; 77 | @property (assign, readwrite, nonatomic) IBInspectable BOOL menuPrefersStatusBarHidden; 78 | 79 | @property (assign, readwrite, nonatomic) UIColor *tintColor; 80 | 81 | 82 | - (id)initWithContentViewController:(UIViewController *)contentViewController 83 | leftMenuViewController:(UIViewController *)leftMenuViewController 84 | rightMenuViewController:(UIViewController *)rightMenuViewController; 85 | - (void)presentLeftMenuViewController; 86 | - (void)presentRightMenuViewController; 87 | - (void)hideMenuViewController; 88 | - (void)setContentViewController:(UIViewController *)contentViewController animated:(BOOL)animated; 89 | 90 | @end 91 | 92 | @protocol RESideMenuDelegate 93 | 94 | @optional 95 | - (void)sideMenu:(RESideMenu *)sideMenu didRecognizePanGesture:(UIPanGestureRecognizer *)recognizer; 96 | - (void)sideMenu:(RESideMenu *)sideMenu willShowMenuViewController:(UIViewController *)menuViewController; 97 | - (void)sideMenu:(RESideMenu *)sideMenu didShowMenuViewController:(UIViewController *)menuViewController; 98 | - (void)sideMenu:(RESideMenu *)sideMenu willHideMenuViewController:(UIViewController *)menuViewController; 99 | - (void)sideMenu:(RESideMenu *)sideMenu didHideMenuViewController:(UIViewController *)menuViewController; 100 | 101 | @end 102 | -------------------------------------------------------------------------------- /Classes/RESideMenu/RESideMenu.m: -------------------------------------------------------------------------------- 1 | // 2 | // REFrostedViewController.m 3 | // RESideMenu 4 | // 5 | // Copyright (c) 2013-2014 Roman Efimov (https://github.com/romaonthego) 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | // 25 | 26 | #import "RESideMenu.h" 27 | #import "UIViewController+RESideMenu.h" 28 | #import "RECommonFunctions.h" 29 | 30 | 31 | @interface RESideMenu () 32 | 33 | @property (strong, readwrite, nonatomic) UIImageView *backgroundImageView; 34 | @property (assign, readwrite, nonatomic) BOOL visible; 35 | @property (assign, readwrite, nonatomic) BOOL leftMenuVisible; 36 | @property (assign, readwrite, nonatomic) BOOL rightMenuVisible; 37 | @property (assign, readwrite, nonatomic) CGPoint originalPoint; 38 | @property (strong, readwrite, nonatomic) UIButton *contentButton; 39 | @property (strong, readwrite, nonatomic) UIView *menuViewContainer; 40 | @property (strong, readwrite, nonatomic) UIView *contentViewContainer; 41 | @property (assign, readwrite, nonatomic) BOOL didNotifyDelegate; 42 | 43 | @end 44 | 45 | @implementation RESideMenu 46 | 47 | #pragma mark - 48 | #pragma mark Instance lifecycle 49 | 50 | - (id)init 51 | { 52 | self = [super init]; 53 | if (self) { 54 | [self commonInit]; 55 | } 56 | return self; 57 | } 58 | 59 | - (id)initWithCoder:(NSCoder *)decoder 60 | { 61 | self = [super initWithCoder:decoder]; 62 | if (self) { 63 | [self commonInit]; 64 | } 65 | return self; 66 | } 67 | 68 | #if __IPHONE_8_0 69 | - (void)awakeFromNib 70 | { 71 | if (self.contentViewStoryboardID) { 72 | self.contentViewController = [self.storyboard instantiateViewControllerWithIdentifier:self.contentViewStoryboardID]; 73 | } 74 | if (self.leftMenuViewStoryboardID) { 75 | self.leftMenuViewController = [self.storyboard instantiateViewControllerWithIdentifier:self.leftMenuViewStoryboardID]; 76 | } 77 | if (self.rightMenuViewStoryboardID) { 78 | self.rightMenuViewController = [self.storyboard instantiateViewControllerWithIdentifier:self.rightMenuViewStoryboardID]; 79 | } 80 | } 81 | #endif 82 | 83 | - (void)commonInit 84 | { 85 | _menuViewContainer = [[UIView alloc] init]; 86 | _contentViewContainer = [[UIView alloc] init]; 87 | 88 | _animationDuration = 0.35f; 89 | _interactivePopGestureRecognizerEnabled = YES; 90 | 91 | _menuViewControllerTransformation = CGAffineTransformMakeScale(1.5f, 1.5f); 92 | 93 | _scaleContentView = YES; 94 | _scaleBackgroundImageView = YES; 95 | _scaleMenuView = YES; 96 | 97 | _fadeMenuView = YES; 98 | _parallaxEnabled = YES; 99 | _parallaxMenuMinimumRelativeValue = -15; 100 | _parallaxMenuMaximumRelativeValue = 15; 101 | _parallaxContentMinimumRelativeValue = -25; 102 | _parallaxContentMaximumRelativeValue = 25; 103 | 104 | _bouncesHorizontally = YES; 105 | 106 | _panGestureEnabled = YES; 107 | _leftPanEnabled = YES; 108 | _rightPanEnabled = YES; 109 | _panFromEdge = YES; 110 | _panMinimumOpenThreshold = 60.0; 111 | 112 | _contentViewShadowEnabled = NO; 113 | _contentViewShadowColor = [UIColor blackColor]; 114 | _contentViewShadowOffset = CGSizeZero; 115 | _contentViewShadowOpacity = 0.4f; 116 | _contentViewShadowRadius = 8.0f; 117 | _contentViewInLandscapeOffsetCenterX = 30.f; 118 | _contentViewInPortraitOffsetCenterX = 30.f; 119 | _contentViewScaleValue = 0.7f; 120 | } 121 | 122 | #pragma mark - 123 | #pragma mark Public methods 124 | 125 | - (id)initWithContentViewController:(UIViewController *)contentViewController leftMenuViewController:(UIViewController *)leftMenuViewController rightMenuViewController:(UIViewController *)rightMenuViewController 126 | { 127 | self = [self init]; 128 | if (self) { 129 | _contentViewController = contentViewController; 130 | _leftMenuViewController = leftMenuViewController; 131 | _rightMenuViewController = rightMenuViewController; 132 | } 133 | return self; 134 | } 135 | 136 | - (void)presentLeftMenuViewController 137 | { 138 | [self presentMenuViewContainerWithMenuViewController:self.leftMenuViewController]; 139 | [self showLeftMenuViewController]; 140 | } 141 | 142 | - (void)presentRightMenuViewController 143 | { 144 | [self presentMenuViewContainerWithMenuViewController:self.rightMenuViewController]; 145 | [self showRightMenuViewController]; 146 | } 147 | 148 | - (void)hideMenuViewController 149 | { 150 | [self hideMenuViewControllerAnimated:YES]; 151 | } 152 | 153 | - (void)setContentViewController:(UIViewController *)contentViewController animated:(BOOL)animated 154 | { 155 | if (_contentViewController == contentViewController) 156 | { 157 | return; 158 | } 159 | 160 | if (!animated) { 161 | [self setContentViewController:contentViewController]; 162 | } else { 163 | [self addChildViewController:contentViewController]; 164 | contentViewController.view.alpha = 0; 165 | contentViewController.view.frame = self.contentViewContainer.bounds; 166 | [self.contentViewContainer addSubview:contentViewController.view]; 167 | [UIView animateWithDuration:self.animationDuration animations:^{ 168 | contentViewController.view.alpha = 1; 169 | } completion:^(BOOL finished) { 170 | [self hideViewController:self.contentViewController]; 171 | [contentViewController didMoveToParentViewController:self]; 172 | _contentViewController = contentViewController; 173 | 174 | [self statusBarNeedsAppearanceUpdate]; 175 | [self updateContentViewShadow]; 176 | 177 | if (self.visible) { 178 | [self addContentViewControllerMotionEffects]; 179 | } 180 | }]; 181 | } 182 | } 183 | 184 | #pragma mark View life cycle 185 | 186 | - (void)viewDidLoad 187 | { 188 | [super viewDidLoad]; 189 | 190 | self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 191 | self.backgroundImageView = ({ 192 | UIImageView *imageView = [[UIImageView alloc] initWithFrame:self.view.bounds]; 193 | imageView.image = self.backgroundImage; 194 | imageView.contentMode = UIViewContentModeScaleAspectFill; 195 | imageView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 196 | imageView; 197 | }); 198 | self.contentButton = ({ 199 | UIButton *button = [[UIButton alloc] initWithFrame:CGRectNull]; 200 | [button addTarget:self action:@selector(hideMenuViewController) forControlEvents:UIControlEventTouchUpInside]; 201 | button; 202 | }); 203 | 204 | [self.view addSubview:self.backgroundImageView]; 205 | [self.view addSubview:self.menuViewContainer]; 206 | [self.view addSubview:self.contentViewContainer]; 207 | 208 | self.menuViewContainer.frame = self.view.bounds; 209 | self.menuViewContainer.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 210 | 211 | if (self.leftMenuViewController) { 212 | [self addChildViewController:self.leftMenuViewController]; 213 | self.leftMenuViewController.view.frame = self.view.bounds; 214 | self.leftMenuViewController.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 215 | [self.menuViewContainer addSubview:self.leftMenuViewController.view]; 216 | [self.leftMenuViewController didMoveToParentViewController:self]; 217 | } 218 | 219 | if (self.rightMenuViewController) { 220 | [self addChildViewController:self.rightMenuViewController]; 221 | self.rightMenuViewController.view.frame = self.view.bounds; 222 | self.rightMenuViewController.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 223 | [self.menuViewContainer addSubview:self.rightMenuViewController.view]; 224 | [self.rightMenuViewController didMoveToParentViewController:self]; 225 | } 226 | 227 | self.contentViewContainer.frame = self.view.bounds; 228 | self.contentViewContainer.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 229 | 230 | [self addChildViewController:self.contentViewController]; 231 | self.contentViewController.view.frame = self.view.bounds; 232 | [self.contentViewContainer addSubview:self.contentViewController.view]; 233 | [self.contentViewController didMoveToParentViewController:self]; 234 | 235 | self.menuViewContainer.alpha = !self.fadeMenuView ?: 0; 236 | if (self.scaleBackgroundImageView) 237 | self.backgroundImageView.transform = CGAffineTransformMakeScale(1.7f, 1.7f); 238 | 239 | [self addMenuViewControllerMotionEffects]; 240 | 241 | if (self.panGestureEnabled) { 242 | self.view.multipleTouchEnabled = NO; 243 | UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panGestureRecognized:)]; 244 | panGestureRecognizer.delegate = self; 245 | [self.view addGestureRecognizer:panGestureRecognizer]; 246 | } 247 | 248 | [self updateContentViewShadow]; 249 | } 250 | 251 | #pragma mark - 252 | #pragma mark Private methods 253 | 254 | - (void)presentMenuViewContainerWithMenuViewController:(UIViewController *)menuViewController 255 | { 256 | self.menuViewContainer.transform = CGAffineTransformIdentity; 257 | if (self.scaleBackgroundImageView) { 258 | self.backgroundImageView.transform = CGAffineTransformIdentity; 259 | self.backgroundImageView.frame = self.view.bounds; 260 | } 261 | self.menuViewContainer.frame = self.view.bounds; 262 | if (self.scaleMenuView) { 263 | self.menuViewContainer.transform = self.menuViewControllerTransformation; 264 | } 265 | self.menuViewContainer.alpha = !self.fadeMenuView ?: 0; 266 | if (self.scaleBackgroundImageView) 267 | self.backgroundImageView.transform = CGAffineTransformMakeScale(1.7f, 1.7f); 268 | 269 | if ([self.delegate conformsToProtocol:@protocol(RESideMenuDelegate)] && [self.delegate respondsToSelector:@selector(sideMenu:willShowMenuViewController:)]) { 270 | [self.delegate sideMenu:self willShowMenuViewController:menuViewController]; 271 | } 272 | } 273 | 274 | - (void)showLeftMenuViewController 275 | { 276 | if (!self.leftMenuViewController) { 277 | return; 278 | } 279 | self.leftMenuViewController.view.hidden = NO; 280 | self.rightMenuViewController.view.hidden = YES; 281 | [self.view.window endEditing:YES]; 282 | [self addContentButton]; 283 | [self updateContentViewShadow]; 284 | [self resetContentViewScale]; 285 | 286 | [UIView animateWithDuration:self.animationDuration animations:^{ 287 | if (self.scaleContentView) { 288 | self.contentViewContainer.transform = CGAffineTransformMakeScale(self.contentViewScaleValue, self.contentViewScaleValue); 289 | } else { 290 | self.contentViewContainer.transform = CGAffineTransformIdentity; 291 | } 292 | 293 | if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_7_1) { 294 | self.contentViewContainer.center = CGPointMake((UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation]) ? self.contentViewInLandscapeOffsetCenterX + CGRectGetWidth(self.view.frame) : self.contentViewInPortraitOffsetCenterX + CGRectGetWidth(self.view.frame)), self.contentViewContainer.center.y); 295 | } else { 296 | self.contentViewContainer.center = CGPointMake((UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation]) ? self.contentViewInLandscapeOffsetCenterX + CGRectGetHeight(self.view.frame) : self.contentViewInPortraitOffsetCenterX + CGRectGetWidth(self.view.frame)), self.contentViewContainer.center.y); 297 | } 298 | 299 | self.menuViewContainer.alpha = !self.fadeMenuView ?: 1.0f; 300 | 301 | self.menuViewContainer.transform = CGAffineTransformIdentity; 302 | if (self.scaleBackgroundImageView) 303 | self.backgroundImageView.transform = CGAffineTransformIdentity; 304 | 305 | } completion:^(BOOL finished) { 306 | [self addContentViewControllerMotionEffects]; 307 | 308 | if (!self.visible && [self.delegate conformsToProtocol:@protocol(RESideMenuDelegate)] && [self.delegate respondsToSelector:@selector(sideMenu:didShowMenuViewController:)]) { 309 | [self.delegate sideMenu:self didShowMenuViewController:self.leftMenuViewController]; 310 | } 311 | 312 | self.visible = YES; 313 | self.leftMenuVisible = YES; 314 | }]; 315 | 316 | [self statusBarNeedsAppearanceUpdate]; 317 | } 318 | 319 | - (void)showRightMenuViewController 320 | { 321 | if (!self.rightMenuViewController) { 322 | return; 323 | } 324 | self.leftMenuViewController.view.hidden = YES; 325 | self.rightMenuViewController.view.hidden = NO; 326 | [self.view.window endEditing:YES]; 327 | [self addContentButton]; 328 | [self updateContentViewShadow]; 329 | [self resetContentViewScale]; 330 | 331 | [[UIApplication sharedApplication] beginIgnoringInteractionEvents]; 332 | [UIView animateWithDuration:self.animationDuration animations:^{ 333 | if (self.scaleContentView) { 334 | self.contentViewContainer.transform = CGAffineTransformMakeScale(self.contentViewScaleValue, self.contentViewScaleValue); 335 | } else { 336 | self.contentViewContainer.transform = CGAffineTransformIdentity; 337 | } 338 | self.contentViewContainer.center = CGPointMake((UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation]) ? -self.contentViewInLandscapeOffsetCenterX : -self.contentViewInPortraitOffsetCenterX), self.contentViewContainer.center.y); 339 | 340 | self.menuViewContainer.alpha = !self.fadeMenuView ?: 1.0f; 341 | self.menuViewContainer.transform = CGAffineTransformIdentity; 342 | if (self.scaleBackgroundImageView) 343 | self.backgroundImageView.transform = CGAffineTransformIdentity; 344 | 345 | } completion:^(BOOL finished) { 346 | if (!self.rightMenuVisible && [self.delegate conformsToProtocol:@protocol(RESideMenuDelegate)] && [self.delegate respondsToSelector:@selector(sideMenu:didShowMenuViewController:)]) { 347 | [self.delegate sideMenu:self didShowMenuViewController:self.rightMenuViewController]; 348 | } 349 | 350 | self.visible = !(self.contentViewContainer.frame.size.width == self.view.bounds.size.width && self.contentViewContainer.frame.size.height == self.view.bounds.size.height && self.contentViewContainer.frame.origin.x == 0 && self.contentViewContainer.frame.origin.y == 0); 351 | self.rightMenuVisible = self.visible; 352 | [[UIApplication sharedApplication] endIgnoringInteractionEvents]; 353 | [self addContentViewControllerMotionEffects]; 354 | }]; 355 | 356 | [self statusBarNeedsAppearanceUpdate]; 357 | } 358 | 359 | - (void)resetContentViewScale 360 | { 361 | CGAffineTransform t = self.contentViewContainer.transform; 362 | CGFloat scale = sqrt(t.a * t.a + t.c * t.c); 363 | CGRect frame = self.contentViewContainer.frame; 364 | self.contentViewContainer.transform = CGAffineTransformIdentity; 365 | self.contentViewContainer.transform = CGAffineTransformMakeScale(scale, scale); 366 | self.contentViewContainer.frame = frame; 367 | } 368 | 369 | - (void)hideViewController:(UIViewController *)viewController 370 | { 371 | [viewController willMoveToParentViewController:nil]; 372 | [viewController.view removeFromSuperview]; 373 | [viewController removeFromParentViewController]; 374 | } 375 | 376 | - (void)hideMenuViewControllerAnimated:(BOOL)animated 377 | { 378 | BOOL rightMenuVisible = self.rightMenuVisible; 379 | if ([self.delegate conformsToProtocol:@protocol(RESideMenuDelegate)] && [self.delegate respondsToSelector:@selector(sideMenu:willHideMenuViewController:)]) { 380 | [self.delegate sideMenu:self willHideMenuViewController:rightMenuVisible ? self.rightMenuViewController : self.leftMenuViewController]; 381 | } 382 | 383 | self.visible = NO; 384 | self.leftMenuVisible = NO; 385 | self.rightMenuVisible = NO; 386 | [self.contentButton removeFromSuperview]; 387 | 388 | __typeof (self) __weak weakSelf = self; 389 | void (^animationBlock)(void) = ^{ 390 | __typeof (weakSelf) __strong strongSelf = weakSelf; 391 | if (!strongSelf) { 392 | return; 393 | } 394 | strongSelf.contentViewContainer.transform = CGAffineTransformIdentity; 395 | strongSelf.contentViewContainer.frame = strongSelf.view.bounds; 396 | if (strongSelf.scaleMenuView) { 397 | strongSelf.menuViewContainer.transform = strongSelf.menuViewControllerTransformation; 398 | } 399 | strongSelf.menuViewContainer.alpha = !self.fadeMenuView ?: 0; 400 | if (strongSelf.scaleBackgroundImageView) { 401 | strongSelf.backgroundImageView.transform = CGAffineTransformMakeScale(1.7f, 1.7f); 402 | } 403 | if (strongSelf.parallaxEnabled) { 404 | IF_IOS7_OR_GREATER( 405 | for (UIMotionEffect *effect in strongSelf.contentViewContainer.motionEffects) { 406 | [strongSelf.contentViewContainer removeMotionEffect:effect]; 407 | } 408 | ); 409 | } 410 | }; 411 | void (^completionBlock)(void) = ^{ 412 | __typeof (weakSelf) __strong strongSelf = weakSelf; 413 | if (!strongSelf) { 414 | return; 415 | } 416 | if (!strongSelf.visible && [strongSelf.delegate conformsToProtocol:@protocol(RESideMenuDelegate)] && [strongSelf.delegate respondsToSelector:@selector(sideMenu:didHideMenuViewController:)]) { 417 | [strongSelf.delegate sideMenu:strongSelf didHideMenuViewController:rightMenuVisible ? strongSelf.rightMenuViewController : strongSelf.leftMenuViewController]; 418 | } 419 | }; 420 | 421 | if (animated) { 422 | [[UIApplication sharedApplication] beginIgnoringInteractionEvents]; 423 | [UIView animateWithDuration:self.animationDuration animations:^{ 424 | animationBlock(); 425 | } completion:^(BOOL finished) { 426 | [[UIApplication sharedApplication] endIgnoringInteractionEvents]; 427 | completionBlock(); 428 | }]; 429 | } else { 430 | animationBlock(); 431 | completionBlock(); 432 | } 433 | [self statusBarNeedsAppearanceUpdate]; 434 | } 435 | 436 | - (void)addContentButton 437 | { 438 | if (self.contentButton.superview) 439 | return; 440 | 441 | self.contentButton.autoresizingMask = UIViewAutoresizingNone; 442 | self.contentButton.frame = self.contentViewContainer.bounds; 443 | self.contentButton.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 444 | [self.contentViewContainer addSubview:self.contentButton]; 445 | } 446 | 447 | - (void)statusBarNeedsAppearanceUpdate 448 | { 449 | if ([self respondsToSelector:@selector(setNeedsStatusBarAppearanceUpdate)]) { 450 | [UIView animateWithDuration:0.3f animations:^{ 451 | [self performSelector:@selector(setNeedsStatusBarAppearanceUpdate)]; 452 | }]; 453 | } 454 | } 455 | 456 | - (void)updateContentViewShadow 457 | { 458 | if (self.contentViewShadowEnabled) { 459 | CALayer *layer = self.contentViewContainer.layer; 460 | UIBezierPath *path = [UIBezierPath bezierPathWithRect:layer.bounds]; 461 | layer.shadowPath = path.CGPath; 462 | layer.shadowColor = self.contentViewShadowColor.CGColor; 463 | layer.shadowOffset = self.contentViewShadowOffset; 464 | layer.shadowOpacity = self.contentViewShadowOpacity; 465 | layer.shadowRadius = self.contentViewShadowRadius; 466 | } 467 | } 468 | 469 | #pragma mark - 470 | #pragma mark iOS 7 Motion Effects (Private) 471 | 472 | - (void)addMenuViewControllerMotionEffects 473 | { 474 | if (self.parallaxEnabled) { 475 | IF_IOS7_OR_GREATER( 476 | for (UIMotionEffect *effect in self.menuViewContainer.motionEffects) { 477 | [self.menuViewContainer removeMotionEffect:effect]; 478 | } 479 | UIInterpolatingMotionEffect *interpolationHorizontal = [[UIInterpolatingMotionEffect alloc]initWithKeyPath:@"center.x" type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis]; 480 | interpolationHorizontal.minimumRelativeValue = @(self.parallaxMenuMinimumRelativeValue); 481 | interpolationHorizontal.maximumRelativeValue = @(self.parallaxMenuMaximumRelativeValue); 482 | 483 | UIInterpolatingMotionEffect *interpolationVertical = [[UIInterpolatingMotionEffect alloc]initWithKeyPath:@"center.y" type:UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis]; 484 | interpolationVertical.minimumRelativeValue = @(self.parallaxMenuMinimumRelativeValue); 485 | interpolationVertical.maximumRelativeValue = @(self.parallaxMenuMaximumRelativeValue); 486 | 487 | [self.menuViewContainer addMotionEffect:interpolationHorizontal]; 488 | [self.menuViewContainer addMotionEffect:interpolationVertical]; 489 | ); 490 | } 491 | } 492 | 493 | - (void)addContentViewControllerMotionEffects 494 | { 495 | if (self.parallaxEnabled) { 496 | IF_IOS7_OR_GREATER( 497 | for (UIMotionEffect *effect in self.contentViewContainer.motionEffects) { 498 | [self.contentViewContainer removeMotionEffect:effect]; 499 | } 500 | [UIView animateWithDuration:0.2 animations:^{ 501 | UIInterpolatingMotionEffect *interpolationHorizontal = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.x" type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis]; 502 | interpolationHorizontal.minimumRelativeValue = @(self.parallaxContentMinimumRelativeValue); 503 | interpolationHorizontal.maximumRelativeValue = @(self.parallaxContentMaximumRelativeValue); 504 | 505 | UIInterpolatingMotionEffect *interpolationVertical = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.y" type:UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis]; 506 | interpolationVertical.minimumRelativeValue = @(self.parallaxContentMinimumRelativeValue); 507 | interpolationVertical.maximumRelativeValue = @(self.parallaxContentMaximumRelativeValue); 508 | 509 | [self.contentViewContainer addMotionEffect:interpolationHorizontal]; 510 | [self.contentViewContainer addMotionEffect:interpolationVertical]; 511 | }]; 512 | ); 513 | } 514 | } 515 | 516 | #pragma mark - 517 | #pragma mark UIGestureRecognizer Delegate (Private) 518 | 519 | - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch 520 | { 521 | IF_IOS7_OR_GREATER( 522 | if (self.interactivePopGestureRecognizerEnabled && [self.contentViewController isKindOfClass:[UINavigationController class]]) { 523 | UINavigationController *navigationController = (UINavigationController *)self.contentViewController; 524 | if (navigationController.viewControllers.count > 1 && navigationController.interactivePopGestureRecognizer.enabled) { 525 | return NO; 526 | } 527 | } 528 | ); 529 | 530 | if (self.panFromEdge && [gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]] && !self.visible) { 531 | CGPoint point = [touch locationInView:gestureRecognizer.view]; 532 | if (point.x < 20.0 || point.x > self.view.frame.size.width - 20.0) { 533 | return YES; 534 | } else { 535 | return NO; 536 | } 537 | } 538 | 539 | return YES; 540 | } 541 | 542 | #pragma mark - 543 | #pragma mark Pan gesture recognizer (Private) 544 | 545 | - (void)panGestureRecognized:(UIPanGestureRecognizer *)recognizer 546 | { 547 | if ([self.delegate conformsToProtocol:@protocol(RESideMenuDelegate)] && [self.delegate respondsToSelector:@selector(sideMenu:didRecognizePanGesture:)]) 548 | [self.delegate sideMenu:self didRecognizePanGesture:recognizer]; 549 | 550 | if (!self.panGestureEnabled) { 551 | return; 552 | } 553 | 554 | CGPoint point = [recognizer translationInView:self.view]; 555 | 556 | if (point.x <= 0 && !self.rightPanEnabled && !self.leftMenuVisible) { 557 | return; 558 | } 559 | if (point.x > 0 && !self.leftPanEnabled && !self.rightMenuVisible) { 560 | return; 561 | } 562 | 563 | if (recognizer.state == UIGestureRecognizerStateBegan) { 564 | [self updateContentViewShadow]; 565 | 566 | self.originalPoint = CGPointMake(self.contentViewContainer.center.x - CGRectGetWidth(self.contentViewContainer.bounds) / 2.0, 567 | self.contentViewContainer.center.y - CGRectGetHeight(self.contentViewContainer.bounds) / 2.0); 568 | self.menuViewContainer.transform = CGAffineTransformIdentity; 569 | if (self.scaleBackgroundImageView) { 570 | self.backgroundImageView.transform = CGAffineTransformIdentity; 571 | self.backgroundImageView.frame = self.view.bounds; 572 | } 573 | self.menuViewContainer.frame = self.view.bounds; 574 | [self addContentButton]; 575 | [self.view.window endEditing:YES]; 576 | self.didNotifyDelegate = NO; 577 | } 578 | 579 | if (recognizer.state == UIGestureRecognizerStateChanged) { 580 | CGFloat delta = 0; 581 | if (self.visible) { 582 | delta = self.originalPoint.x != 0 ? (point.x + self.originalPoint.x) / self.originalPoint.x : 0; 583 | } else { 584 | delta = point.x / self.view.frame.size.width; 585 | } 586 | delta = MIN(fabs(delta), 1.6); 587 | 588 | CGFloat contentViewScale = self.scaleContentView ? 1 - ((1 - self.contentViewScaleValue) * delta) : 1; 589 | 590 | CGFloat backgroundViewScale = 1.7f - (0.7f * delta); 591 | CGFloat menuViewScale = 1.5f - (0.5f * delta); 592 | 593 | if (!self.bouncesHorizontally) { 594 | contentViewScale = MAX(contentViewScale, self.contentViewScaleValue); 595 | backgroundViewScale = MAX(backgroundViewScale, 1.0); 596 | menuViewScale = MAX(menuViewScale, 1.0); 597 | } 598 | 599 | self.menuViewContainer.alpha = !self.fadeMenuView ?: delta; 600 | 601 | if (self.scaleBackgroundImageView) { 602 | self.backgroundImageView.transform = CGAffineTransformMakeScale(backgroundViewScale, backgroundViewScale); 603 | } 604 | 605 | if (self.scaleMenuView) { 606 | self.menuViewContainer.transform = CGAffineTransformMakeScale(menuViewScale, menuViewScale); 607 | } 608 | 609 | if (self.scaleBackgroundImageView) { 610 | if (backgroundViewScale < 1) { 611 | self.backgroundImageView.transform = CGAffineTransformIdentity; 612 | } 613 | } 614 | 615 | if (!self.bouncesHorizontally && self.visible) { 616 | if (self.contentViewContainer.frame.origin.x > self.contentViewContainer.frame.size.width / 2.0) 617 | point.x = MIN(0.0, point.x); 618 | 619 | if (self.contentViewContainer.frame.origin.x < -(self.contentViewContainer.frame.size.width / 2.0)) 620 | point.x = MAX(0.0, point.x); 621 | } 622 | 623 | // Limit size 624 | // 625 | if (point.x < 0) { 626 | point.x = MAX(point.x, -[UIScreen mainScreen].bounds.size.height); 627 | } else { 628 | point.x = MIN(point.x, [UIScreen mainScreen].bounds.size.height); 629 | } 630 | [recognizer setTranslation:point inView:self.view]; 631 | 632 | if (!self.didNotifyDelegate) { 633 | if (point.x > 0) { 634 | if (!self.visible && [self.delegate conformsToProtocol:@protocol(RESideMenuDelegate)] && [self.delegate respondsToSelector:@selector(sideMenu:willShowMenuViewController:)]) { 635 | [self.delegate sideMenu:self willShowMenuViewController:self.leftMenuViewController]; 636 | } 637 | } 638 | if (point.x < 0) { 639 | if (!self.visible && [self.delegate conformsToProtocol:@protocol(RESideMenuDelegate)] && [self.delegate respondsToSelector:@selector(sideMenu:willShowMenuViewController:)]) { 640 | [self.delegate sideMenu:self willShowMenuViewController:self.rightMenuViewController]; 641 | } 642 | } 643 | self.didNotifyDelegate = YES; 644 | } 645 | 646 | if (contentViewScale > 1) { 647 | CGFloat oppositeScale = (1 - (contentViewScale - 1)); 648 | self.contentViewContainer.transform = CGAffineTransformMakeScale(oppositeScale, oppositeScale); 649 | self.contentViewContainer.transform = CGAffineTransformTranslate(self.contentViewContainer.transform, point.x, 0); 650 | } else { 651 | self.contentViewContainer.transform = CGAffineTransformMakeScale(contentViewScale, contentViewScale); 652 | self.contentViewContainer.transform = CGAffineTransformTranslate(self.contentViewContainer.transform, point.x, 0); 653 | } 654 | 655 | self.leftMenuViewController.view.hidden = self.contentViewContainer.frame.origin.x < 0; 656 | self.rightMenuViewController.view.hidden = self.contentViewContainer.frame.origin.x > 0; 657 | 658 | if (!self.leftMenuViewController && self.contentViewContainer.frame.origin.x > 0) { 659 | self.contentViewContainer.transform = CGAffineTransformIdentity; 660 | self.contentViewContainer.frame = self.view.bounds; 661 | self.visible = NO; 662 | self.leftMenuVisible = NO; 663 | } else if (!self.rightMenuViewController && self.contentViewContainer.frame.origin.x < 0) { 664 | self.contentViewContainer.transform = CGAffineTransformIdentity; 665 | self.contentViewContainer.frame = self.view.bounds; 666 | self.visible = NO; 667 | self.rightMenuVisible = NO; 668 | } 669 | 670 | [self statusBarNeedsAppearanceUpdate]; 671 | } 672 | 673 | if (recognizer.state == UIGestureRecognizerStateEnded) { 674 | self.didNotifyDelegate = NO; 675 | if (self.panMinimumOpenThreshold > 0 && ( 676 | (self.contentViewContainer.frame.origin.x < 0 && self.contentViewContainer.frame.origin.x > -((NSInteger)self.panMinimumOpenThreshold)) || 677 | (self.contentViewContainer.frame.origin.x > 0 && self.contentViewContainer.frame.origin.x < self.panMinimumOpenThreshold)) 678 | ) { 679 | [self hideMenuViewController]; 680 | } 681 | else if (self.contentViewContainer.frame.origin.x == 0) { 682 | [self hideMenuViewControllerAnimated:NO]; 683 | } 684 | else { 685 | if ([recognizer velocityInView:self.view].x > 0) { 686 | if (self.contentViewContainer.frame.origin.x < 0) { 687 | [self hideMenuViewController]; 688 | } else { 689 | if (self.leftMenuViewController) { 690 | [self showLeftMenuViewController]; 691 | } 692 | } 693 | } else { 694 | if (self.contentViewContainer.frame.origin.x < 20) { 695 | if (self.rightMenuViewController) { 696 | [self showRightMenuViewController]; 697 | } 698 | } else { 699 | [self hideMenuViewController]; 700 | } 701 | } 702 | } 703 | } 704 | } 705 | 706 | #pragma mark - 707 | #pragma mark Setters 708 | 709 | - (void)setBackgroundImage:(UIImage *)backgroundImage 710 | { 711 | _backgroundImage = backgroundImage; 712 | if (self.backgroundImageView) 713 | self.backgroundImageView.image = backgroundImage; 714 | } 715 | 716 | - (void)setContentViewController:(UIViewController *)contentViewController 717 | { 718 | if (!_contentViewController) { 719 | _contentViewController = contentViewController; 720 | return; 721 | } 722 | [self hideViewController:_contentViewController]; 723 | _contentViewController = contentViewController; 724 | 725 | [self addChildViewController:self.contentViewController]; 726 | self.contentViewController.view.frame = self.view.bounds; 727 | [self.contentViewContainer addSubview:self.contentViewController.view]; 728 | [self.contentViewController didMoveToParentViewController:self]; 729 | 730 | [self updateContentViewShadow]; 731 | 732 | if (self.visible) { 733 | [self addContentViewControllerMotionEffects]; 734 | } 735 | } 736 | 737 | - (void)setLeftMenuViewController:(UIViewController *)leftMenuViewController 738 | { 739 | if (!_leftMenuViewController) { 740 | _leftMenuViewController = leftMenuViewController; 741 | return; 742 | } 743 | [self hideViewController:_leftMenuViewController]; 744 | _leftMenuViewController = leftMenuViewController; 745 | 746 | [self addChildViewController:self.leftMenuViewController]; 747 | self.leftMenuViewController.view.frame = self.view.bounds; 748 | self.leftMenuViewController.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 749 | [self.menuViewContainer addSubview:self.leftMenuViewController.view]; 750 | [self.leftMenuViewController didMoveToParentViewController:self]; 751 | 752 | [self addMenuViewControllerMotionEffects]; 753 | [self.view bringSubviewToFront:self.contentViewContainer]; 754 | } 755 | 756 | - (void)setRightMenuViewController:(UIViewController *)rightMenuViewController 757 | { 758 | if (!_rightMenuViewController) { 759 | _rightMenuViewController = rightMenuViewController; 760 | return; 761 | } 762 | [self hideViewController:_rightMenuViewController]; 763 | _rightMenuViewController = rightMenuViewController; 764 | 765 | [self addChildViewController:self.rightMenuViewController]; 766 | self.rightMenuViewController.view.frame = self.view.bounds; 767 | self.rightMenuViewController.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 768 | [self.menuViewContainer addSubview:self.rightMenuViewController.view]; 769 | [self.rightMenuViewController didMoveToParentViewController:self]; 770 | 771 | [self addMenuViewControllerMotionEffects]; 772 | [self.view bringSubviewToFront:self.contentViewContainer]; 773 | } 774 | 775 | #pragma mark - 776 | #pragma mark View Controller Rotation handler 777 | 778 | - (BOOL)shouldAutorotate 779 | { 780 | return self.contentViewController.shouldAutorotate; 781 | } 782 | 783 | - (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration 784 | { 785 | if (self.visible) { 786 | self.menuViewContainer.bounds = self.view.bounds; 787 | self.contentViewContainer.transform = CGAffineTransformIdentity; 788 | self.contentViewContainer.frame = self.view.bounds; 789 | 790 | if (self.scaleContentView) { 791 | self.contentViewContainer.transform = CGAffineTransformMakeScale(self.contentViewScaleValue, self.contentViewScaleValue); 792 | } else { 793 | self.contentViewContainer.transform = CGAffineTransformIdentity; 794 | } 795 | 796 | CGPoint center; 797 | if (self.leftMenuVisible) { 798 | if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_7_1) { 799 | center = CGPointMake((UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation) ? self.contentViewInLandscapeOffsetCenterX + CGRectGetWidth(self.view.frame) : self.contentViewInPortraitOffsetCenterX + CGRectGetWidth(self.view.frame)), self.contentViewContainer.center.y); 800 | } else { 801 | center = CGPointMake((UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation) ? self.contentViewInLandscapeOffsetCenterX + CGRectGetHeight(self.view.frame) : self.contentViewInPortraitOffsetCenterX + CGRectGetWidth(self.view.frame)), self.contentViewContainer.center.y); 802 | } 803 | } else { 804 | center = CGPointMake((UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation) ? -self.contentViewInLandscapeOffsetCenterX : -self.contentViewInPortraitOffsetCenterX), self.contentViewContainer.center.y); 805 | } 806 | 807 | self.contentViewContainer.center = center; 808 | } 809 | 810 | [self updateContentViewShadow]; 811 | } 812 | 813 | #pragma mark - 814 | #pragma mark Status Bar Appearance Management 815 | 816 | - (UIStatusBarStyle)preferredStatusBarStyle 817 | { 818 | UIStatusBarStyle statusBarStyle = UIStatusBarStyleDefault; 819 | IF_IOS7_OR_GREATER( 820 | statusBarStyle = self.visible ? self.menuPreferredStatusBarStyle : self.contentViewController.preferredStatusBarStyle; 821 | if (self.contentViewContainer.frame.origin.y > 10) { 822 | statusBarStyle = self.menuPreferredStatusBarStyle; 823 | } else { 824 | statusBarStyle = self.contentViewController.preferredStatusBarStyle; 825 | } 826 | ); 827 | return statusBarStyle; 828 | } 829 | 830 | - (BOOL)prefersStatusBarHidden 831 | { 832 | BOOL statusBarHidden = NO; 833 | IF_IOS7_OR_GREATER( 834 | statusBarHidden = self.visible ? self.menuPrefersStatusBarHidden : self.contentViewController.prefersStatusBarHidden; 835 | if (self.contentViewContainer.frame.origin.y > 10) { 836 | statusBarHidden = self.menuPrefersStatusBarHidden; 837 | } else { 838 | statusBarHidden = self.contentViewController.prefersStatusBarHidden; 839 | } 840 | ); 841 | return statusBarHidden; 842 | } 843 | 844 | - (UIStatusBarAnimation)preferredStatusBarUpdateAnimation 845 | { 846 | UIStatusBarAnimation statusBarAnimation = UIStatusBarAnimationNone; 847 | IF_IOS7_OR_GREATER( 848 | statusBarAnimation = self.visible ? self.leftMenuViewController.preferredStatusBarUpdateAnimation : self.contentViewController.preferredStatusBarUpdateAnimation; 849 | if (self.contentViewContainer.frame.origin.y > 10) { 850 | statusBarAnimation = self.leftMenuViewController.preferredStatusBarUpdateAnimation; 851 | } else { 852 | statusBarAnimation = self.contentViewController.preferredStatusBarUpdateAnimation; 853 | } 854 | ); 855 | return statusBarAnimation; 856 | } 857 | 858 | @end 859 | -------------------------------------------------------------------------------- /Classes/RESideMenu/UIViewController+RESideMenu.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIViewController+RESideMenu.h 3 | // RESideMenu 4 | // 5 | // Copyright (c) 2013-2014 Roman Efimov (https://github.com/romaonthego) 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | // 25 | 26 | #import 27 | 28 | @class RESideMenu; 29 | 30 | @interface UIViewController (RESideMenu) 31 | 32 | @property (strong, readonly, nonatomic) RESideMenu *sideMenuViewController; 33 | 34 | // IB Action Helper methods 35 | 36 | - (IBAction)presentLeftMenuViewController:(id)sender; 37 | - (IBAction)presentRightMenuViewController:(id)sender; 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /Classes/RESideMenu/UIViewController+RESideMenu.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIViewController+RESideMenu.m 3 | // RESideMenu 4 | // 5 | // Copyright (c) 2013-2014 Roman Efimov (https://github.com/romaonthego) 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | // 25 | 26 | #import "UIViewController+RESideMenu.h" 27 | #import "RESideMenu.h" 28 | 29 | @implementation UIViewController (RESideMenu) 30 | 31 | - (RESideMenu *)sideMenuViewController 32 | { 33 | UIViewController *iter = self.parentViewController; 34 | while (iter) { 35 | if ([iter isKindOfClass:[RESideMenu class]]) { 36 | return (RESideMenu *)iter; 37 | } else if (iter.parentViewController && iter.parentViewController != iter) { 38 | iter = iter.parentViewController; 39 | } else { 40 | iter = nil; 41 | } 42 | } 43 | return nil; 44 | } 45 | 46 | #pragma mark - 47 | #pragma mark IB Action Helper methods 48 | 49 | - (IBAction)presentLeftMenuViewController:(id)sender 50 | { 51 | [self.sideMenuViewController presentLeftMenuViewController]; 52 | } 53 | 54 | - (IBAction)presentRightMenuViewController:(id)sender 55 | { 56 | [self.sideMenuViewController presentRightMenuViewController]; 57 | } 58 | 59 | @end 60 | -------------------------------------------------------------------------------- /DeMarcelpociotSidemenu_Prefix.pch: -------------------------------------------------------------------------------- 1 | 2 | #ifdef __OBJC__ 3 | #import 4 | #endif 5 | -------------------------------------------------------------------------------- /Demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mpociot/TiSideMenu/fecf854a3565415eea339e07f0fed3e81e83496d/Demo.gif -------------------------------------------------------------------------------- /FXBlurView/FXBlurView.h: -------------------------------------------------------------------------------- 1 | // 2 | // FXBlurView.h 3 | // 4 | // Version 1.4.3 5 | // 6 | // Created by Nick Lockwood on 25/08/2013. 7 | // Copyright (c) 2013 Charcoal Design 8 | // 9 | // Distributed under the permissive zlib License 10 | // Get the latest version from here: 11 | // 12 | // https://github.com/nicklockwood/FXBlurView 13 | // 14 | // This software is provided 'as-is', without any express or implied 15 | // warranty. In no event will the authors be held liable for any damages 16 | // arising from the use of this software. 17 | // 18 | // Permission is granted to anyone to use this software for any purpose, 19 | // including commercial applications, and to alter it and redistribute it 20 | // freely, subject to the following restrictions: 21 | // 22 | // 1. The origin of this software must not be misrepresented; you must not 23 | // claim that you wrote the original software. If you use this software 24 | // in a product, an acknowledgment in the product documentation would be 25 | // appreciated but is not required. 26 | // 27 | // 2. Altered source versions must be plainly marked as such, and must not be 28 | // misrepresented as being the original software. 29 | // 30 | // 3. This notice may not be removed or altered from any source distribution. 31 | // 32 | 33 | 34 | #import 35 | #import 36 | 37 | 38 | @interface UIImage (FXBlurView) 39 | 40 | - (UIImage *)blurredImageWithRadius:(CGFloat)radius iterations:(NSUInteger)iterations tintColor:(UIColor *)tintColor; 41 | 42 | @end 43 | 44 | 45 | @interface FXBlurView : UIView 46 | 47 | + (void)setBlurEnabled:(BOOL)blurEnabled; 48 | + (void)setUpdatesEnabled; 49 | + (void)setUpdatesDisabled; 50 | 51 | @property (nonatomic, getter = isBlurEnabled) BOOL blurEnabled; 52 | @property (nonatomic, getter = isDynamic) BOOL dynamic; 53 | @property (nonatomic, assign) NSUInteger iterations; 54 | @property (nonatomic, assign) NSTimeInterval updateInterval; 55 | @property (nonatomic, assign) CGFloat blurRadius; 56 | @property (nonatomic, strong) UIColor *tintColor; 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /FXBlurView/FXBlurView.m: -------------------------------------------------------------------------------- 1 | // 2 | // FXBlurView.m 3 | // 4 | // Version 1.4.3 5 | // 6 | // Created by Nick Lockwood on 25/08/2013. 7 | // Copyright (c) 2013 Charcoal Design 8 | // 9 | // Distributed under the permissive zlib License 10 | // Get the latest version from here: 11 | // 12 | // https://github.com/nicklockwood/FXBlurView 13 | // 14 | // This software is provided 'as-is', without any express or implied 15 | // warranty. In no event will the authors be held liable for any damages 16 | // arising from the use of this software. 17 | // 18 | // Permission is granted to anyone to use this software for any purpose, 19 | // including commercial applications, and to alter it and redistribute it 20 | // freely, subject to the following restrictions: 21 | // 22 | // 1. The origin of this software must not be misrepresented; you must not 23 | // claim that you wrote the original software. If you use this software 24 | // in a product, an acknowledgment in the product documentation would be 25 | // appreciated but is not required. 26 | // 27 | // 2. Altered source versions must be plainly marked as such, and must not be 28 | // misrepresented as being the original software. 29 | // 30 | // 3. This notice may not be removed or altered from any source distribution. 31 | // 32 | 33 | 34 | #import "FXBlurView.h" 35 | #import 36 | #import 37 | #import 38 | 39 | 40 | #import 41 | #if !__has_feature(objc_arc) 42 | #error This class requires automatic reference counting 43 | #endif 44 | 45 | 46 | @implementation UIImage (FXBlurView) 47 | 48 | - (UIImage *)blurredImageWithRadius:(CGFloat)radius iterations:(NSUInteger)iterations tintColor:(UIColor *)tintColor 49 | { 50 | //image must be nonzero size 51 | if (floorf(self.size.width) * floorf(self.size.height) <= 0.0f) return self; 52 | 53 | //boxsize must be an odd integer 54 | uint32_t boxSize = radius * self.scale; 55 | if (boxSize % 2 == 0) boxSize ++; 56 | 57 | //create image buffers 58 | CGImageRef imageRef = self.CGImage; 59 | vImage_Buffer buffer1, buffer2; 60 | buffer1.width = buffer2.width = CGImageGetWidth(imageRef); 61 | buffer1.height = buffer2.height = CGImageGetHeight(imageRef); 62 | buffer1.rowBytes = buffer2.rowBytes = CGImageGetBytesPerRow(imageRef); 63 | CFIndex bytes = buffer1.rowBytes * buffer1.height; 64 | buffer1.data = malloc(bytes); 65 | buffer2.data = malloc(bytes); 66 | 67 | //create temp buffer 68 | void *tempBuffer = malloc(vImageBoxConvolve_ARGB8888(&buffer1, &buffer2, NULL, 0, 0, boxSize, boxSize, 69 | NULL, kvImageEdgeExtend + kvImageGetTempBufferSize)); 70 | 71 | //copy image data 72 | CFDataRef dataSource = CGDataProviderCopyData(CGImageGetDataProvider(imageRef)); 73 | memcpy(buffer1.data, CFDataGetBytePtr(dataSource), bytes); 74 | CFRelease(dataSource); 75 | 76 | for (NSUInteger i = 0; i < iterations; i++) 77 | { 78 | //perform blur 79 | vImageBoxConvolve_ARGB8888(&buffer1, &buffer2, tempBuffer, 0, 0, boxSize, boxSize, NULL, kvImageEdgeExtend); 80 | 81 | //swap buffers 82 | void *temp = buffer1.data; 83 | buffer1.data = buffer2.data; 84 | buffer2.data = temp; 85 | } 86 | 87 | //free buffers 88 | free(buffer2.data); 89 | free(tempBuffer); 90 | 91 | //create image context from buffer 92 | CGContextRef ctx = CGBitmapContextCreate(buffer1.data, buffer1.width, buffer1.height, 93 | 8, buffer1.rowBytes, CGImageGetColorSpace(imageRef), 94 | CGImageGetBitmapInfo(imageRef)); 95 | 96 | //apply tint 97 | if (tintColor && CGColorGetAlpha(tintColor.CGColor) > 0.0f) 98 | { 99 | CGContextSetFillColorWithColor(ctx, [tintColor colorWithAlphaComponent:0.25].CGColor); 100 | CGContextSetBlendMode(ctx, kCGBlendModePlusLighter); 101 | CGContextFillRect(ctx, CGRectMake(0, 0, buffer1.width, buffer1.height)); 102 | } 103 | 104 | //create image from context 105 | imageRef = CGBitmapContextCreateImage(ctx); 106 | UIImage *image = [UIImage imageWithCGImage:imageRef scale:self.scale orientation:self.imageOrientation]; 107 | CGImageRelease(imageRef); 108 | CGContextRelease(ctx); 109 | free(buffer1.data); 110 | return image; 111 | } 112 | 113 | @end 114 | 115 | 116 | @interface FXBlurScheduler : NSObject 117 | 118 | @property (nonatomic, strong) NSMutableArray *views; 119 | @property (nonatomic, assign) NSInteger viewIndex; 120 | @property (nonatomic, assign) NSInteger updatesEnabled; 121 | @property (nonatomic, assign) BOOL blurEnabled; 122 | @property (nonatomic, assign) BOOL updating; 123 | 124 | @end 125 | 126 | 127 | @interface FXBlurView () 128 | 129 | @property (nonatomic, assign) BOOL iterationsSet; 130 | @property (nonatomic, assign) BOOL blurRadiusSet; 131 | @property (nonatomic, assign) BOOL dynamicSet; 132 | @property (nonatomic, assign) BOOL blurEnabledSet; 133 | @property (nonatomic, strong) NSDate *lastUpdate; 134 | 135 | - (UIImage *)snapshotOfSuperview:(UIView *)superview; 136 | 137 | @end 138 | 139 | 140 | @implementation FXBlurScheduler 141 | 142 | + (instancetype)sharedInstance 143 | { 144 | static FXBlurScheduler *sharedInstance = nil; 145 | if (!sharedInstance) 146 | { 147 | sharedInstance = [[FXBlurScheduler alloc] init]; 148 | } 149 | return sharedInstance; 150 | } 151 | 152 | - (instancetype)init 153 | { 154 | if (self = [super init]) 155 | { 156 | _updatesEnabled = 1; 157 | _blurEnabled = YES; 158 | _views = [[NSMutableArray alloc] init]; 159 | } 160 | return self; 161 | } 162 | 163 | - (void)setBlurEnabled:(BOOL)blurEnabled 164 | { 165 | _blurEnabled = blurEnabled; 166 | if (blurEnabled) 167 | { 168 | for (FXBlurView *view in self.views) 169 | { 170 | [view setNeedsDisplay]; 171 | } 172 | [self updateAsynchronously]; 173 | } 174 | } 175 | 176 | - (void)setUpdatesEnabled 177 | { 178 | _updatesEnabled ++; 179 | [self updateAsynchronously]; 180 | } 181 | 182 | - (void)setUpdatesDisabled 183 | { 184 | _updatesEnabled --; 185 | } 186 | 187 | - (void)addView:(FXBlurView *)view 188 | { 189 | if (![self.views containsObject:view]) 190 | { 191 | [self.views addObject:view]; 192 | [self updateAsynchronously]; 193 | } 194 | } 195 | 196 | - (void)removeView:(FXBlurView *)view 197 | { 198 | NSInteger index = [self.views indexOfObject:view]; 199 | if (index != NSNotFound) 200 | { 201 | if (index <= self.viewIndex) 202 | { 203 | self.viewIndex --; 204 | } 205 | [self.views removeObjectAtIndex:index]; 206 | } 207 | } 208 | 209 | - (void)updateAsynchronously 210 | { 211 | if (self.blurEnabled && !self.updating && self.updatesEnabled > 0 && [self.views count]) 212 | { 213 | //loop through until we find a view that's ready to be drawn 214 | self.viewIndex = self.viewIndex % [self.views count]; 215 | for (NSUInteger i = self.viewIndex; i < [self.views count]; i++) 216 | { 217 | FXBlurView *view = self.views[i]; 218 | if (view.blurEnabled && view.dynamic && view.window && 219 | (!view.lastUpdate || [view.lastUpdate timeIntervalSinceNow] < -view.updateInterval) && 220 | !CGRectIsEmpty(view.bounds) && !CGRectIsEmpty(view.superview.bounds)) 221 | { 222 | self.updating = YES; 223 | UIImage *snapshot = [view snapshotOfSuperview:view.superview]; 224 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{ 225 | 226 | UIImage *blurredImage = [snapshot blurredImageWithRadius:view.blurRadius 227 | iterations:view.iterations 228 | tintColor:view.tintColor]; 229 | dispatch_sync(dispatch_get_main_queue(), ^{ 230 | 231 | //set image 232 | self.updating = NO; 233 | if (view.dynamic) 234 | { 235 | view.layer.contents = (id)blurredImage.CGImage; 236 | view.layer.contentsScale = blurredImage.scale; 237 | } 238 | 239 | //render next view 240 | self.viewIndex = i + 1; 241 | [self performSelectorOnMainThread:@selector(updateAsynchronously) withObject:nil 242 | waitUntilDone:NO modes:@[NSDefaultRunLoopMode, UITrackingRunLoopMode]]; 243 | }); 244 | }); 245 | return; 246 | } 247 | } 248 | 249 | //try again 250 | self.viewIndex = 0; 251 | [self performSelectorOnMainThread:@selector(updateAsynchronously) withObject:nil 252 | waitUntilDone:NO modes:@[NSDefaultRunLoopMode, UITrackingRunLoopMode]]; 253 | } 254 | } 255 | 256 | @end 257 | 258 | 259 | @implementation FXBlurView 260 | 261 | + (void)setBlurEnabled:(BOOL)blurEnabled 262 | { 263 | [FXBlurScheduler sharedInstance].blurEnabled = blurEnabled; 264 | } 265 | 266 | + (void)setUpdatesEnabled 267 | { 268 | [[FXBlurScheduler sharedInstance] setUpdatesEnabled]; 269 | } 270 | 271 | + (void)setUpdatesDisabled 272 | { 273 | [[FXBlurScheduler sharedInstance] setUpdatesDisabled]; 274 | } 275 | 276 | - (void)setUp 277 | { 278 | if (!_iterationsSet) _iterations = 3; 279 | if (!_blurRadiusSet) _blurRadius = 40.0f; 280 | if (!_dynamicSet) _dynamic = YES; 281 | if (!_blurEnabledSet) _blurEnabled = YES; 282 | self.updateInterval = _updateInterval; 283 | 284 | unsigned int numberOfMethods; 285 | Method *methods = class_copyMethodList([UIView class], &numberOfMethods); 286 | for (unsigned int i = 0; i < numberOfMethods; i++) 287 | { 288 | Method method = methods[i]; 289 | SEL selector = method_getName(method); 290 | if (selector == @selector(tintColor)) 291 | { 292 | _tintColor = ((id (*)(id,SEL))method_getImplementation(method))(self, selector); 293 | break; 294 | } 295 | } 296 | free(methods); 297 | } 298 | 299 | - (id)initWithFrame:(CGRect)frame 300 | { 301 | if ((self = [super initWithFrame:frame])) 302 | { 303 | [self setUp]; 304 | self.clipsToBounds = YES; 305 | } 306 | return self; 307 | } 308 | 309 | - (id)initWithCoder:(NSCoder *)aDecoder 310 | { 311 | if ((self = [super initWithCoder:aDecoder])) 312 | { 313 | [self setUp]; 314 | } 315 | return self; 316 | } 317 | 318 | - (void)dealloc 319 | { 320 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 321 | } 322 | 323 | - (void)setIterations:(NSUInteger)iterations 324 | { 325 | _iterationsSet = YES; 326 | _iterations = iterations; 327 | [self setNeedsDisplay]; 328 | } 329 | 330 | - (void)setBlurRadius:(CGFloat)blurRadius 331 | { 332 | _blurRadiusSet = YES; 333 | _blurRadius = blurRadius; 334 | [self setNeedsDisplay]; 335 | } 336 | 337 | - (void)setBlurEnabled:(BOOL)blurEnabled 338 | { 339 | _blurEnabledSet = YES; 340 | if (_blurEnabled != blurEnabled) 341 | { 342 | _blurEnabled = blurEnabled; 343 | [self schedule]; 344 | if (_blurEnabled) 345 | { 346 | [self setNeedsDisplay]; 347 | } 348 | } 349 | } 350 | 351 | - (void)setDynamic:(BOOL)dynamic 352 | { 353 | _dynamicSet = YES; 354 | if (_dynamic != dynamic) 355 | { 356 | _dynamic = dynamic; 357 | [self schedule]; 358 | if (!dynamic) 359 | { 360 | [self setNeedsDisplay]; 361 | } 362 | } 363 | } 364 | 365 | - (void)setUpdateInterval:(NSTimeInterval)updateInterval 366 | { 367 | _updateInterval = updateInterval; 368 | if (_updateInterval <= 0) _updateInterval = 1.0/60; 369 | } 370 | 371 | - (void)setTintColor:(UIColor *)tintColor 372 | { 373 | _tintColor = tintColor; 374 | [self setNeedsDisplay]; 375 | } 376 | 377 | - (void)didMoveToSuperview 378 | { 379 | [super didMoveToSuperview]; 380 | [self.layer setNeedsDisplay]; 381 | } 382 | 383 | - (void)didMoveToWindow 384 | { 385 | [super didMoveToWindow]; 386 | [self schedule]; 387 | } 388 | 389 | - (void)schedule 390 | { 391 | if (self.window && self.dynamic && self.blurEnabled) 392 | { 393 | [[FXBlurScheduler sharedInstance] addView:self]; 394 | } 395 | else 396 | { 397 | [[FXBlurScheduler sharedInstance] removeView:self]; 398 | } 399 | } 400 | 401 | - (void)setNeedsDisplay 402 | { 403 | [super setNeedsDisplay]; 404 | [self.layer setNeedsDisplay]; 405 | } 406 | 407 | - (void)displayLayer:(__unused CALayer *)layer 408 | { 409 | if ([FXBlurScheduler sharedInstance].blurEnabled && self.blurEnabled && self.superview && 410 | !CGRectIsEmpty(self.bounds) && !CGRectIsEmpty(self.superview.bounds)) 411 | { 412 | UIImage *snapshot = [self snapshotOfSuperview:self.superview]; 413 | UIImage *blurredImage = [snapshot blurredImageWithRadius:self.blurRadius 414 | iterations:self.iterations 415 | tintColor:self.tintColor]; 416 | self.layer.contents = (id)blurredImage.CGImage; 417 | self.layer.contentsScale = blurredImage.scale; 418 | } 419 | } 420 | 421 | - (UIImage *)snapshotOfSuperview:(UIView *)superview 422 | { 423 | self.lastUpdate = [NSDate date]; 424 | CGFloat scale = 0.5; 425 | if (self.iterations > 0 && ([UIScreen mainScreen].scale > 1 || self.contentMode == UIViewContentModeScaleAspectFill)) 426 | { 427 | CGFloat blockSize = 12.0f/self.iterations; 428 | scale = blockSize/MAX(blockSize * 2, floor(self.blurRadius)); 429 | } 430 | CGSize size = self.bounds.size; 431 | size.width = ceilf(size.width * scale) / scale; 432 | size.height = ceilf(size.height * scale) / scale; 433 | UIGraphicsBeginImageContextWithOptions(self.bounds.size, YES, scale); 434 | CGContextRef context = UIGraphicsGetCurrentContext(); 435 | CGContextTranslateCTM(context, -self.frame.origin.x, -self.frame.origin.y); 436 | CGContextScaleCTM(context, size.width / self.bounds.size.width, size.height / self.bounds.size.height); 437 | NSArray *hiddenViews = [self prepareSuperviewForSnapshot:superview]; 438 | [superview.layer renderInContext:context]; 439 | [self restoreSuperviewAfterSnapshot:hiddenViews]; 440 | UIImage *snapshot = UIGraphicsGetImageFromCurrentImageContext(); 441 | UIGraphicsEndImageContext(); 442 | return snapshot; 443 | } 444 | 445 | - (NSArray *)prepareSuperviewForSnapshot:(UIView *)superview 446 | { 447 | NSMutableArray *views = [NSMutableArray array]; 448 | NSInteger index = [superview.subviews indexOfObject:self]; 449 | if (index != NSNotFound) 450 | { 451 | for (NSUInteger i = index; i < [superview.subviews count]; i++) 452 | { 453 | UIView *view = superview.subviews[i]; 454 | if (!view.hidden) 455 | { 456 | view.hidden = YES; 457 | [views addObject:view]; 458 | } 459 | } 460 | } 461 | return views; 462 | } 463 | 464 | - (void)restoreSuperviewAfterSnapshot:(NSArray *)hiddenViews 465 | { 466 | for (UIView *view in hiddenViews) 467 | { 468 | view.hidden = NO; 469 | } 470 | } 471 | 472 | @end 473 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Titanium Wrapper Copyright (c) 2013 Marcel Pociot (https://github.com/mpociot). 2 | Module Copyright (c) 2013 Roman Efimov (https://github.com/romaonthego). 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | TiSideMenu 2 | =========================================== 3 | 4 | ** iOS 7 / 8 ONLY ** 5 | 6 | iOS 7 / 8 style side menu with parallax effect. 7 | 8 | Wrapper module for the great [RESideMenu](https://github.com/romaonthego/RESideMenu) 9 | 10 | Since 1.2 this module supports both left and right menu views. 11 | 12 | 13 | RESideMenu Screenshot 14 | 15 | ### Usage 16 | 17 | Use TiSideMenu as a replacement for your root window. 18 | 19 | var contentView = Ti.UI.createWindow({ 20 | background: 'red' 21 | }); 22 | 23 | var leftMenuView = Ti.UI.createWindow({ 24 | background: 'transparent' 25 | }); 26 | var rightMenuView = Ti.UI.createWindow({ 27 | background: 'transparent' 28 | }); 29 | 30 | var win = TiSideMenu.createSideMenu({ 31 | contentView: contentView, 32 | leftMenuView: leftMenuView, 33 | rightMenuView: rightMenuView, 34 | backgroundImage: 'stars.png', 35 | contentViewScaleValue: 0.2, 36 | scaleContentView: true, 37 | panGestureEnabled: false, 38 | scaleBackgroundImageView: false, 39 | scaleMenuView: true, 40 | parallaxEnabled: false, 41 | panFromEdge: true, 42 | }); 43 | win.open(); 44 | 45 | ### Replacing the content window 46 | 47 | * Setting the content window without animation `Default` 48 | 49 | win.setContentWindow(newWin); 50 | 51 | * Setting the content window with an animation 52 | 53 | win.setContentWindow({ 54 | window: newWin, 55 | animated: true 56 | }); 57 | 58 | ### Alloy 59 | 60 | To use this module within Alloy, please take a look at this repository: [de.marcelpociot.alloysidemenu](https://github.com/manumaticx/de.marcelpociot.alloysidemenu) 61 | 62 | 63 | ### Known issues 64 | If the slide animation is enabled, a bug exists where an incomplete slide results in opening empty windows through a navigation / tabgroup. 65 | To resolve this issue be sure to manually hide the side Menu before opening the new window. 66 | 67 | `win.hideMenuViewController();` 68 | 69 | 70 | ### Configuration 71 | 72 | * Enable / Disable the pan gesture 73 | `win.setPanGestureEnabled( true / false );` 74 | 75 | * Enable / Disable pan from left 76 | `win.setLeftPanEnabled( true / false );` 77 | 78 | * Enable / Disable pan from right 79 | `win.setRightPanEnabled( true / false );` 80 | 81 | * Enable / Disable then pan from the edge 82 | `win.setPanFromEdge( true / false ); ` 83 | 84 | * Enable / Disable Parallax effect 85 | `win.setParallaxEnabled( true / false ); ` 86 | 87 | * Enable / Disable Background image scaling 88 | `win.setScaleBackgroundImageView( true / false );` 89 | 90 | * Enable / Disable menu view scaling 91 | `win.setScaleMenuView( true / false );` 92 | 93 | * Enable / Disable Content view scaling 94 | `win.setScaleContentView( true / false );` 95 | 96 | * Set the content view scale value 97 | `win.setContentViewScaleValue( 0.0 - 1.0 );` 98 | 99 | Manually showing / hiding the menu: 100 | 101 | `win.hideMenuViewController()` 102 | 103 | `win.presentLeftMenuViewController()` 104 | 105 | `win.presentRightMenuViewController()` 106 | 107 | ### Options 108 | 109 | 110 | #### backgroundImage 111 | 112 | Type: `Blog / Image URL` 113 | Default: `empty String` 114 | 115 | Background image to use for the menu. 116 | 117 | #### contentViewScaleValue 118 | 119 | Type: `Float` 120 | Default: `0.5` 121 | 122 | Scale value used for the content view when the menu is shown. 123 | 124 | #### scaleContentView 125 | 126 | Type: `Boolean` 127 | Default: `true` 128 | 129 | Should the content view be scaled when the menu gets displayed. 130 | 131 | 132 | #### panGestureEnabled 133 | 134 | Type: `Boolean` 135 | Default: `true` 136 | 137 | Should the pan gesture be available for showing the menu. 138 | 139 | #### leftPanEnabled 140 | 141 | Type: `Boolean` 142 | Default: `true` 143 | 144 | Enable / Disable pan from left. 145 | 146 | #### rightPanEnabled 147 | 148 | Type: `Boolean` 149 | Default: `true` 150 | 151 | Enable / Disable pan from right. 152 | 153 | #### panFromEdge 154 | 155 | Type: `Boolean` 156 | Default: `false` 157 | 158 | Should the pan gesture only trigger when it starts from the edge 159 | 160 | #### scaleBackgroundImageView 161 | 162 | Type: `Boolean` 163 | Default: `true` 164 | 165 | Should the background image view be scaled for showing the menu. 166 | 167 | #### scaleMenuView 168 | 169 | Type: `Boolean` 170 | Default: `true` 171 | 172 | Should the menu view be scaled as it is made visible. 173 | 174 | #### parallaxEnabled 175 | 176 | Type: `Boolean` 177 | Default: `true` 178 | 179 | Enable / disable the parallax effect. 180 | 181 | 182 | 183 | Events 184 | === 185 | 186 | 187 | win.addEventListener("willShowMenuViewController",function() 188 | { 189 | alert("Will show menu view controller"); 190 | }); 191 | 192 | win.addEventListener("didShowMenuViewController",function() 193 | { 194 | alert("Did show menu view controller"); 195 | }); 196 | 197 | win.addEventListener("willHideMenuViewController",function() 198 | { 199 | alert("Will hide menu view controller"); 200 | }); 201 | 202 | win.addEventListener("didHideMenuViewController",function() 203 | { 204 | alert("Did hide menu view controller"); 205 | }); 206 | 207 | 208 | Changelog 209 | === 210 | #### 2.0 211 | * Added iOS 8 support 212 | * Removed the build-in blur APIs as they where crushing the battery 213 | * Updated to the latest RESideMenu Version 214 | 215 | #### 1.2 216 | * Added support for left and right menu views 217 | 218 | 219 | ABOUT THE AUTHOR 220 | ======================== 221 | I'm a web enthusiast located in Germany. 222 | 223 | Follow me on twitter: @marcelpociot 224 | 225 | 226 | [![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/mpociot/tisidemenu/trend.png)](https://bitdeli.com/free "Bitdeli Badge") 227 | 228 | -------------------------------------------------------------------------------- /TiSideMenu.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXAggregateTarget section */ 10 | 24416B8111C4CA220047AFDD /* Build & Test */ = { 11 | isa = PBXAggregateTarget; 12 | buildConfigurationList = 24416B8A11C4CA520047AFDD /* Build configuration list for PBXAggregateTarget "Build & Test" */; 13 | buildPhases = ( 14 | 24416B8011C4CA220047AFDD /* ShellScript */, 15 | ); 16 | dependencies = ( 17 | 24416B8511C4CA280047AFDD /* PBXTargetDependency */, 18 | ); 19 | name = "Build & Test"; 20 | productName = "Build & test"; 21 | }; 22 | /* End PBXAggregateTarget section */ 23 | 24 | /* Begin PBXBuildFile section */ 25 | 1E9D41C618283C7F00BFEAE8 /* FXBlurView.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E9D41C418283C7F00BFEAE8 /* FXBlurView.h */; }; 26 | 1E9D41C718283C7F00BFEAE8 /* FXBlurView.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E9D41C518283C7F00BFEAE8 /* FXBlurView.m */; }; 27 | 1EA8BECD181C66B700880B36 /* RECommonFunctions.h in Headers */ = {isa = PBXBuildFile; fileRef = 1EA8BEC7181C66B700880B36 /* RECommonFunctions.h */; }; 28 | 1EA8BECE181C66B700880B36 /* RECommonFunctions.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EA8BEC8181C66B700880B36 /* RECommonFunctions.m */; }; 29 | 1EA8BECF181C66B700880B36 /* RESideMenu.h in Headers */ = {isa = PBXBuildFile; fileRef = 1EA8BEC9181C66B700880B36 /* RESideMenu.h */; }; 30 | 1EA8BED0181C66B700880B36 /* RESideMenu.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EA8BECA181C66B700880B36 /* RESideMenu.m */; }; 31 | 1EA8BED1181C66B700880B36 /* UIViewController+RESideMenu.h in Headers */ = {isa = PBXBuildFile; fileRef = 1EA8BECB181C66B700880B36 /* UIViewController+RESideMenu.h */; }; 32 | 1EA8BED2181C66B700880B36 /* UIViewController+RESideMenu.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EA8BECC181C66B700880B36 /* UIViewController+RESideMenu.m */; }; 33 | 1EA8BED5181C689B00880B36 /* DeMarcelpociotSidemenuSideMenuProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 1EA8BED3181C689B00880B36 /* DeMarcelpociotSidemenuSideMenuProxy.h */; }; 34 | 1EA8BED6181C689B00880B36 /* DeMarcelpociotSidemenuSideMenuProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EA8BED4181C689B00880B36 /* DeMarcelpociotSidemenuSideMenuProxy.m */; }; 35 | 1EA8BED9181C68AD00880B36 /* DeMarcelpociotSidemenuSideMenu.h in Headers */ = {isa = PBXBuildFile; fileRef = 1EA8BED7181C68AD00880B36 /* DeMarcelpociotSidemenuSideMenu.h */; }; 36 | 1EA8BEDA181C68AD00880B36 /* DeMarcelpociotSidemenuSideMenu.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EA8BED8181C68AD00880B36 /* DeMarcelpociotSidemenuSideMenu.m */; }; 37 | 1EF4025B19E5E67E00DC7692 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1EF4025A19E5E67E00DC7692 /* QuartzCore.framework */; }; 38 | 1EF4025D19E5E68300DC7692 /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1EF4025C19E5E68300DC7692 /* Accelerate.framework */; }; 39 | 1EF4025F19E5E68800DC7692 /* CoreImage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1EF4025E19E5E68800DC7692 /* CoreImage.framework */; }; 40 | 24DD6CF91134B3F500162E58 /* DeMarcelpociotSidemenuModule.h in Headers */ = {isa = PBXBuildFile; fileRef = 24DD6CF71134B3F500162E58 /* DeMarcelpociotSidemenuModule.h */; }; 41 | 24DD6CFA1134B3F500162E58 /* DeMarcelpociotSidemenuModule.m in Sources */ = {isa = PBXBuildFile; fileRef = 24DD6CF81134B3F500162E58 /* DeMarcelpociotSidemenuModule.m */; }; 42 | 24DE9E1111C5FE74003F90F6 /* DeMarcelpociotSidemenuModuleAssets.h in Headers */ = {isa = PBXBuildFile; fileRef = 24DE9E0F11C5FE74003F90F6 /* DeMarcelpociotSidemenuModuleAssets.h */; }; 43 | 24DE9E1211C5FE74003F90F6 /* DeMarcelpociotSidemenuModuleAssets.m in Sources */ = {isa = PBXBuildFile; fileRef = 24DE9E1011C5FE74003F90F6 /* DeMarcelpociotSidemenuModuleAssets.m */; }; 44 | AA747D9F0F9514B9006C5449 /* DeMarcelpociotSidemenu_Prefix.pch in Headers */ = {isa = PBXBuildFile; fileRef = AA747D9E0F9514B9006C5449 /* DeMarcelpociotSidemenu_Prefix.pch */; }; 45 | AACBBE4A0F95108600F1A2B1 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AACBBE490F95108600F1A2B1 /* Foundation.framework */; }; 46 | /* End PBXBuildFile section */ 47 | 48 | /* Begin PBXContainerItemProxy section */ 49 | 24416B8411C4CA280047AFDD /* PBXContainerItemProxy */ = { 50 | isa = PBXContainerItemProxy; 51 | containerPortal = 0867D690FE84028FC02AAC07 /* Project object */; 52 | proxyType = 1; 53 | remoteGlobalIDString = D2AAC07D0554694100DB518D; 54 | remoteInfo = TiSideMenu; 55 | }; 56 | /* End PBXContainerItemProxy section */ 57 | 58 | /* Begin PBXFileReference section */ 59 | 1E9D41C418283C7F00BFEAE8 /* FXBlurView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FXBlurView.h; sourceTree = ""; }; 60 | 1E9D41C518283C7F00BFEAE8 /* FXBlurView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FXBlurView.m; sourceTree = ""; }; 61 | 1EA8BEC7181C66B700880B36 /* RECommonFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RECommonFunctions.h; sourceTree = ""; }; 62 | 1EA8BEC8181C66B700880B36 /* RECommonFunctions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RECommonFunctions.m; sourceTree = ""; }; 63 | 1EA8BEC9181C66B700880B36 /* RESideMenu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RESideMenu.h; sourceTree = ""; }; 64 | 1EA8BECA181C66B700880B36 /* RESideMenu.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RESideMenu.m; sourceTree = ""; }; 65 | 1EA8BECB181C66B700880B36 /* UIViewController+RESideMenu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIViewController+RESideMenu.h"; sourceTree = ""; }; 66 | 1EA8BECC181C66B700880B36 /* UIViewController+RESideMenu.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIViewController+RESideMenu.m"; sourceTree = ""; }; 67 | 1EA8BED3181C689B00880B36 /* DeMarcelpociotSidemenuSideMenuProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DeMarcelpociotSidemenuSideMenuProxy.h; path = Classes/DeMarcelpociotSidemenuSideMenuProxy.h; sourceTree = ""; }; 68 | 1EA8BED4181C689B00880B36 /* DeMarcelpociotSidemenuSideMenuProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DeMarcelpociotSidemenuSideMenuProxy.m; path = Classes/DeMarcelpociotSidemenuSideMenuProxy.m; sourceTree = ""; }; 69 | 1EA8BED7181C68AD00880B36 /* DeMarcelpociotSidemenuSideMenu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DeMarcelpociotSidemenuSideMenu.h; path = Classes/DeMarcelpociotSidemenuSideMenu.h; sourceTree = ""; }; 70 | 1EA8BED8181C68AD00880B36 /* DeMarcelpociotSidemenuSideMenu.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DeMarcelpociotSidemenuSideMenu.m; path = Classes/DeMarcelpociotSidemenuSideMenu.m; sourceTree = ""; }; 71 | 1EF4025A19E5E67E00DC7692 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; 72 | 1EF4025C19E5E68300DC7692 /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = System/Library/Frameworks/Accelerate.framework; sourceTree = SDKROOT; }; 73 | 1EF4025E19E5E68800DC7692 /* CoreImage.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreImage.framework; path = System/Library/Frameworks/CoreImage.framework; sourceTree = SDKROOT; }; 74 | 24DD6CF71134B3F500162E58 /* DeMarcelpociotSidemenuModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DeMarcelpociotSidemenuModule.h; path = Classes/DeMarcelpociotSidemenuModule.h; sourceTree = ""; }; 75 | 24DD6CF81134B3F500162E58 /* DeMarcelpociotSidemenuModule.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DeMarcelpociotSidemenuModule.m; path = Classes/DeMarcelpociotSidemenuModule.m; sourceTree = ""; }; 76 | 24DD6D1B1134B66800162E58 /* titanium.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = titanium.xcconfig; sourceTree = ""; }; 77 | 24DE9E0F11C5FE74003F90F6 /* DeMarcelpociotSidemenuModuleAssets.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DeMarcelpociotSidemenuModuleAssets.h; path = Classes/DeMarcelpociotSidemenuModuleAssets.h; sourceTree = ""; }; 78 | 24DE9E1011C5FE74003F90F6 /* DeMarcelpociotSidemenuModuleAssets.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DeMarcelpociotSidemenuModuleAssets.m; path = Classes/DeMarcelpociotSidemenuModuleAssets.m; sourceTree = ""; }; 79 | AA747D9E0F9514B9006C5449 /* DeMarcelpociotSidemenu_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DeMarcelpociotSidemenu_Prefix.pch; sourceTree = SOURCE_ROOT; }; 80 | AACBBE490F95108600F1A2B1 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 81 | D2AAC07E0554694100DB518D /* libDeMarcelpociotSidemenu.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libDeMarcelpociotSidemenu.a; sourceTree = BUILT_PRODUCTS_DIR; }; 82 | /* End PBXFileReference section */ 83 | 84 | /* Begin PBXFrameworksBuildPhase section */ 85 | D2AAC07C0554694100DB518D /* Frameworks */ = { 86 | isa = PBXFrameworksBuildPhase; 87 | buildActionMask = 2147483647; 88 | files = ( 89 | 1EF4025F19E5E68800DC7692 /* CoreImage.framework in Frameworks */, 90 | 1EF4025D19E5E68300DC7692 /* Accelerate.framework in Frameworks */, 91 | 1EF4025B19E5E67E00DC7692 /* QuartzCore.framework in Frameworks */, 92 | AACBBE4A0F95108600F1A2B1 /* Foundation.framework in Frameworks */, 93 | ); 94 | runOnlyForDeploymentPostprocessing = 0; 95 | }; 96 | /* End PBXFrameworksBuildPhase section */ 97 | 98 | /* Begin PBXGroup section */ 99 | 034768DFFF38A50411DB9C8B /* Products */ = { 100 | isa = PBXGroup; 101 | children = ( 102 | D2AAC07E0554694100DB518D /* libDeMarcelpociotSidemenu.a */, 103 | ); 104 | name = Products; 105 | sourceTree = ""; 106 | }; 107 | 0867D691FE84028FC02AAC07 /* TiSideMenu */ = { 108 | isa = PBXGroup; 109 | children = ( 110 | 08FB77AEFE84172EC02AAC07 /* Classes */, 111 | 32C88DFF0371C24200C91783 /* Other Sources */, 112 | 0867D69AFE84028FC02AAC07 /* Frameworks */, 113 | 034768DFFF38A50411DB9C8B /* Products */, 114 | ); 115 | name = TiSideMenu; 116 | sourceTree = ""; 117 | }; 118 | 0867D69AFE84028FC02AAC07 /* Frameworks */ = { 119 | isa = PBXGroup; 120 | children = ( 121 | 1EF4025E19E5E68800DC7692 /* CoreImage.framework */, 122 | 1EF4025C19E5E68300DC7692 /* Accelerate.framework */, 123 | 1EF4025A19E5E67E00DC7692 /* QuartzCore.framework */, 124 | AACBBE490F95108600F1A2B1 /* Foundation.framework */, 125 | ); 126 | name = Frameworks; 127 | sourceTree = ""; 128 | }; 129 | 08FB77AEFE84172EC02AAC07 /* Classes */ = { 130 | isa = PBXGroup; 131 | children = ( 132 | 1E9D41C318283C7F00BFEAE8 /* FXBlurView */, 133 | 1EA8BEC6181C66B700880B36 /* RESideMenu */, 134 | 24DE9E0F11C5FE74003F90F6 /* DeMarcelpociotSidemenuModuleAssets.h */, 135 | 24DE9E1011C5FE74003F90F6 /* DeMarcelpociotSidemenuModuleAssets.m */, 136 | 24DD6CF71134B3F500162E58 /* DeMarcelpociotSidemenuModule.h */, 137 | 24DD6CF81134B3F500162E58 /* DeMarcelpociotSidemenuModule.m */, 138 | 1EA8BED3181C689B00880B36 /* DeMarcelpociotSidemenuSideMenuProxy.h */, 139 | 1EA8BED4181C689B00880B36 /* DeMarcelpociotSidemenuSideMenuProxy.m */, 140 | 1EA8BED7181C68AD00880B36 /* DeMarcelpociotSidemenuSideMenu.h */, 141 | 1EA8BED8181C68AD00880B36 /* DeMarcelpociotSidemenuSideMenu.m */, 142 | ); 143 | name = Classes; 144 | sourceTree = ""; 145 | }; 146 | 1E9D41C318283C7F00BFEAE8 /* FXBlurView */ = { 147 | isa = PBXGroup; 148 | children = ( 149 | 1E9D41C418283C7F00BFEAE8 /* FXBlurView.h */, 150 | 1E9D41C518283C7F00BFEAE8 /* FXBlurView.m */, 151 | ); 152 | path = FXBlurView; 153 | sourceTree = ""; 154 | }; 155 | 1EA8BEC6181C66B700880B36 /* RESideMenu */ = { 156 | isa = PBXGroup; 157 | children = ( 158 | 1EA8BEC7181C66B700880B36 /* RECommonFunctions.h */, 159 | 1EA8BEC8181C66B700880B36 /* RECommonFunctions.m */, 160 | 1EA8BEC9181C66B700880B36 /* RESideMenu.h */, 161 | 1EA8BECA181C66B700880B36 /* RESideMenu.m */, 162 | 1EA8BECB181C66B700880B36 /* UIViewController+RESideMenu.h */, 163 | 1EA8BECC181C66B700880B36 /* UIViewController+RESideMenu.m */, 164 | ); 165 | name = RESideMenu; 166 | path = Classes/RESideMenu; 167 | sourceTree = ""; 168 | }; 169 | 32C88DFF0371C24200C91783 /* Other Sources */ = { 170 | isa = PBXGroup; 171 | children = ( 172 | AA747D9E0F9514B9006C5449 /* DeMarcelpociotSidemenu_Prefix.pch */, 173 | 24DD6D1B1134B66800162E58 /* titanium.xcconfig */, 174 | ); 175 | name = "Other Sources"; 176 | sourceTree = ""; 177 | }; 178 | /* End PBXGroup section */ 179 | 180 | /* Begin PBXHeadersBuildPhase section */ 181 | D2AAC07A0554694100DB518D /* Headers */ = { 182 | isa = PBXHeadersBuildPhase; 183 | buildActionMask = 2147483647; 184 | files = ( 185 | 1EA8BED5181C689B00880B36 /* DeMarcelpociotSidemenuSideMenuProxy.h in Headers */, 186 | AA747D9F0F9514B9006C5449 /* DeMarcelpociotSidemenu_Prefix.pch in Headers */, 187 | 1EA8BED9181C68AD00880B36 /* DeMarcelpociotSidemenuSideMenu.h in Headers */, 188 | 24DD6CF91134B3F500162E58 /* DeMarcelpociotSidemenuModule.h in Headers */, 189 | 1EA8BED1181C66B700880B36 /* UIViewController+RESideMenu.h in Headers */, 190 | 1EA8BECD181C66B700880B36 /* RECommonFunctions.h in Headers */, 191 | 1EA8BECF181C66B700880B36 /* RESideMenu.h in Headers */, 192 | 1E9D41C618283C7F00BFEAE8 /* FXBlurView.h in Headers */, 193 | 24DE9E1111C5FE74003F90F6 /* DeMarcelpociotSidemenuModuleAssets.h in Headers */, 194 | ); 195 | runOnlyForDeploymentPostprocessing = 0; 196 | }; 197 | /* End PBXHeadersBuildPhase section */ 198 | 199 | /* Begin PBXNativeTarget section */ 200 | D2AAC07D0554694100DB518D /* TiSideMenu */ = { 201 | isa = PBXNativeTarget; 202 | buildConfigurationList = 1DEB921E08733DC00010E9CD /* Build configuration list for PBXNativeTarget "TiSideMenu" */; 203 | buildPhases = ( 204 | D2AAC07A0554694100DB518D /* Headers */, 205 | D2AAC07B0554694100DB518D /* Sources */, 206 | D2AAC07C0554694100DB518D /* Frameworks */, 207 | ); 208 | buildRules = ( 209 | ); 210 | dependencies = ( 211 | ); 212 | name = TiSideMenu; 213 | productName = TiSideMenu; 214 | productReference = D2AAC07E0554694100DB518D /* libDeMarcelpociotSidemenu.a */; 215 | productType = "com.apple.product-type.library.static"; 216 | }; 217 | /* End PBXNativeTarget section */ 218 | 219 | /* Begin PBXProject section */ 220 | 0867D690FE84028FC02AAC07 /* Project object */ = { 221 | isa = PBXProject; 222 | attributes = { 223 | LastUpgradeCheck = 0600; 224 | }; 225 | buildConfigurationList = 1DEB922208733DC00010E9CD /* Build configuration list for PBXProject "TiSideMenu" */; 226 | compatibilityVersion = "Xcode 3.2"; 227 | developmentRegion = English; 228 | hasScannedForEncodings = 1; 229 | knownRegions = ( 230 | English, 231 | Japanese, 232 | French, 233 | German, 234 | ); 235 | mainGroup = 0867D691FE84028FC02AAC07 /* TiSideMenu */; 236 | productRefGroup = 034768DFFF38A50411DB9C8B /* Products */; 237 | projectDirPath = ""; 238 | projectRoot = ""; 239 | targets = ( 240 | D2AAC07D0554694100DB518D /* TiSideMenu */, 241 | 24416B8111C4CA220047AFDD /* Build & Test */, 242 | ); 243 | }; 244 | /* End PBXProject section */ 245 | 246 | /* Begin PBXShellScriptBuildPhase section */ 247 | 24416B8011C4CA220047AFDD /* ShellScript */ = { 248 | isa = PBXShellScriptBuildPhase; 249 | buildActionMask = 2147483647; 250 | files = ( 251 | ); 252 | inputPaths = ( 253 | ); 254 | outputPaths = ( 255 | ); 256 | runOnlyForDeploymentPostprocessing = 0; 257 | shellPath = /bin/sh; 258 | shellScript = "# shell script goes here\n\npython \"${TITANIUM_SDK}/titanium.py\" run --dir=\"${PROJECT_DIR}\"\nexit $?\n"; 259 | }; 260 | /* End PBXShellScriptBuildPhase section */ 261 | 262 | /* Begin PBXSourcesBuildPhase section */ 263 | D2AAC07B0554694100DB518D /* Sources */ = { 264 | isa = PBXSourcesBuildPhase; 265 | buildActionMask = 2147483647; 266 | files = ( 267 | 1EA8BED0181C66B700880B36 /* RESideMenu.m in Sources */, 268 | 1EA8BEDA181C68AD00880B36 /* DeMarcelpociotSidemenuSideMenu.m in Sources */, 269 | 24DD6CFA1134B3F500162E58 /* DeMarcelpociotSidemenuModule.m in Sources */, 270 | 1EA8BED2181C66B700880B36 /* UIViewController+RESideMenu.m in Sources */, 271 | 1EA8BECE181C66B700880B36 /* RECommonFunctions.m in Sources */, 272 | 1E9D41C718283C7F00BFEAE8 /* FXBlurView.m in Sources */, 273 | 24DE9E1211C5FE74003F90F6 /* DeMarcelpociotSidemenuModuleAssets.m in Sources */, 274 | 1EA8BED6181C689B00880B36 /* DeMarcelpociotSidemenuSideMenuProxy.m in Sources */, 275 | ); 276 | runOnlyForDeploymentPostprocessing = 0; 277 | }; 278 | /* End PBXSourcesBuildPhase section */ 279 | 280 | /* Begin PBXTargetDependency section */ 281 | 24416B8511C4CA280047AFDD /* PBXTargetDependency */ = { 282 | isa = PBXTargetDependency; 283 | target = D2AAC07D0554694100DB518D /* TiSideMenu */; 284 | targetProxy = 24416B8411C4CA280047AFDD /* PBXContainerItemProxy */; 285 | }; 286 | /* End PBXTargetDependency section */ 287 | 288 | /* Begin XCBuildConfiguration section */ 289 | 1DEB921F08733DC00010E9CD /* Debug */ = { 290 | isa = XCBuildConfiguration; 291 | baseConfigurationReference = 24DD6D1B1134B66800162E58 /* titanium.xcconfig */; 292 | buildSettings = { 293 | CLANG_ENABLE_OBJC_ARC = YES; 294 | CODE_SIGN_IDENTITY = "iPhone Developer"; 295 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 296 | DSTROOT = /tmp/DeMarcelpociotSidemenu.dst; 297 | GCC_C_LANGUAGE_STANDARD = c99; 298 | GCC_OPTIMIZATION_LEVEL = 0; 299 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 300 | GCC_PREFIX_HEADER = DeMarcelpociotSidemenu_Prefix.pch; 301 | GCC_PREPROCESSOR_DEFINITIONS = "TI_VERSION=$(TI_VERSION)"; 302 | GCC_TREAT_WARNINGS_AS_ERRORS = NO; 303 | GCC_VERSION = ""; 304 | GCC_WARN_ABOUT_RETURN_TYPE = NO; 305 | GCC_WARN_MISSING_PARENTHESES = NO; 306 | GCC_WARN_SHADOW = NO; 307 | GCC_WARN_STRICT_SELECTOR_MATCH = NO; 308 | GCC_WARN_UNUSED_FUNCTION = YES; 309 | GCC_WARN_UNUSED_PARAMETER = NO; 310 | GCC_WARN_UNUSED_VALUE = NO; 311 | GCC_WARN_UNUSED_VARIABLE = NO; 312 | INSTALL_PATH = /usr/local/lib; 313 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 314 | LIBRARY_SEARCH_PATHS = ""; 315 | OTHER_CFLAGS = ( 316 | "-DDEBUG", 317 | "-DTI_POST_1_2", 318 | ); 319 | OTHER_LDFLAGS = "-ObjC"; 320 | PRODUCT_NAME = DeMarcelpociotSidemenu; 321 | PROVISIONING_PROFILE = ""; 322 | "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; 323 | RUN_CLANG_STATIC_ANALYZER = NO; 324 | SDKROOT = iphoneos; 325 | USER_HEADER_SEARCH_PATHS = ""; 326 | }; 327 | name = Debug; 328 | }; 329 | 1DEB922008733DC00010E9CD /* Release */ = { 330 | isa = XCBuildConfiguration; 331 | baseConfigurationReference = 24DD6D1B1134B66800162E58 /* titanium.xcconfig */; 332 | buildSettings = { 333 | ALWAYS_SEARCH_USER_PATHS = NO; 334 | CLANG_ENABLE_OBJC_ARC = YES; 335 | DSTROOT = /tmp/DeMarcelpociotSidemenu.dst; 336 | GCC_C_LANGUAGE_STANDARD = c99; 337 | GCC_MODEL_TUNING = G5; 338 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 339 | GCC_PREFIX_HEADER = DeMarcelpociotSidemenu_Prefix.pch; 340 | GCC_PREPROCESSOR_DEFINITIONS = "TI_VERSION=$(TI_VERSION)"; 341 | GCC_TREAT_WARNINGS_AS_ERRORS = NO; 342 | GCC_VERSION = ""; 343 | GCC_WARN_ABOUT_RETURN_TYPE = NO; 344 | GCC_WARN_MISSING_PARENTHESES = NO; 345 | GCC_WARN_SHADOW = NO; 346 | GCC_WARN_STRICT_SELECTOR_MATCH = NO; 347 | GCC_WARN_UNUSED_FUNCTION = YES; 348 | GCC_WARN_UNUSED_PARAMETER = NO; 349 | GCC_WARN_UNUSED_VALUE = NO; 350 | GCC_WARN_UNUSED_VARIABLE = NO; 351 | INSTALL_PATH = /usr/local/lib; 352 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 353 | LIBRARY_SEARCH_PATHS = ""; 354 | OTHER_CFLAGS = "-DTI_POST_1_2"; 355 | OTHER_LDFLAGS = "-ObjC"; 356 | PRODUCT_NAME = DeMarcelpociotSidemenu; 357 | RUN_CLANG_STATIC_ANALYZER = NO; 358 | SDKROOT = iphoneos; 359 | USER_HEADER_SEARCH_PATHS = ""; 360 | }; 361 | name = Release; 362 | }; 363 | 1DEB922308733DC00010E9CD /* Debug */ = { 364 | isa = XCBuildConfiguration; 365 | baseConfigurationReference = 24DD6D1B1134B66800162E58 /* titanium.xcconfig */; 366 | buildSettings = { 367 | CODE_SIGN_IDENTITY = "iPhone Developer"; 368 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 369 | DSTROOT = /tmp/DeMarcelpociotSidemenu.dst; 370 | GCC_C_LANGUAGE_STANDARD = c99; 371 | GCC_OPTIMIZATION_LEVEL = 0; 372 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 373 | GCC_PREFIX_HEADER = DeMarcelpociotSidemenu_Prefix.pch; 374 | GCC_PREPROCESSOR_DEFINITIONS = "TI_VERSION=$(TI_VERSION)"; 375 | GCC_TREAT_WARNINGS_AS_ERRORS = NO; 376 | GCC_VERSION = ""; 377 | GCC_WARN_ABOUT_RETURN_TYPE = NO; 378 | GCC_WARN_MISSING_PARENTHESES = NO; 379 | GCC_WARN_SHADOW = NO; 380 | GCC_WARN_STRICT_SELECTOR_MATCH = NO; 381 | GCC_WARN_UNUSED_FUNCTION = YES; 382 | GCC_WARN_UNUSED_PARAMETER = NO; 383 | GCC_WARN_UNUSED_VALUE = NO; 384 | GCC_WARN_UNUSED_VARIABLE = NO; 385 | INSTALL_PATH = /usr/local/lib; 386 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 387 | ONLY_ACTIVE_ARCH = YES; 388 | OTHER_CFLAGS = ( 389 | "-DDEBUG", 390 | "-DTI_POST_1_2", 391 | ); 392 | OTHER_LDFLAGS = "-ObjC"; 393 | PRODUCT_NAME = DeMarcelpociotSidemenu; 394 | PROVISIONING_PROFILE = ""; 395 | "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; 396 | RUN_CLANG_STATIC_ANALYZER = NO; 397 | SDKROOT = iphoneos; 398 | USER_HEADER_SEARCH_PATHS = ""; 399 | }; 400 | name = Debug; 401 | }; 402 | 1DEB922408733DC00010E9CD /* Release */ = { 403 | isa = XCBuildConfiguration; 404 | baseConfigurationReference = 24DD6D1B1134B66800162E58 /* titanium.xcconfig */; 405 | buildSettings = { 406 | ALWAYS_SEARCH_USER_PATHS = NO; 407 | DSTROOT = /tmp/DeMarcelpociotSidemenu.dst; 408 | GCC_C_LANGUAGE_STANDARD = c99; 409 | GCC_MODEL_TUNING = G5; 410 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 411 | GCC_PREFIX_HEADER = DeMarcelpociotSidemenu_Prefix.pch; 412 | GCC_PREPROCESSOR_DEFINITIONS = "TI_VERSION=$(TI_VERSION)"; 413 | GCC_TREAT_WARNINGS_AS_ERRORS = NO; 414 | GCC_VERSION = ""; 415 | GCC_WARN_ABOUT_RETURN_TYPE = NO; 416 | GCC_WARN_MISSING_PARENTHESES = NO; 417 | GCC_WARN_SHADOW = NO; 418 | GCC_WARN_STRICT_SELECTOR_MATCH = NO; 419 | GCC_WARN_UNUSED_FUNCTION = YES; 420 | GCC_WARN_UNUSED_PARAMETER = NO; 421 | GCC_WARN_UNUSED_VALUE = NO; 422 | GCC_WARN_UNUSED_VARIABLE = NO; 423 | INSTALL_PATH = /usr/local/lib; 424 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 425 | OTHER_CFLAGS = "-DTI_POST_1_2"; 426 | OTHER_LDFLAGS = "-ObjC"; 427 | PRODUCT_NAME = DeMarcelpociotSidemenu; 428 | RUN_CLANG_STATIC_ANALYZER = NO; 429 | SDKROOT = iphoneos; 430 | USER_HEADER_SEARCH_PATHS = ""; 431 | }; 432 | name = Release; 433 | }; 434 | 24416B8211C4CA220047AFDD /* Debug */ = { 435 | isa = XCBuildConfiguration; 436 | baseConfigurationReference = 24DD6D1B1134B66800162E58 /* titanium.xcconfig */; 437 | buildSettings = { 438 | COPY_PHASE_STRIP = NO; 439 | GCC_DYNAMIC_NO_PIC = NO; 440 | GCC_OPTIMIZATION_LEVEL = 0; 441 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 442 | PRODUCT_NAME = "Build & test"; 443 | }; 444 | name = Debug; 445 | }; 446 | 24416B8311C4CA220047AFDD /* Release */ = { 447 | isa = XCBuildConfiguration; 448 | baseConfigurationReference = 24DD6D1B1134B66800162E58 /* titanium.xcconfig */; 449 | buildSettings = { 450 | COPY_PHASE_STRIP = YES; 451 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 452 | GCC_ENABLE_FIX_AND_CONTINUE = NO; 453 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 454 | PRODUCT_NAME = "Build & test"; 455 | ZERO_LINK = NO; 456 | }; 457 | name = Release; 458 | }; 459 | /* End XCBuildConfiguration section */ 460 | 461 | /* Begin XCConfigurationList section */ 462 | 1DEB921E08733DC00010E9CD /* Build configuration list for PBXNativeTarget "TiSideMenu" */ = { 463 | isa = XCConfigurationList; 464 | buildConfigurations = ( 465 | 1DEB921F08733DC00010E9CD /* Debug */, 466 | 1DEB922008733DC00010E9CD /* Release */, 467 | ); 468 | defaultConfigurationIsVisible = 0; 469 | defaultConfigurationName = Release; 470 | }; 471 | 1DEB922208733DC00010E9CD /* Build configuration list for PBXProject "TiSideMenu" */ = { 472 | isa = XCConfigurationList; 473 | buildConfigurations = ( 474 | 1DEB922308733DC00010E9CD /* Debug */, 475 | 1DEB922408733DC00010E9CD /* Release */, 476 | ); 477 | defaultConfigurationIsVisible = 0; 478 | defaultConfigurationName = Release; 479 | }; 480 | 24416B8A11C4CA520047AFDD /* Build configuration list for PBXAggregateTarget "Build & Test" */ = { 481 | isa = XCConfigurationList; 482 | buildConfigurations = ( 483 | 24416B8211C4CA220047AFDD /* Debug */, 484 | 24416B8311C4CA220047AFDD /* Release */, 485 | ); 486 | defaultConfigurationIsVisible = 0; 487 | defaultConfigurationName = Release; 488 | }; 489 | /* End XCConfigurationList section */ 490 | }; 491 | rootObject = 0867D690FE84028FC02AAC07 /* Project object */; 492 | } 493 | -------------------------------------------------------------------------------- /TiSideMenu.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /TiSideMenu.xcodeproj/project.xcworkspace/xcshareddata/TiSideMenu.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | 12C60D2F-4D88-46A3-8C62-2FE051DA982F 9 | IDESourceControlProjectName 10 | TiSideMenu 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | 762DA8BD60B7A5B61218D312214DCEA723E36090 14 | github.com:mpociot/TiSideMenu.git 15 | 16 | IDESourceControlProjectPath 17 | TiSideMenu.xcodeproj 18 | IDESourceControlProjectRelativeInstallPathDictionary 19 | 20 | 762DA8BD60B7A5B61218D312214DCEA723E36090 21 | ../.. 22 | 23 | IDESourceControlProjectURL 24 | github.com:mpociot/TiSideMenu.git 25 | IDESourceControlProjectVersion 26 | 111 27 | IDESourceControlProjectWCCIdentifier 28 | 762DA8BD60B7A5B61218D312214DCEA723E36090 29 | IDESourceControlProjectWCConfigurations 30 | 31 | 32 | IDESourceControlRepositoryExtensionIdentifierKey 33 | public.vcs.git 34 | IDESourceControlWCCIdentifierKey 35 | 762DA8BD60B7A5B61218D312214DCEA723E36090 36 | IDESourceControlWCCName 37 | TiSideMenu 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /TiSideMenu.xcodeproj/project.xcworkspace/xcuserdata/marcelpociot.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mpociot/TiSideMenu/fecf854a3565415eea339e07f0fed3e81e83496d/TiSideMenu.xcodeproj/project.xcworkspace/xcuserdata/marcelpociot.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /TiSideMenu.xcodeproj/project.xcworkspace/xcuserdata/marcelpociot.xcuserdatad/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges 6 | 7 | SnapshotAutomaticallyBeforeSignificantChanges 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /TiSideMenu.xcodeproj/xcuserdata/marcelpociot.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /TiSideMenu.xcodeproj/xcuserdata/marcelpociot.xcuserdatad/xcschemes/Build & Test.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 60 | 61 | 63 | 64 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /TiSideMenu.xcodeproj/xcuserdata/marcelpociot.xcuserdatad/xcschemes/TiSideMenu.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 60 | 61 | 63 | 64 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /TiSideMenu.xcodeproj/xcuserdata/marcelpociot.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Build & Test.xcscheme 8 | 9 | orderHint 10 | 1 11 | 12 | TiSideMenu.xcscheme 13 | 14 | orderHint 15 | 0 16 | 17 | 18 | SuppressBuildableAutocreation 19 | 20 | 24416B8111C4CA220047AFDD 21 | 22 | primary 23 | 24 | 25 | D2AAC07D0554694100DB518D 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /assets/README: -------------------------------------------------------------------------------- 1 | Place your assets like PNG files in this directory and they will be packaged with your module. 2 | 3 | If you create a file named de.marcelpociot.sidemenu.js in this directory, it will be 4 | compiled and used as your module. This allows you to run pure Javascript 5 | modules that are pre-compiled. 6 | 7 | -------------------------------------------------------------------------------- /build.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Appcelerator Titanium Module Packager 4 | # 5 | # 6 | import os, subprocess, sys, glob, string 7 | import zipfile 8 | from datetime import date 9 | 10 | cwd = os.path.abspath(os.path.dirname(sys._getframe(0).f_code.co_filename)) 11 | os.chdir(cwd) 12 | required_module_keys = ['name','version','moduleid','description','copyright','license','copyright','platform','minsdk'] 13 | module_defaults = { 14 | 'description':'My module', 15 | 'author': 'Your Name', 16 | 'license' : 'Specify your license', 17 | 'copyright' : 'Copyright (c) %s by Your Company' % str(date.today().year), 18 | } 19 | module_license_default = "TODO: place your license here and we'll include it in the module distribution" 20 | 21 | def find_sdk(config): 22 | sdk = config['TITANIUM_SDK'] 23 | return os.path.expandvars(os.path.expanduser(sdk)) 24 | 25 | def replace_vars(config,token): 26 | idx = token.find('$(') 27 | while idx != -1: 28 | idx2 = token.find(')',idx+2) 29 | if idx2 == -1: break 30 | key = token[idx+2:idx2] 31 | if not config.has_key(key): break 32 | token = token.replace('$(%s)' % key, config[key]) 33 | idx = token.find('$(') 34 | return token 35 | 36 | 37 | def read_ti_xcconfig(): 38 | contents = open(os.path.join(cwd,'titanium.xcconfig')).read() 39 | config = {} 40 | for line in contents.splitlines(False): 41 | line = line.strip() 42 | if line[0:2]=='//': continue 43 | idx = line.find('=') 44 | if idx > 0: 45 | key = line[0:idx].strip() 46 | value = line[idx+1:].strip() 47 | config[key] = replace_vars(config,value) 48 | return config 49 | 50 | def generate_doc(config): 51 | docdir = os.path.join(cwd,'documentation') 52 | if not os.path.exists(docdir): 53 | print "Couldn't find documentation file at: %s" % docdir 54 | return None 55 | 56 | try: 57 | import markdown2 as markdown 58 | except ImportError: 59 | import markdown 60 | documentation = [] 61 | for file in os.listdir(docdir): 62 | if file in ignoreFiles or os.path.isdir(os.path.join(docdir, file)): 63 | continue 64 | md = open(os.path.join(docdir,file)).read() 65 | html = markdown.markdown(md) 66 | documentation.append({file:html}); 67 | return documentation 68 | 69 | def compile_js(manifest,config): 70 | js_file = os.path.join(cwd,'assets','de.marcelpociot.sidemenu.js') 71 | if not os.path.exists(js_file): return 72 | 73 | from compiler import Compiler 74 | try: 75 | import json 76 | except: 77 | import simplejson as json 78 | 79 | compiler = Compiler(cwd, manifest['moduleid'], manifest['name'], 'commonjs') 80 | root_asset, module_assets = compiler.compile_module() 81 | 82 | root_asset_content = """ 83 | %s 84 | 85 | return filterDataInRange([NSData dataWithBytesNoCopy:data length:sizeof(data) freeWhenDone:NO], ranges[0]); 86 | """ % root_asset 87 | 88 | module_asset_content = """ 89 | %s 90 | 91 | NSNumber *index = [map objectForKey:path]; 92 | if (index == nil) { 93 | return nil; 94 | } 95 | return filterDataInRange([NSData dataWithBytesNoCopy:data length:sizeof(data) freeWhenDone:NO], ranges[index.integerValue]); 96 | """ % module_assets 97 | 98 | from tools import splice_code 99 | 100 | assets_router = os.path.join(cwd,'Classes','DeMarcelpociotSidemenuModuleAssets.m') 101 | splice_code(assets_router, 'asset', root_asset_content) 102 | splice_code(assets_router, 'resolve_asset', module_asset_content) 103 | 104 | # Generate the exports after crawling all of the available JS source 105 | exports = open('metadata.json','w') 106 | json.dump({'exports':compiler.exports }, exports) 107 | exports.close() 108 | 109 | def die(msg): 110 | print msg 111 | sys.exit(1) 112 | 113 | def warn(msg): 114 | print "[WARN] %s" % msg 115 | 116 | def validate_license(): 117 | c = open(os.path.join(cwd,'LICENSE')).read() 118 | if c.find(module_license_default)!=-1: 119 | warn('please update the LICENSE file with your license text before distributing') 120 | 121 | def validate_manifest(): 122 | path = os.path.join(cwd,'manifest') 123 | f = open(path) 124 | if not os.path.exists(path): die("missing %s" % path) 125 | manifest = {} 126 | for line in f.readlines(): 127 | line = line.strip() 128 | if line[0:1]=='#': continue 129 | if line.find(':') < 0: continue 130 | key,value = line.split(':') 131 | manifest[key.strip()]=value.strip() 132 | for key in required_module_keys: 133 | if not manifest.has_key(key): die("missing required manifest key '%s'" % key) 134 | if module_defaults.has_key(key): 135 | defvalue = module_defaults[key] 136 | curvalue = manifest[key] 137 | if curvalue==defvalue: warn("please update the manifest key: '%s' to a non-default value" % key) 138 | return manifest,path 139 | 140 | ignoreFiles = ['.DS_Store','.gitignore','libTitanium.a','titanium.jar','README'] 141 | ignoreDirs = ['.DS_Store','.svn','.git','CVSROOT'] 142 | 143 | def zip_dir(zf,dir,basepath,ignoreExt=[]): 144 | if not os.path.exists(dir): return 145 | for root, dirs, files in os.walk(dir): 146 | for name in ignoreDirs: 147 | if name in dirs: 148 | dirs.remove(name) # don't visit ignored directories 149 | for file in files: 150 | if file in ignoreFiles: continue 151 | e = os.path.splitext(file) 152 | if len(e) == 2 and e[1] in ignoreExt: continue 153 | from_ = os.path.join(root, file) 154 | to_ = from_.replace(dir, '%s/%s'%(basepath,dir), 1) 155 | zf.write(from_, to_) 156 | 157 | def glob_libfiles(): 158 | files = [] 159 | for libfile in glob.glob('build/**/*.a'): 160 | if libfile.find('Release-')!=-1: 161 | files.append(libfile) 162 | return files 163 | 164 | def build_module(manifest,config): 165 | from tools import ensure_dev_path 166 | ensure_dev_path() 167 | 168 | rc = os.system("xcodebuild -sdk iphoneos -configuration Release") 169 | if rc != 0: 170 | die("xcodebuild failed") 171 | rc = os.system("xcodebuild -sdk iphonesimulator -configuration Release") 172 | if rc != 0: 173 | die("xcodebuild failed") 174 | # build the merged library using lipo 175 | moduleid = manifest['moduleid'] 176 | libpaths = '' 177 | for libfile in glob_libfiles(): 178 | libpaths+='%s ' % libfile 179 | 180 | os.system("lipo %s -create -output build/lib%s.a" %(libpaths,moduleid)) 181 | 182 | def package_module(manifest,mf,config): 183 | name = manifest['name'].lower() 184 | moduleid = manifest['moduleid'].lower() 185 | version = manifest['version'] 186 | modulezip = '%s-iphone-%s.zip' % (moduleid,version) 187 | if os.path.exists(modulezip): os.remove(modulezip) 188 | zf = zipfile.ZipFile(modulezip, 'w', zipfile.ZIP_DEFLATED) 189 | modulepath = 'modules/iphone/%s/%s' % (moduleid,version) 190 | zf.write(mf,'%s/manifest' % modulepath) 191 | libname = 'lib%s.a' % moduleid 192 | zf.write('build/%s' % libname, '%s/%s' % (modulepath,libname)) 193 | docs = generate_doc(config) 194 | if docs!=None: 195 | for doc in docs: 196 | for file, html in doc.iteritems(): 197 | filename = string.replace(file,'.md','.html') 198 | zf.writestr('%s/documentation/%s'%(modulepath,filename),html) 199 | zip_dir(zf,'assets',modulepath,['.pyc','.js']) 200 | zip_dir(zf,'example',modulepath,['.pyc']) 201 | zip_dir(zf,'platform',modulepath,['.pyc','.js']) 202 | zf.write('LICENSE','%s/LICENSE' % modulepath) 203 | zf.write('module.xcconfig','%s/module.xcconfig' % modulepath) 204 | exports_file = 'metadata.json' 205 | if os.path.exists(exports_file): 206 | zf.write(exports_file, '%s/%s' % (modulepath, exports_file)) 207 | zf.close() 208 | 209 | 210 | if __name__ == '__main__': 211 | manifest,mf = validate_manifest() 212 | validate_license() 213 | config = read_ti_xcconfig() 214 | 215 | sdk = find_sdk(config) 216 | sys.path.insert(0,os.path.join(sdk,'iphone')) 217 | sys.path.append(os.path.join(sdk, "common")) 218 | 219 | compile_js(manifest,config) 220 | build_module(manifest,config) 221 | package_module(manifest,mf,config) 222 | sys.exit(0) 223 | 224 | -------------------------------------------------------------------------------- /dist/de.marcelpociot.sidemenu-iphone-1.0.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mpociot/TiSideMenu/fecf854a3565415eea339e07f0fed3e81e83496d/dist/de.marcelpociot.sidemenu-iphone-1.0.zip -------------------------------------------------------------------------------- /dist/de.marcelpociot.sidemenu-iphone-1.1.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mpociot/TiSideMenu/fecf854a3565415eea339e07f0fed3e81e83496d/dist/de.marcelpociot.sidemenu-iphone-1.1.zip -------------------------------------------------------------------------------- /dist/de.marcelpociot.sidemenu-iphone-1.2.1.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mpociot/TiSideMenu/fecf854a3565415eea339e07f0fed3e81e83496d/dist/de.marcelpociot.sidemenu-iphone-1.2.1.zip -------------------------------------------------------------------------------- /dist/de.marcelpociot.sidemenu-iphone-1.2.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mpociot/TiSideMenu/fecf854a3565415eea339e07f0fed3e81e83496d/dist/de.marcelpociot.sidemenu-iphone-1.2.zip -------------------------------------------------------------------------------- /dist/de.marcelpociot.sidemenu-iphone-2.0.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mpociot/TiSideMenu/fecf854a3565415eea339e07f0fed3e81e83496d/dist/de.marcelpociot.sidemenu-iphone-2.0.zip -------------------------------------------------------------------------------- /dist/de.marcelpociot.sidemenu-iphone-2.1.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mpociot/TiSideMenu/fecf854a3565415eea339e07f0fed3e81e83496d/dist/de.marcelpociot.sidemenu-iphone-2.1.zip -------------------------------------------------------------------------------- /dist/de.marcelpociot.sidemenu-iphone-2.2.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mpociot/TiSideMenu/fecf854a3565415eea339e07f0fed3e81e83496d/dist/de.marcelpociot.sidemenu-iphone-2.2.zip -------------------------------------------------------------------------------- /documentation/index.md: -------------------------------------------------------------------------------- 1 | # TiSideMenu Module 2 | 3 | ## Description 4 | 5 | TODO: Enter your module description here 6 | 7 | ## Accessing the TiSideMenu Module 8 | 9 | To access this module from JavaScript, you would do the following: 10 | 11 | var TiSideMenu = require("de.marcelpociot.sidemenu"); 12 | 13 | The TiSideMenu variable is a reference to the Module object. 14 | 15 | ## Reference 16 | 17 | TODO: If your module has an API, you should document 18 | the reference here. 19 | 20 | ### ___PROJECTNAMEASIDENTIFIER__.function 21 | 22 | TODO: This is an example of a module function. 23 | 24 | ### ___PROJECTNAMEASIDENTIFIER__.property 25 | 26 | TODO: This is an example of a module property. 27 | 28 | ## Usage 29 | 30 | TODO: Enter your usage example here 31 | 32 | ## Author 33 | 34 | TODO: Enter your author name, email and other contact 35 | details you want to share here. 36 | 37 | ## License 38 | 39 | TODO: Enter your license/legal information here. 40 | -------------------------------------------------------------------------------- /example/app.js: -------------------------------------------------------------------------------- 1 | var TiSideMenu = require('de.marcelpociot.sidemenu'); 2 | 3 | 4 | var leftMenuWin = Ti.UI.createWindow({ 5 | backgroundColor:'transparent', 6 | statusBarStyle: Titanium.UI.iPhone.StatusBar.LIGHT_CONTENT 7 | }); 8 | var leftTableView = Ti.UI.createTableView({ 9 | top: 100, 10 | font:{fontSize:12,color: '#ffffff'}, 11 | rowHeight:40, 12 | backgroundColor:'transparent', 13 | data:[ 14 | {title:'Row 1',color: 'white'}, 15 | {title:'Row 2',color: 'white'}, 16 | {title:'Change Center Window',color: 'white'}, 17 | {title:'Push new Window',color: 'white'}, 18 | {title:'Reset Window',color: 'white'} 19 | ] 20 | }); 21 | leftMenuWin.add(leftTableView); 22 | 23 | 24 | var rightMenuWin = Ti.UI.createWindow({ 25 | backgroundColor:'transparent', 26 | statusBarStyle: Titanium.UI.iPhone.StatusBar.LIGHT_CONTENT 27 | }); 28 | var rightTableView = Ti.UI.createTableView({ 29 | top: 100, 30 | font:{fontSize:12,color: '#ffffff'}, 31 | rowHeight:40, 32 | backgroundColor:'transparent', 33 | data:[ 34 | {title:'Row 1',color: 'white'}, 35 | {title:'Row 2',color: 'white'}, 36 | {title:'Change Center Window',color: 'white'}, 37 | {title:'Push new Window',color: 'white'}, 38 | {title:'Reset Window',color: 'white'} 39 | ] 40 | }); 41 | rightMenuWin.add(rightTableView); 42 | 43 | leftTableView.addEventListener("click", function(e){ 44 | switch(e.index){ 45 | case 0: 46 | case 1: 47 | win.hideMenuViewController(); 48 | alert("You clicked " + e.rowData.title + "."); 49 | break; 50 | case 2: 51 | var newWin = Ti.UI.createWindow({ 52 | backgroundColor:'red' 53 | }); 54 | win.setContentWindow({ 55 | window: newWin, 56 | animated: true 57 | }); 58 | win.hideMenuViewController(); 59 | break; 60 | case 3: 61 | var newWin = Ti.UI.createWindow({ 62 | backgroundColor:'red' 63 | }); 64 | contentWindow.openWindow(newWin); 65 | win.hideMenuViewController(); 66 | break; 67 | case 4: 68 | win.setContentWindow( createContentWindow() ); 69 | win.hideMenuViewController(); 70 | break; 71 | } 72 | }); 73 | 74 | function createContentWindow() 75 | { 76 | var contentWin = Ti.UI.createWindow({ 77 | backgroundColor:'transparent', 78 | title:"RE Side Menu", 79 | barColor:"#f7f7f7" 80 | }); 81 | var toggleLeftMenuBtn = Ti.UI.createButton({ 82 | title: 'LEFT' 83 | }); 84 | contentWin.leftNavButton = toggleLeftMenuBtn; 85 | toggleLeftMenuBtn.addEventListener('click',function(e) 86 | { 87 | win.presentLeftMenuViewController(); 88 | }); 89 | 90 | var toggleRightMenuBtn = Ti.UI.createButton({ 91 | title: 'RIGHT' 92 | }); 93 | contentWin.rightNavButton = toggleRightMenuBtn; 94 | toggleRightMenuBtn.addEventListener('click',function(e) 95 | { 96 | win.presentRightMenuViewController(); 97 | }); 98 | 99 | // Module settings 100 | var scaleContentViewLabel = Ti.UI.createLabel({ 101 | text: 'Scale content view:', 102 | top: 50, 103 | left: 10 104 | }); 105 | var scaleContentViewBtn = Ti.UI.createSwitch({ 106 | value: true, 107 | top: 50, 108 | right: 10 109 | }); 110 | contentWin.add( scaleContentViewLabel ); 111 | contentWin.add( scaleContentViewBtn ); 112 | scaleContentViewBtn.addEventListener('change',function(e) 113 | { 114 | win.setScaleContentView( scaleContentViewBtn.value ); 115 | }); 116 | 117 | 118 | var scaleBackgroundImageViewLabel = Ti.UI.createLabel({ 119 | text: 'Scale background image:', 120 | top: 100, 121 | left: 10 122 | }); 123 | var scaleBackgroundImageViewBtn = Ti.UI.createSwitch({ 124 | value: true, 125 | top: 100, 126 | right: 10 127 | }); 128 | contentWin.add( scaleBackgroundImageViewLabel ); 129 | contentWin.add( scaleBackgroundImageViewBtn ); 130 | scaleBackgroundImageViewBtn.addEventListener('change',function(e) 131 | { 132 | win.setScaleBackgroundImageView( scaleBackgroundImageViewBtn.value ); 133 | }); 134 | 135 | var scaleMenuViewLabel = Ti.UI.createLabel({ 136 | text: 'Scale menu view:', 137 | top: 150, 138 | left: 10 139 | }); 140 | var scaleMenuViewBtn = Ti.UI.createSwitch({ 141 | value: true, 142 | top: 150, 143 | right: 10 144 | }); 145 | contentWin.add( scaleMenuViewLabel ); 146 | contentWin.add( scaleMenuViewBtn ); 147 | scaleMenuViewBtn.addEventListener('change',function(e) 148 | { 149 | win.setScaleMenuView( scaleMenuViewBtn.value ); 150 | }); 151 | 152 | var parallaxLabel = Ti.UI.createLabel({ 153 | text: 'Parallax enabled:', 154 | top: 200, 155 | left: 10 156 | }); 157 | var parallaxBtn = Ti.UI.createSwitch({ 158 | value: true, 159 | top: 200, 160 | right: 10 161 | }); 162 | contentWin.add( parallaxLabel ); 163 | contentWin.add( parallaxBtn ); 164 | parallaxBtn.addEventListener('change',function(e) 165 | { 166 | win.setParallaxEnabled( parallaxBtn.value ); 167 | }); 168 | 169 | 170 | var panLabel = Ti.UI.createLabel({ 171 | text: 'Pan gesture enabled:', 172 | top: 250, 173 | left: 10 174 | }); 175 | var panBtn = Ti.UI.createSwitch({ 176 | value: true, 177 | top: 250, 178 | right: 10 179 | }); 180 | contentWin.add( panLabel ); 181 | contentWin.add( panBtn ); 182 | panBtn.addEventListener('change',function(e) 183 | { 184 | win.setPanGestureEnabled( panBtn.value ); 185 | }); 186 | 187 | var scaleLabel = Ti.UI.createLabel({ 188 | text: 'Content View scale:', 189 | top: 300, 190 | left: 10 191 | }); 192 | var scaleSlider = Titanium.UI.createSlider({ 193 | top: 340, 194 | min: 0, 195 | max: 100, 196 | width: '100%', 197 | value: 50 198 | }); 199 | contentWin.add( scaleLabel ); 200 | contentWin.add( scaleSlider ); 201 | scaleSlider.addEventListener('change', function(e) { 202 | win.setContentViewScaleValue( e.value / 100 ); 203 | }); 204 | 205 | 206 | var navController = Ti.UI.iOS.createNavigationWindow({ 207 | statusBarStyle: Titanium.UI.iPhone.StatusBar.LIGHT_CONTENT, 208 | window : contentWin 209 | }); 210 | return navController; 211 | } 212 | var contentWindow = createContentWindow(); 213 | var win = TiSideMenu.createSideMenu({ 214 | contentView: contentWindow, 215 | leftMenuView: leftMenuWin, 216 | rightMenuView: rightMenuWin, 217 | backgroundImage: 'stars.png', 218 | contentViewScaleValue: 0.2, 219 | scaleContentView: true, 220 | panGestureEnabled: true, 221 | panFromEdge: true, 222 | scaleBackgroundImageView: true, 223 | scaleMenuView: true, 224 | parallaxEnabled: true, 225 | // Blur options 226 | blurBackground: false, 227 | tintColor: '#ffffff', 228 | blurRadius: 0, 229 | iterations: 0 230 | }); 231 | 232 | 233 | win.addEventListener("willShowMenuViewController",function() 234 | { 235 | //alert("Will show menu view controller"); 236 | }); 237 | 238 | win.addEventListener("didShowMenuViewController",function() 239 | { 240 | //alert("Did show menu view controller"); 241 | }); 242 | 243 | win.addEventListener("willHideMenuViewController",function() 244 | { 245 | //alert("Will hide menu view controller"); 246 | }); 247 | 248 | win.addEventListener("didHideMenuViewController",function() 249 | { 250 | //alert("Did hide menu view controller"); 251 | }); 252 | 253 | 254 | win.open(); 255 | -------------------------------------------------------------------------------- /example/stars.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mpociot/TiSideMenu/fecf854a3565415eea339e07f0fed3e81e83496d/example/stars.png -------------------------------------------------------------------------------- /hooks/README: -------------------------------------------------------------------------------- 1 | These files are not yet supported as of 1.4.0 but will be in a near future release. 2 | -------------------------------------------------------------------------------- /hooks/add.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # This is the module project add hook that will be 4 | # called when your module is added to a project 5 | # 6 | import os, sys 7 | 8 | def dequote(s): 9 | if s[0:1] == '"': 10 | return s[1:-1] 11 | return s 12 | 13 | def main(args,argc): 14 | # You will get the following command line arguments 15 | # in the following order: 16 | # 17 | # project_dir = the full path to the project root directory 18 | # project_type = the type of project (desktop, mobile, ipad) 19 | # project_name = the name of the project 20 | # 21 | project_dir = dequote(os.path.expanduser(args[1])) 22 | project_type = dequote(args[2]) 23 | project_name = dequote(args[3]) 24 | 25 | # TODO: write your add hook here (optional) 26 | 27 | 28 | # exit 29 | sys.exit(0) 30 | 31 | 32 | 33 | if __name__ == '__main__': 34 | main(sys.argv,len(sys.argv)) 35 | 36 | -------------------------------------------------------------------------------- /hooks/install.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # This is the module install hook that will be 4 | # called when your module is first installed 5 | # 6 | import os, sys 7 | 8 | def main(args,argc): 9 | 10 | # TODO: write your install hook here (optional) 11 | 12 | # exit 13 | sys.exit(0) 14 | 15 | 16 | 17 | if __name__ == '__main__': 18 | main(sys.argv,len(sys.argv)) 19 | 20 | -------------------------------------------------------------------------------- /hooks/remove.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # This is the module project remove hook that will be 4 | # called when your module is remove from a project 5 | # 6 | import os, sys 7 | 8 | def dequote(s): 9 | if s[0:1] == '"': 10 | return s[1:-1] 11 | return s 12 | 13 | def main(args,argc): 14 | # You will get the following command line arguments 15 | # in the following order: 16 | # 17 | # project_dir = the full path to the project root directory 18 | # project_type = the type of project (desktop, mobile, ipad) 19 | # project_name = the name of the project 20 | # 21 | project_dir = dequote(os.path.expanduser(args[1])) 22 | project_type = dequote(args[2]) 23 | project_name = dequote(args[3]) 24 | 25 | # TODO: write your remove hook here (optional) 26 | 27 | # exit 28 | sys.exit(0) 29 | 30 | 31 | 32 | if __name__ == '__main__': 33 | main(sys.argv,len(sys.argv)) 34 | 35 | -------------------------------------------------------------------------------- /hooks/uninstall.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # This is the module uninstall hook that will be 4 | # called when your module is uninstalled 5 | # 6 | import os, sys 7 | 8 | def main(args,argc): 9 | 10 | # TODO: write your uninstall hook here (optional) 11 | 12 | # exit 13 | sys.exit(0) 14 | 15 | 16 | if __name__ == '__main__': 17 | main(sys.argv,len(sys.argv)) 18 | 19 | -------------------------------------------------------------------------------- /manifest: -------------------------------------------------------------------------------- 1 | # 2 | # this is your module manifest and used by Titanium 3 | # during compilation, packaging, distribution, etc. 4 | # 5 | version: 2.2 6 | apiversion: 3 7 | description: My module 8 | author: Marcel Pociot 9 | license: MIT 10 | copyright: Copyright (c) 2013-2014 by Marcel Pociot 11 | 12 | 13 | # these should not be edited 14 | name: TiSideMenu 15 | moduleid: de.marcelpociot.sidemenu 16 | guid: 544290ca-7102-4cf4-8b20-feedb53f2045 17 | platform: iphone 18 | minsdk: 3.4.0.GA 19 | architectures: armv7 arm64 i386 x86_64 20 | -------------------------------------------------------------------------------- /module.xcconfig: -------------------------------------------------------------------------------- 1 | OTHER_LDFLAGS=$(inherited) -framework QuartzCore -framework Accelerate -framework CoreImage -------------------------------------------------------------------------------- /platform/README: -------------------------------------------------------------------------------- 1 | You can place platform-specific files here in sub-folders named "android" and/or "iphone", just as you can with normal Titanium Mobile SDK projects. Any folders and files you place here will be merged with the platform-specific files in a Titanium Mobile project that uses this module. 2 | 3 | When a Titanium Mobile project that uses this module is built, the files from this platform/ folder will be treated the same as files (if any) from the Titanium Mobile project's platform/ folder. 4 | -------------------------------------------------------------------------------- /timodule.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /titanium.xcconfig: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // CHANGE THESE VALUES TO REFLECT THE VERSION (AND LOCATION IF DIFFERENT) 4 | // OF YOUR TITANIUM SDK YOU'RE BUILDING FOR 5 | // 6 | // 7 | TITANIUM_SDK_VERSION = 3.4.0.GA 8 | 9 | 10 | // 11 | // THESE SHOULD BE OK GENERALLY AS-IS 12 | // 13 | TITANIUM_SDK = $HOME/Library/Application Support/Titanium/mobilesdk/osx/$(TITANIUM_SDK_VERSION) 14 | TITANIUM_BASE_SDK = "$(TITANIUM_SDK)/iphone/include" 15 | TITANIUM_BASE_SDK2 = "$(TITANIUM_SDK)/iphone/include/TiCore" 16 | HEADER_SEARCH_PATHS= $(TITANIUM_BASE_SDK) $(TITANIUM_BASE_SDK2) 17 | 18 | 19 | 20 | --------------------------------------------------------------------------------