├── .gitignore ├── AwesomeMenu.podspec ├── AwesomeMenu.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ └── AwesomeMenu.xccheckout │ └── xcuserdata │ │ ├── Arjun.xcuserdatad │ │ ├── UserInterfaceState.xcuserstate │ │ └── WorkspaceSettings.xcsettings │ │ └── Levey.xcuserdatad │ │ ├── UserInterfaceState.xcuserstate │ │ └── WorkspaceSettings.xcsettings └── xcuserdata │ ├── Arjun.xcuserdatad │ └── xcschemes │ │ ├── AwesomeMenu.xcscheme │ │ └── xcschememanagement.plist │ └── Levey.xcuserdatad │ ├── xcdebugger │ └── Breakpoints.xcbkptlist │ └── xcschemes │ ├── AwesomeMenu.xcscheme │ └── xcschememanagement.plist ├── AwesomeMenu ├── AppDelegate.h ├── AppDelegate.m ├── AwesomeMenu-Info.plist ├── AwesomeMenu-Prefix.pch ├── AwesomeMenu │ ├── AwesomeMenu.h │ ├── AwesomeMenu.m │ ├── AwesomeMenuItem.h │ └── AwesomeMenuItem.m ├── Images │ ├── bg-addbutton-highlighted.png │ ├── bg-addbutton-highlighted@2x.png │ ├── bg-addbutton.png │ ├── bg-addbutton@2x.png │ ├── bg-menuitem-highlighted.png │ ├── bg-menuitem-highlighted@2x.png │ ├── bg-menuitem.png │ ├── bg-menuitem@2x.png │ ├── icon-plus-highlighted.png │ ├── icon-plus-highlighted@2x.png │ ├── icon-plus.png │ ├── icon-plus@2x.png │ ├── icon-star.png │ └── icon-star@2x.png ├── en.lproj │ └── InfoPlist.strings └── main.m ├── Default-568h@2x.png ├── LICENSE.txt └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.xcuserdatad -------------------------------------------------------------------------------- /AwesomeMenu.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |spec| 2 | spec.name = 'AwesomeMenu' 3 | spec.version = '2.0.0' 4 | spec.license = 'MIT' 5 | spec.summary = 'Path 2.0 menu using CoreAnimation' 6 | spec.homepage = 'https://github.com/levey/AwesomeMenu' 7 | spec.author = 'Levey Zhu' 8 | spec.source = { :git => 'git@github.com:levey/AwesomeMenu.git', :tag => '2.0.0'} 9 | spec.source_files = '/AwesomeMenu/AwesomeMenu/*' 10 | spec.requires_arc = true 11 | end 12 | -------------------------------------------------------------------------------- /AwesomeMenu.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 5C03649D1488A5D4000CE00F /* bg-addbutton-highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = 5C03648A1488A5D4000CE00F /* bg-addbutton-highlighted.png */; }; 11 | 5C03649E1488A5D4000CE00F /* bg-addbutton-highlighted@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 5C03648B1488A5D4000CE00F /* bg-addbutton-highlighted@2x.png */; }; 12 | 5C03649F1488A5D4000CE00F /* bg-addbutton.png in Resources */ = {isa = PBXBuildFile; fileRef = 5C03648C1488A5D4000CE00F /* bg-addbutton.png */; }; 13 | 5C0364A01488A5D4000CE00F /* bg-addbutton@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 5C03648D1488A5D4000CE00F /* bg-addbutton@2x.png */; }; 14 | 5C0364A11488A5D4000CE00F /* bg-menuitem-highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = 5C03648E1488A5D4000CE00F /* bg-menuitem-highlighted.png */; }; 15 | 5C0364A21488A5D4000CE00F /* bg-menuitem-highlighted@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 5C03648F1488A5D4000CE00F /* bg-menuitem-highlighted@2x.png */; }; 16 | 5C0364A31488A5D4000CE00F /* bg-menuitem.png in Resources */ = {isa = PBXBuildFile; fileRef = 5C0364901488A5D4000CE00F /* bg-menuitem.png */; }; 17 | 5C0364A41488A5D4000CE00F /* bg-menuitem@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 5C0364911488A5D4000CE00F /* bg-menuitem@2x.png */; }; 18 | 5C0364A51488A5D4000CE00F /* icon-plus-highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = 5C0364921488A5D4000CE00F /* icon-plus-highlighted.png */; }; 19 | 5C0364A61488A5D4000CE00F /* icon-plus-highlighted@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 5C0364931488A5D4000CE00F /* icon-plus-highlighted@2x.png */; }; 20 | 5C0364A71488A5D4000CE00F /* icon-plus.png in Resources */ = {isa = PBXBuildFile; fileRef = 5C0364941488A5D4000CE00F /* icon-plus.png */; }; 21 | 5C0364A81488A5D4000CE00F /* icon-plus@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 5C0364951488A5D4000CE00F /* icon-plus@2x.png */; }; 22 | 5C0364A91488A5D4000CE00F /* icon-star.png in Resources */ = {isa = PBXBuildFile; fileRef = 5C0364961488A5D4000CE00F /* icon-star.png */; }; 23 | 5C0364AA1488A5D4000CE00F /* icon-star@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 5C0364971488A5D4000CE00F /* icon-star@2x.png */; }; 24 | 5C3FF3641486564E0098EE93 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C3FF3631486564E0098EE93 /* UIKit.framework */; }; 25 | 5C3FF3661486564E0098EE93 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C3FF3651486564E0098EE93 /* Foundation.framework */; }; 26 | 5C3FF3681486564E0098EE93 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C3FF3671486564E0098EE93 /* CoreGraphics.framework */; }; 27 | 5C3FF36E1486564E0098EE93 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 5C3FF36C1486564E0098EE93 /* InfoPlist.strings */; }; 28 | 5C3FF3701486564E0098EE93 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C3FF36F1486564E0098EE93 /* main.m */; }; 29 | 5C3FF3741486564E0098EE93 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C3FF3731486564E0098EE93 /* AppDelegate.m */; }; 30 | 5C5949CA153ACC510023B034 /* AwesomeMenu.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C5949C7153ACC510023B034 /* AwesomeMenu.m */; }; 31 | 5C5949CB153ACC510023B034 /* AwesomeMenuItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C5949C9153ACC510023B034 /* AwesomeMenuItem.m */; }; 32 | 5C93DC61148673F2003029CA /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C93DC60148673F2003029CA /* QuartzCore.framework */; }; 33 | DCDD5EA716E5B2A1005D7B61 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DCDD5EA616E5B2A1005D7B61 /* Default-568h@2x.png */; }; 34 | /* End PBXBuildFile section */ 35 | 36 | /* Begin PBXFileReference section */ 37 | 5C03648A1488A5D4000CE00F /* bg-addbutton-highlighted.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "bg-addbutton-highlighted.png"; sourceTree = ""; }; 38 | 5C03648B1488A5D4000CE00F /* bg-addbutton-highlighted@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "bg-addbutton-highlighted@2x.png"; sourceTree = ""; }; 39 | 5C03648C1488A5D4000CE00F /* bg-addbutton.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "bg-addbutton.png"; sourceTree = ""; }; 40 | 5C03648D1488A5D4000CE00F /* bg-addbutton@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "bg-addbutton@2x.png"; sourceTree = ""; }; 41 | 5C03648E1488A5D4000CE00F /* bg-menuitem-highlighted.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "bg-menuitem-highlighted.png"; sourceTree = ""; }; 42 | 5C03648F1488A5D4000CE00F /* bg-menuitem-highlighted@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "bg-menuitem-highlighted@2x.png"; sourceTree = ""; }; 43 | 5C0364901488A5D4000CE00F /* bg-menuitem.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "bg-menuitem.png"; sourceTree = ""; }; 44 | 5C0364911488A5D4000CE00F /* bg-menuitem@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "bg-menuitem@2x.png"; sourceTree = ""; }; 45 | 5C0364921488A5D4000CE00F /* icon-plus-highlighted.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-plus-highlighted.png"; sourceTree = ""; }; 46 | 5C0364931488A5D4000CE00F /* icon-plus-highlighted@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-plus-highlighted@2x.png"; sourceTree = ""; }; 47 | 5C0364941488A5D4000CE00F /* icon-plus.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-plus.png"; sourceTree = ""; }; 48 | 5C0364951488A5D4000CE00F /* icon-plus@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-plus@2x.png"; sourceTree = ""; }; 49 | 5C0364961488A5D4000CE00F /* icon-star.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-star.png"; sourceTree = ""; }; 50 | 5C0364971488A5D4000CE00F /* icon-star@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-star@2x.png"; sourceTree = ""; }; 51 | 5C3FF35F1486564E0098EE93 /* AwesomeMenu.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AwesomeMenu.app; sourceTree = BUILT_PRODUCTS_DIR; }; 52 | 5C3FF3631486564E0098EE93 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 53 | 5C3FF3651486564E0098EE93 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 54 | 5C3FF3671486564E0098EE93 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 55 | 5C3FF36B1486564E0098EE93 /* AwesomeMenu-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "AwesomeMenu-Info.plist"; sourceTree = ""; }; 56 | 5C3FF36D1486564E0098EE93 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 57 | 5C3FF36F1486564E0098EE93 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 58 | 5C3FF3711486564E0098EE93 /* AwesomeMenu-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "AwesomeMenu-Prefix.pch"; sourceTree = ""; }; 59 | 5C3FF3721486564E0098EE93 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 60 | 5C3FF3731486564E0098EE93 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 61 | 5C5949C6153ACC510023B034 /* AwesomeMenu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AwesomeMenu.h; sourceTree = ""; }; 62 | 5C5949C7153ACC510023B034 /* AwesomeMenu.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AwesomeMenu.m; sourceTree = ""; }; 63 | 5C5949C8153ACC510023B034 /* AwesomeMenuItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AwesomeMenuItem.h; sourceTree = ""; }; 64 | 5C5949C9153ACC510023B034 /* AwesomeMenuItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AwesomeMenuItem.m; sourceTree = ""; }; 65 | 5C93DC60148673F2003029CA /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; 66 | DCDD5EA616E5B2A1005D7B61 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; }; 67 | /* End PBXFileReference section */ 68 | 69 | /* Begin PBXFrameworksBuildPhase section */ 70 | 5C3FF35C1486564E0098EE93 /* Frameworks */ = { 71 | isa = PBXFrameworksBuildPhase; 72 | buildActionMask = 2147483647; 73 | files = ( 74 | 5C93DC61148673F2003029CA /* QuartzCore.framework in Frameworks */, 75 | 5C3FF3641486564E0098EE93 /* UIKit.framework in Frameworks */, 76 | 5C3FF3661486564E0098EE93 /* Foundation.framework in Frameworks */, 77 | 5C3FF3681486564E0098EE93 /* CoreGraphics.framework in Frameworks */, 78 | ); 79 | runOnlyForDeploymentPostprocessing = 0; 80 | }; 81 | /* End PBXFrameworksBuildPhase section */ 82 | 83 | /* Begin PBXGroup section */ 84 | 5C0364891488A5D4000CE00F /* Images */ = { 85 | isa = PBXGroup; 86 | children = ( 87 | 5C03648A1488A5D4000CE00F /* bg-addbutton-highlighted.png */, 88 | 5C03648B1488A5D4000CE00F /* bg-addbutton-highlighted@2x.png */, 89 | 5C03648C1488A5D4000CE00F /* bg-addbutton.png */, 90 | 5C03648D1488A5D4000CE00F /* bg-addbutton@2x.png */, 91 | 5C03648E1488A5D4000CE00F /* bg-menuitem-highlighted.png */, 92 | 5C03648F1488A5D4000CE00F /* bg-menuitem-highlighted@2x.png */, 93 | 5C0364901488A5D4000CE00F /* bg-menuitem.png */, 94 | 5C0364911488A5D4000CE00F /* bg-menuitem@2x.png */, 95 | 5C0364921488A5D4000CE00F /* icon-plus-highlighted.png */, 96 | 5C0364931488A5D4000CE00F /* icon-plus-highlighted@2x.png */, 97 | 5C0364941488A5D4000CE00F /* icon-plus.png */, 98 | 5C0364951488A5D4000CE00F /* icon-plus@2x.png */, 99 | 5C0364961488A5D4000CE00F /* icon-star.png */, 100 | 5C0364971488A5D4000CE00F /* icon-star@2x.png */, 101 | ); 102 | path = Images; 103 | sourceTree = ""; 104 | }; 105 | 5C3FF3541486564E0098EE93 = { 106 | isa = PBXGroup; 107 | children = ( 108 | DCDD5EA616E5B2A1005D7B61 /* Default-568h@2x.png */, 109 | 5C3FF3691486564E0098EE93 /* AwesomeMenu */, 110 | 5C3FF3621486564E0098EE93 /* Frameworks */, 111 | 5C3FF3601486564E0098EE93 /* Products */, 112 | ); 113 | sourceTree = ""; 114 | }; 115 | 5C3FF3601486564E0098EE93 /* Products */ = { 116 | isa = PBXGroup; 117 | children = ( 118 | 5C3FF35F1486564E0098EE93 /* AwesomeMenu.app */, 119 | ); 120 | name = Products; 121 | sourceTree = ""; 122 | }; 123 | 5C3FF3621486564E0098EE93 /* Frameworks */ = { 124 | isa = PBXGroup; 125 | children = ( 126 | 5C93DC60148673F2003029CA /* QuartzCore.framework */, 127 | 5C3FF3631486564E0098EE93 /* UIKit.framework */, 128 | 5C3FF3651486564E0098EE93 /* Foundation.framework */, 129 | 5C3FF3671486564E0098EE93 /* CoreGraphics.framework */, 130 | ); 131 | name = Frameworks; 132 | sourceTree = ""; 133 | }; 134 | 5C3FF3691486564E0098EE93 /* AwesomeMenu */ = { 135 | isa = PBXGroup; 136 | children = ( 137 | 5C0364891488A5D4000CE00F /* Images */, 138 | 5C5949C5153ACC510023B034 /* AwesomeMenu */, 139 | 5C3FF3721486564E0098EE93 /* AppDelegate.h */, 140 | 5C3FF3731486564E0098EE93 /* AppDelegate.m */, 141 | 5C3FF36A1486564E0098EE93 /* Supporting Files */, 142 | ); 143 | path = AwesomeMenu; 144 | sourceTree = ""; 145 | }; 146 | 5C3FF36A1486564E0098EE93 /* Supporting Files */ = { 147 | isa = PBXGroup; 148 | children = ( 149 | 5C3FF36B1486564E0098EE93 /* AwesomeMenu-Info.plist */, 150 | 5C3FF36C1486564E0098EE93 /* InfoPlist.strings */, 151 | 5C3FF36F1486564E0098EE93 /* main.m */, 152 | 5C3FF3711486564E0098EE93 /* AwesomeMenu-Prefix.pch */, 153 | ); 154 | name = "Supporting Files"; 155 | sourceTree = ""; 156 | }; 157 | 5C5949C5153ACC510023B034 /* AwesomeMenu */ = { 158 | isa = PBXGroup; 159 | children = ( 160 | 5C5949C6153ACC510023B034 /* AwesomeMenu.h */, 161 | 5C5949C7153ACC510023B034 /* AwesomeMenu.m */, 162 | 5C5949C8153ACC510023B034 /* AwesomeMenuItem.h */, 163 | 5C5949C9153ACC510023B034 /* AwesomeMenuItem.m */, 164 | ); 165 | path = AwesomeMenu; 166 | sourceTree = ""; 167 | }; 168 | /* End PBXGroup section */ 169 | 170 | /* Begin PBXNativeTarget section */ 171 | 5C3FF35E1486564E0098EE93 /* AwesomeMenu */ = { 172 | isa = PBXNativeTarget; 173 | buildConfigurationList = 5C3FF3771486564E0098EE93 /* Build configuration list for PBXNativeTarget "AwesomeMenu" */; 174 | buildPhases = ( 175 | 5C3FF35B1486564E0098EE93 /* Sources */, 176 | 5C3FF35C1486564E0098EE93 /* Frameworks */, 177 | 5C3FF35D1486564E0098EE93 /* Resources */, 178 | ); 179 | buildRules = ( 180 | ); 181 | dependencies = ( 182 | ); 183 | name = AwesomeMenu; 184 | productName = AwesomeMenu; 185 | productReference = 5C3FF35F1486564E0098EE93 /* AwesomeMenu.app */; 186 | productType = "com.apple.product-type.application"; 187 | }; 188 | /* End PBXNativeTarget section */ 189 | 190 | /* Begin PBXProject section */ 191 | 5C3FF3561486564E0098EE93 /* Project object */ = { 192 | isa = PBXProject; 193 | attributes = { 194 | LastUpgradeCheck = 0460; 195 | }; 196 | buildConfigurationList = 5C3FF3591486564E0098EE93 /* Build configuration list for PBXProject "AwesomeMenu" */; 197 | compatibilityVersion = "Xcode 3.2"; 198 | developmentRegion = English; 199 | hasScannedForEncodings = 0; 200 | knownRegions = ( 201 | en, 202 | ); 203 | mainGroup = 5C3FF3541486564E0098EE93; 204 | productRefGroup = 5C3FF3601486564E0098EE93 /* Products */; 205 | projectDirPath = ""; 206 | projectRoot = ""; 207 | targets = ( 208 | 5C3FF35E1486564E0098EE93 /* AwesomeMenu */, 209 | ); 210 | }; 211 | /* End PBXProject section */ 212 | 213 | /* Begin PBXResourcesBuildPhase section */ 214 | 5C3FF35D1486564E0098EE93 /* Resources */ = { 215 | isa = PBXResourcesBuildPhase; 216 | buildActionMask = 2147483647; 217 | files = ( 218 | 5C3FF36E1486564E0098EE93 /* InfoPlist.strings in Resources */, 219 | 5C03649D1488A5D4000CE00F /* bg-addbutton-highlighted.png in Resources */, 220 | 5C03649E1488A5D4000CE00F /* bg-addbutton-highlighted@2x.png in Resources */, 221 | 5C03649F1488A5D4000CE00F /* bg-addbutton.png in Resources */, 222 | 5C0364A01488A5D4000CE00F /* bg-addbutton@2x.png in Resources */, 223 | 5C0364A11488A5D4000CE00F /* bg-menuitem-highlighted.png in Resources */, 224 | 5C0364A21488A5D4000CE00F /* bg-menuitem-highlighted@2x.png in Resources */, 225 | 5C0364A31488A5D4000CE00F /* bg-menuitem.png in Resources */, 226 | 5C0364A41488A5D4000CE00F /* bg-menuitem@2x.png in Resources */, 227 | 5C0364A51488A5D4000CE00F /* icon-plus-highlighted.png in Resources */, 228 | 5C0364A61488A5D4000CE00F /* icon-plus-highlighted@2x.png in Resources */, 229 | 5C0364A71488A5D4000CE00F /* icon-plus.png in Resources */, 230 | 5C0364A81488A5D4000CE00F /* icon-plus@2x.png in Resources */, 231 | 5C0364A91488A5D4000CE00F /* icon-star.png in Resources */, 232 | 5C0364AA1488A5D4000CE00F /* icon-star@2x.png in Resources */, 233 | DCDD5EA716E5B2A1005D7B61 /* Default-568h@2x.png in Resources */, 234 | ); 235 | runOnlyForDeploymentPostprocessing = 0; 236 | }; 237 | /* End PBXResourcesBuildPhase section */ 238 | 239 | /* Begin PBXSourcesBuildPhase section */ 240 | 5C3FF35B1486564E0098EE93 /* Sources */ = { 241 | isa = PBXSourcesBuildPhase; 242 | buildActionMask = 2147483647; 243 | files = ( 244 | 5C3FF3701486564E0098EE93 /* main.m in Sources */, 245 | 5C3FF3741486564E0098EE93 /* AppDelegate.m in Sources */, 246 | 5C5949CA153ACC510023B034 /* AwesomeMenu.m in Sources */, 247 | 5C5949CB153ACC510023B034 /* AwesomeMenuItem.m in Sources */, 248 | ); 249 | runOnlyForDeploymentPostprocessing = 0; 250 | }; 251 | /* End PBXSourcesBuildPhase section */ 252 | 253 | /* Begin PBXVariantGroup section */ 254 | 5C3FF36C1486564E0098EE93 /* InfoPlist.strings */ = { 255 | isa = PBXVariantGroup; 256 | children = ( 257 | 5C3FF36D1486564E0098EE93 /* en */, 258 | ); 259 | name = InfoPlist.strings; 260 | sourceTree = ""; 261 | }; 262 | /* End PBXVariantGroup section */ 263 | 264 | /* Begin XCBuildConfiguration section */ 265 | 5C3FF3751486564E0098EE93 /* Debug */ = { 266 | isa = XCBuildConfiguration; 267 | buildSettings = { 268 | ALWAYS_SEARCH_USER_PATHS = NO; 269 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 270 | CLANG_ENABLE_OBJC_ARC = YES; 271 | CLANG_WARN_CONSTANT_CONVERSION = YES; 272 | CLANG_WARN_ENUM_CONVERSION = YES; 273 | CLANG_WARN_INT_CONVERSION = YES; 274 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 275 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 276 | COPY_PHASE_STRIP = NO; 277 | GCC_C_LANGUAGE_STANDARD = gnu99; 278 | GCC_DYNAMIC_NO_PIC = NO; 279 | GCC_OPTIMIZATION_LEVEL = 0; 280 | GCC_PREPROCESSOR_DEFINITIONS = ( 281 | "DEBUG=1", 282 | "$(inherited)", 283 | ); 284 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 285 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 286 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; 287 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 288 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 289 | GCC_WARN_UNUSED_VARIABLE = YES; 290 | IPHONEOS_DEPLOYMENT_TARGET = 5.0; 291 | SDKROOT = iphoneos; 292 | }; 293 | name = Debug; 294 | }; 295 | 5C3FF3761486564E0098EE93 /* Release */ = { 296 | isa = XCBuildConfiguration; 297 | buildSettings = { 298 | ALWAYS_SEARCH_USER_PATHS = NO; 299 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 300 | CLANG_ENABLE_OBJC_ARC = YES; 301 | CLANG_WARN_CONSTANT_CONVERSION = YES; 302 | CLANG_WARN_ENUM_CONVERSION = YES; 303 | CLANG_WARN_INT_CONVERSION = YES; 304 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 305 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 306 | COPY_PHASE_STRIP = YES; 307 | GCC_C_LANGUAGE_STANDARD = gnu99; 308 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 309 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; 310 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 311 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 312 | GCC_WARN_UNUSED_VARIABLE = YES; 313 | IPHONEOS_DEPLOYMENT_TARGET = 5.0; 314 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; 315 | SDKROOT = iphoneos; 316 | VALIDATE_PRODUCT = YES; 317 | }; 318 | name = Release; 319 | }; 320 | 5C3FF3781486564E0098EE93 /* Debug */ = { 321 | isa = XCBuildConfiguration; 322 | buildSettings = { 323 | CLANG_ENABLE_OBJC_ARC = YES; 324 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 325 | GCC_PREFIX_HEADER = "AwesomeMenu/AwesomeMenu-Prefix.pch"; 326 | INFOPLIST_FILE = "AwesomeMenu/AwesomeMenu-Info.plist"; 327 | IPHONEOS_DEPLOYMENT_TARGET = 6.0; 328 | PRODUCT_NAME = "$(TARGET_NAME)"; 329 | RUN_CLANG_STATIC_ANALYZER = YES; 330 | WARNING_CFLAGS = "-Wall"; 331 | WRAPPER_EXTENSION = app; 332 | }; 333 | name = Debug; 334 | }; 335 | 5C3FF3791486564E0098EE93 /* Release */ = { 336 | isa = XCBuildConfiguration; 337 | buildSettings = { 338 | CLANG_ENABLE_OBJC_ARC = YES; 339 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 340 | GCC_PREFIX_HEADER = "AwesomeMenu/AwesomeMenu-Prefix.pch"; 341 | INFOPLIST_FILE = "AwesomeMenu/AwesomeMenu-Info.plist"; 342 | IPHONEOS_DEPLOYMENT_TARGET = 6.0; 343 | PRODUCT_NAME = "$(TARGET_NAME)"; 344 | RUN_CLANG_STATIC_ANALYZER = YES; 345 | WARNING_CFLAGS = "-Wall"; 346 | WRAPPER_EXTENSION = app; 347 | }; 348 | name = Release; 349 | }; 350 | /* End XCBuildConfiguration section */ 351 | 352 | /* Begin XCConfigurationList section */ 353 | 5C3FF3591486564E0098EE93 /* Build configuration list for PBXProject "AwesomeMenu" */ = { 354 | isa = XCConfigurationList; 355 | buildConfigurations = ( 356 | 5C3FF3751486564E0098EE93 /* Debug */, 357 | 5C3FF3761486564E0098EE93 /* Release */, 358 | ); 359 | defaultConfigurationIsVisible = 0; 360 | defaultConfigurationName = Release; 361 | }; 362 | 5C3FF3771486564E0098EE93 /* Build configuration list for PBXNativeTarget "AwesomeMenu" */ = { 363 | isa = XCConfigurationList; 364 | buildConfigurations = ( 365 | 5C3FF3781486564E0098EE93 /* Debug */, 366 | 5C3FF3791486564E0098EE93 /* Release */, 367 | ); 368 | defaultConfigurationIsVisible = 0; 369 | defaultConfigurationName = Release; 370 | }; 371 | /* End XCConfigurationList section */ 372 | }; 373 | rootObject = 5C3FF3561486564E0098EE93 /* Project object */; 374 | } 375 | -------------------------------------------------------------------------------- /AwesomeMenu.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /AwesomeMenu.xcodeproj/project.xcworkspace/xcshareddata/AwesomeMenu.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | 4F845190-413F-4A06-BB74-B670E9EF4657 9 | IDESourceControlProjectName 10 | AwesomeMenu 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | 08DC04EC29A9EEEB651F68DD1636988CA003BDC9 14 | github.com:levey/AwesomeMenu.git 15 | 16 | IDESourceControlProjectPath 17 | AwesomeMenu.xcodeproj 18 | IDESourceControlProjectRelativeInstallPathDictionary 19 | 20 | 08DC04EC29A9EEEB651F68DD1636988CA003BDC9 21 | ../.. 22 | 23 | IDESourceControlProjectURL 24 | github.com:levey/AwesomeMenu.git 25 | IDESourceControlProjectVersion 26 | 111 27 | IDESourceControlProjectWCCIdentifier 28 | 08DC04EC29A9EEEB651F68DD1636988CA003BDC9 29 | IDESourceControlProjectWCConfigurations 30 | 31 | 32 | IDESourceControlRepositoryExtensionIdentifierKey 33 | public.vcs.git 34 | IDESourceControlWCCIdentifierKey 35 | 08DC04EC29A9EEEB651F68DD1636988CA003BDC9 36 | IDESourceControlWCCName 37 | AwesomeMenu 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /AwesomeMenu.xcodeproj/project.xcworkspace/xcuserdata/Arjun.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levey/AwesomeMenu/f52b91cea704562d10f3f453da4b74104696ab46/AwesomeMenu.xcodeproj/project.xcworkspace/xcuserdata/Arjun.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /AwesomeMenu.xcodeproj/project.xcworkspace/xcuserdata/Arjun.xcuserdatad/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildLocationStyle 6 | UseAppPreferences 7 | CustomBuildLocationType 8 | RelativeToDerivedData 9 | DerivedDataLocationStyle 10 | Default 11 | HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges 12 | 13 | IssueFilterStyle 14 | ShowActiveSchemeOnly 15 | LiveSourceIssuesEnabled 16 | 17 | SnapshotAutomaticallyBeforeSignificantChanges 18 | 19 | SnapshotLocationStyle 20 | Default 21 | 22 | 23 | -------------------------------------------------------------------------------- /AwesomeMenu.xcodeproj/project.xcworkspace/xcuserdata/Levey.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levey/AwesomeMenu/f52b91cea704562d10f3f453da4b74104696ab46/AwesomeMenu.xcodeproj/project.xcworkspace/xcuserdata/Levey.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /AwesomeMenu.xcodeproj/project.xcworkspace/xcuserdata/Levey.xcuserdatad/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEWorkspaceUserSettings_HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges 6 | 7 | IDEWorkspaceUserSettings_SnapshotAutomaticallyBeforeSignificantChanges 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /AwesomeMenu.xcodeproj/xcuserdata/Arjun.xcuserdatad/xcschemes/AwesomeMenu.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 51 | 52 | 58 | 59 | 60 | 61 | 62 | 63 | 69 | 70 | 76 | 77 | 78 | 79 | 81 | 82 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /AwesomeMenu.xcodeproj/xcuserdata/Arjun.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | AwesomeMenu.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 5C3FF35E1486564E0098EE93 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /AwesomeMenu.xcodeproj/xcuserdata/Levey.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /AwesomeMenu.xcodeproj/xcuserdata/Levey.xcuserdatad/xcschemes/AwesomeMenu.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | 14 | 20 | 21 | 22 | 23 | 24 | 29 | 30 | 31 | 32 | 38 | 39 | 40 | 41 | 50 | 52 | 58 | 59 | 60 | 61 | 62 | 63 | 69 | 71 | 77 | 78 | 79 | 80 | 82 | 83 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /AwesomeMenu.xcodeproj/xcuserdata/Levey.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | AwesomeMenu.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 5C3FF35E1486564E0098EE93 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /AwesomeMenu/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // AwesomeMenu 4 | // 5 | // Created by Levey on 11/30/11. 6 | // Copyright (c) 2011 Levey & Other Contributors. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AwesomeMenu.h" 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /AwesomeMenu/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // AwesomeMenu 4 | // 5 | // Created by Levey on 11/30/11. 6 | // Copyright (c) 2011 Levey & Other Contributors. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @implementation AppDelegate 12 | 13 | @synthesize window = _window; 14 | 15 | 16 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 17 | { 18 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 19 | self.window.backgroundColor = [UIColor whiteColor]; 20 | 21 | UIImage *storyMenuItemImage = [UIImage imageNamed:@"bg-menuitem.png"]; 22 | UIImage *storyMenuItemImagePressed = [UIImage imageNamed:@"bg-menuitem-highlighted.png"]; 23 | 24 | UIImage *starImage = [UIImage imageNamed:@"icon-star.png"]; 25 | 26 | // Default Menu 27 | 28 | AwesomeMenuItem *starMenuItem1 = [[AwesomeMenuItem alloc] initWithImage:storyMenuItemImage 29 | highlightedImage:storyMenuItemImagePressed 30 | ContentImage:starImage 31 | highlightedContentImage:nil]; 32 | AwesomeMenuItem *starMenuItem2 = [[AwesomeMenuItem alloc] initWithImage:storyMenuItemImage 33 | highlightedImage:storyMenuItemImagePressed 34 | ContentImage:starImage 35 | highlightedContentImage:nil]; 36 | AwesomeMenuItem *starMenuItem3 = [[AwesomeMenuItem alloc] initWithImage:storyMenuItemImage 37 | highlightedImage:storyMenuItemImagePressed 38 | ContentImage:starImage 39 | highlightedContentImage:nil]; 40 | AwesomeMenuItem *starMenuItem4 = [[AwesomeMenuItem alloc] initWithImage:storyMenuItemImage 41 | highlightedImage:storyMenuItemImagePressed 42 | ContentImage:starImage 43 | highlightedContentImage:nil]; 44 | AwesomeMenuItem *starMenuItem5 = [[AwesomeMenuItem alloc] initWithImage:storyMenuItemImage 45 | highlightedImage:storyMenuItemImagePressed 46 | ContentImage:starImage 47 | highlightedContentImage:nil]; 48 | AwesomeMenuItem *starMenuItem6 = [[AwesomeMenuItem alloc] initWithImage:storyMenuItemImage 49 | highlightedImage:storyMenuItemImagePressed 50 | ContentImage:starImage 51 | highlightedContentImage:nil]; 52 | AwesomeMenuItem *starMenuItem7 = [[AwesomeMenuItem alloc] initWithImage:storyMenuItemImage 53 | highlightedImage:storyMenuItemImagePressed 54 | ContentImage:starImage 55 | highlightedContentImage:nil]; 56 | AwesomeMenuItem *starMenuItem8 = [[AwesomeMenuItem alloc] initWithImage:storyMenuItemImage 57 | highlightedImage:storyMenuItemImagePressed 58 | ContentImage:starImage 59 | highlightedContentImage:nil]; 60 | AwesomeMenuItem *starMenuItem9 = [[AwesomeMenuItem alloc] initWithImage:storyMenuItemImage 61 | highlightedImage:storyMenuItemImagePressed 62 | ContentImage:starImage 63 | highlightedContentImage:nil]; 64 | 65 | NSArray *menuItems = [NSArray arrayWithObjects:starMenuItem1, starMenuItem2, starMenuItem3, starMenuItem4, starMenuItem5, starMenuItem6, starMenuItem7,starMenuItem8,starMenuItem9, nil]; 66 | 67 | AwesomeMenuItem *startItem = [[AwesomeMenuItem alloc] initWithImage:[UIImage imageNamed:@"bg-addbutton.png"] 68 | highlightedImage:[UIImage imageNamed:@"bg-addbutton-highlighted.png"] 69 | ContentImage:[UIImage imageNamed:@"icon-plus.png"] 70 | highlightedContentImage:[UIImage imageNamed:@"icon-plus-highlighted.png"]]; 71 | 72 | AwesomeMenu *menu = [[AwesomeMenu alloc] initWithFrame:self.window.bounds startItem:startItem menuItems:menuItems]; 73 | menu.delegate = self; 74 | 75 | 76 | 77 | /* Path-like customization 78 | 79 | AwesomeMenuItem *starMenuItem1 = [[AwesomeMenuItem alloc] initWithImage:storyMenuItemImage 80 | highlightedImage:storyMenuItemImagePressed 81 | ContentImage:starImage 82 | highlightedContentImage:nil]; 83 | AwesomeMenuItem *starMenuItem2 = [[AwesomeMenuItem alloc] initWithImage:storyMenuItemImage 84 | highlightedImage:storyMenuItemImagePressed 85 | ContentImage:starImage 86 | highlightedContentImage:nil]; 87 | AwesomeMenuItem *starMenuItem3 = [[AwesomeMenuItem alloc] initWithImage:storyMenuItemImage 88 | highlightedImage:storyMenuItemImagePressed 89 | ContentImage:starImage 90 | highlightedContentImage:nil]; 91 | AwesomeMenuItem *starMenuItem4 = [[AwesomeMenuItem alloc] initWithImage:storyMenuItemImage 92 | highlightedImage:storyMenuItemImagePressed 93 | ContentImage:starImage 94 | highlightedContentImage:nil]; 95 | AwesomeMenuItem *starMenuItem5 = [[AwesomeMenuItem alloc] initWithImage:storyMenuItemImage 96 | highlightedImage:storyMenuItemImagePressed 97 | ContentImage:starImage 98 | highlightedContentImage:nil]; 99 | 100 | NSArray *menus = [NSArray arrayWithObjects:starMenuItem1, starMenuItem2, starMenuItem3, starMenuItem4, starMenuItem5, nil]; 101 | 102 | AwesomeMenuItem *startItem = [[AwesomeMenuItem alloc] initWithImage:[UIImage imageNamed:@"bg-addbutton.png"] 103 | highlightedImage:[UIImage imageNamed:@"bg-addbutton-highlighted.png"] 104 | ContentImage:[UIImage imageNamed:@"icon-plus.png"] 105 | highlightedContentImage:[UIImage imageNamed:@"icon-plus-highlighted.png"]]; 106 | 107 | AwesomeMenu *menu = [[AwesomeMenu alloc] initWithFrame:self.window.bounds startItem:startItem optionMenus:menus]; 108 | menu.delegate = self; 109 | 110 | menu.menuWholeAngle = M_PI_2; 111 | menu.farRadius = 110.0f; 112 | menu.endRadius = 100.0f; 113 | menu.nearRadius = 90.0f; 114 | menu.animationDuration = 0.3f; 115 | menu.startPoint = CGPointMake(50.0, 410.0); 116 | 117 | */ 118 | 119 | [self.window addSubview:menu]; 120 | [self.window makeKeyAndVisible]; 121 | return YES; 122 | } 123 | 124 | 125 | /* ⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇ */ 126 | /* ⬇⬇⬇⬇⬇⬇ GET RESPONSE OF MENU ⬇⬇⬇⬇⬇⬇ */ 127 | /* ⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇ */ 128 | 129 | - (void)awesomeMenu:(AwesomeMenu *)menu didSelectIndex:(NSInteger)idx 130 | { 131 | NSLog(@"Select the index : %d",idx); 132 | } 133 | - (void)awesomeMenuDidFinishAnimationClose:(AwesomeMenu *)menu { 134 | NSLog(@"Menu was closed!"); 135 | } 136 | - (void)awesomeMenuDidFinishAnimationOpen:(AwesomeMenu *)menu { 137 | NSLog(@"Menu is open!"); 138 | } 139 | @end 140 | -------------------------------------------------------------------------------- /AwesomeMenu/AwesomeMenu-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIconFiles 12 | 13 | CFBundleIdentifier 14 | com.lunaapp.${PRODUCT_NAME:rfc1034identifier} 15 | CFBundleInfoDictionaryVersion 16 | 6.0 17 | CFBundleName 18 | ${PRODUCT_NAME} 19 | CFBundlePackageType 20 | APPL 21 | CFBundleShortVersionString 22 | 1.0 23 | CFBundleSignature 24 | ???? 25 | CFBundleVersion 26 | 1.0 27 | LSRequiresIPhoneOS 28 | 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UIStatusBarHidden 34 | 35 | UISupportedInterfaceOrientations 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /AwesomeMenu/AwesomeMenu-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'AwesomeMenu' target in the 'AwesomeMenu' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_3_0 8 | #warning "This project uses features only available in iOS SDK 3.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #endif 15 | -------------------------------------------------------------------------------- /AwesomeMenu/AwesomeMenu/AwesomeMenu.h: -------------------------------------------------------------------------------- 1 | // 2 | // AwesomeMenu.h 3 | // AwesomeMenu 4 | // 5 | // Created by Levey on 11/30/11. 6 | // Copyright (c) 2011 Levey & Other Contributors. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AwesomeMenuItem.h" 11 | 12 | @protocol AwesomeMenuDelegate; 13 | 14 | @interface AwesomeMenu : UIView 15 | 16 | @property (nonatomic, copy) NSArray *menuItems; 17 | @property (nonatomic, strong) AwesomeMenuItem *startButton; 18 | 19 | @property (nonatomic, getter = isExpanded) BOOL expanded; 20 | @property (nonatomic, weak) id delegate; 21 | 22 | @property (nonatomic, strong) UIImage *image; 23 | @property (nonatomic, strong) UIImage *highlightedImage; 24 | @property (nonatomic, strong) UIImage *contentImage; 25 | @property (nonatomic, strong) UIImage *highlightedContentImage; 26 | 27 | @property (nonatomic, assign) CGFloat nearRadius; 28 | @property (nonatomic, assign) CGFloat endRadius; 29 | @property (nonatomic, assign) CGFloat farRadius; 30 | @property (nonatomic, assign) CGPoint startPoint; 31 | @property (nonatomic, assign) CGFloat timeOffset; 32 | @property (nonatomic, assign) CGFloat rotateAngle; 33 | @property (nonatomic, assign) CGFloat menuWholeAngle; 34 | @property (nonatomic, assign) CGFloat expandRotation; 35 | @property (nonatomic, assign) CGFloat closeRotation; 36 | @property (nonatomic, assign) CGFloat animationDuration; 37 | @property (nonatomic, assign) BOOL rotateAddButton; 38 | 39 | - (id)initWithFrame:(CGRect)frame startItem:(AwesomeMenuItem*)startItem menuItems:(NSArray *)menuItems; 40 | 41 | - (id)initWithFrame:(CGRect)frame startItem:(AwesomeMenuItem*)startItem optionMenus:(NSArray *)aMenusArray DEPRECATED_MSG_ATTRIBUTE("use -initWithFrame:startItem:menuItems: instead."); 42 | 43 | - (AwesomeMenuItem *)menuItemAtIndex:(NSUInteger)index; 44 | 45 | - (void)open; 46 | 47 | - (void)close; 48 | 49 | @end 50 | 51 | @protocol AwesomeMenuDelegate 52 | - (void)awesomeMenu:(AwesomeMenu *)menu didSelectIndex:(NSInteger)idx; 53 | @optional 54 | - (void)awesomeMenuDidFinishAnimationClose:(AwesomeMenu *)menu; 55 | - (void)awesomeMenuDidFinishAnimationOpen:(AwesomeMenu *)menu; 56 | - (void)awesomeMenuWillAnimateOpen:(AwesomeMenu *)menu; 57 | - (void)awesomeMenuWillAnimateClose:(AwesomeMenu *)menu; 58 | @end -------------------------------------------------------------------------------- /AwesomeMenu/AwesomeMenu/AwesomeMenu.m: -------------------------------------------------------------------------------- 1 | // 2 | // AwesomeMenu.m 3 | // AwesomeMenu 4 | // 5 | // Created by Levey on 11/30/11. 6 | // Copyright (c) 2011 Levey & Other Contributors. All rights reserved. 7 | // 8 | 9 | #import "AwesomeMenu.h" 10 | #import 11 | 12 | static CGFloat const kAwesomeMenuDefaultNearRadius = 110.0f; 13 | static CGFloat const kAwesomeMenuDefaultEndRadius = 120.0f; 14 | static CGFloat const kAwesomeMenuDefaultFarRadius = 140.0f; 15 | static CGFloat const kAwesomeMenuDefaultStartPointX = 160.0; 16 | static CGFloat const kAwesomeMenuDefaultStartPointY = 240.0; 17 | static CGFloat const kAwesomeMenuDefaultTimeOffset = 0.036f; 18 | static CGFloat const kAwesomeMenuDefaultRotateAngle = 0.0; 19 | static CGFloat const kAwesomeMenuDefaultMenuWholeAngle = M_PI * 2; 20 | static CGFloat const kAwesomeMenuDefaultExpandRotation = M_PI; 21 | static CGFloat const kAwesomeMenuDefaultCloseRotation = M_PI * 2; 22 | static CGFloat const kAwesomeMenuDefaultAnimationDuration = 0.5f; 23 | static CGFloat const kAwesomeMenuStartMenuDefaultAnimationDuration = 0.3f; 24 | 25 | static CGPoint RotateCGPointAroundCenter(CGPoint point, CGPoint center, float angle) 26 | { 27 | CGAffineTransform translation = CGAffineTransformMakeTranslation(center.x, center.y); 28 | CGAffineTransform rotation = CGAffineTransformMakeRotation(angle); 29 | CGAffineTransform transformGroup = CGAffineTransformConcat(CGAffineTransformConcat(CGAffineTransformInvert(translation), rotation), translation); 30 | return CGPointApplyAffineTransform(point, transformGroup); 31 | } 32 | 33 | @interface AwesomeMenu () 34 | - (void)_expandAnimation; 35 | - (void)_closeAnimation; 36 | - (void)_setMenu; 37 | - (CAAnimationGroup *)_blowupAnimationAtPoint:(CGPoint)p; 38 | - (CAAnimationGroup *)_shrinkAnimationAtPoint:(CGPoint)p; 39 | @end 40 | 41 | @implementation AwesomeMenu { 42 | NSUInteger _flag; 43 | NSTimer *_timer; 44 | BOOL _isAnimating; 45 | } 46 | 47 | @synthesize nearRadius, endRadius, farRadius, timeOffset, rotateAngle, menuWholeAngle, startPoint, expandRotation, closeRotation, animationDuration, rotateAddButton; 48 | @synthesize expanded = _expanded; 49 | 50 | #pragma mark - Initialization & Cleaning up 51 | 52 | - (id)initWithFrame:(CGRect)frame startItem:(AwesomeMenuItem*)startItem menuItems:(NSArray *)menuItems 53 | { 54 | self = [super initWithFrame:frame]; 55 | if (self) { 56 | self.backgroundColor = [UIColor clearColor]; 57 | self.nearRadius = kAwesomeMenuDefaultNearRadius; 58 | self.endRadius = kAwesomeMenuDefaultEndRadius; 59 | self.farRadius = kAwesomeMenuDefaultFarRadius; 60 | self.timeOffset = kAwesomeMenuDefaultTimeOffset; 61 | self.rotateAngle = kAwesomeMenuDefaultRotateAngle; 62 | self.menuWholeAngle = kAwesomeMenuDefaultMenuWholeAngle; 63 | self.startPoint = CGPointMake(kAwesomeMenuDefaultStartPointX, kAwesomeMenuDefaultStartPointY); 64 | self.expandRotation = kAwesomeMenuDefaultExpandRotation; 65 | self.closeRotation = kAwesomeMenuDefaultCloseRotation; 66 | self.animationDuration = kAwesomeMenuDefaultAnimationDuration; 67 | self.rotateAddButton = YES; 68 | 69 | self.menuItems = menuItems; 70 | 71 | // assign startItem to "Add" Button. 72 | self.startButton = startItem; 73 | self.startButton.delegate = self; 74 | self.startButton.center = self.startPoint; 75 | [self addSubview:self.startButton]; 76 | } 77 | return self; 78 | } 79 | 80 | - (id)initWithFrame:(CGRect)frame startItem:(AwesomeMenuItem*)startItem optionMenus:(NSArray *)aMenusArray 81 | { 82 | return [self initWithFrame:frame startItem:startItem menuItems:aMenusArray]; 83 | } 84 | 85 | #pragma mark - Getters & Setters 86 | 87 | - (void)setStartPoint:(CGPoint)aPoint 88 | { 89 | startPoint = aPoint; 90 | self.startButton.center = aPoint; 91 | } 92 | 93 | #pragma mark - Images 94 | 95 | - (void)setImage:(UIImage *)image { 96 | self.startButton.image = image; 97 | } 98 | 99 | - (UIImage*)image { 100 | return self.startButton.image; 101 | } 102 | 103 | - (void)setHighlightedImage:(UIImage *)highlightedImage { 104 | self.startButton.highlightedImage = highlightedImage; 105 | } 106 | 107 | - (UIImage*)highlightedImage { 108 | return self.startButton.highlightedImage; 109 | } 110 | 111 | 112 | - (void)setContentImage:(UIImage *)contentImage { 113 | self.startButton.contentImageView.image = contentImage; 114 | } 115 | 116 | - (UIImage*)contentImage { 117 | return self.startButton.contentImageView.image; 118 | } 119 | 120 | - (void)setHighlightedContentImage:(UIImage *)highlightedContentImage { 121 | self.startButton.contentImageView.highlightedImage = highlightedContentImage; 122 | } 123 | 124 | - (UIImage*)highlightedContentImage { 125 | return self.startButton.contentImageView.highlightedImage; 126 | } 127 | 128 | 129 | 130 | #pragma mark - UIView's methods 131 | 132 | - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event 133 | { 134 | // if the menu is animating, prevent touches 135 | if (_isAnimating) 136 | { 137 | return NO; 138 | } 139 | // if the menu state is expanding, everywhere can be touch 140 | // otherwise, only the add button are can be touch 141 | if (YES == [self isExpanded]) 142 | { 143 | return YES; 144 | } 145 | else 146 | { 147 | return CGRectContainsPoint(self.startButton.frame, point); 148 | } 149 | } 150 | 151 | - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 152 | { 153 | self.expanded = ![self isExpanded]; 154 | } 155 | 156 | #pragma mark - AwesomeMenuItem delegates 157 | 158 | - (void)AwesomeMenuItemTouchesBegan:(AwesomeMenuItem *)item 159 | { 160 | if (item == self.startButton) 161 | { 162 | self.expanded = ![self isExpanded]; 163 | } 164 | } 165 | - (void)AwesomeMenuItemTouchesEnd:(AwesomeMenuItem *)item 166 | { 167 | // exclude the "add" button 168 | if (item == self.startButton) 169 | { 170 | return; 171 | } 172 | // blowup the selected menu button 173 | CAAnimationGroup *blowup = [self _blowupAnimationAtPoint:item.center]; 174 | [item.layer addAnimation:blowup forKey:@"blowup"]; 175 | item.center = item.startPoint; 176 | 177 | // shrink other menu buttons 178 | for (int i = 0; i < [self.menuItems count]; i ++) 179 | { 180 | AwesomeMenuItem *otherItem = [self.menuItems objectAtIndex:i]; 181 | CAAnimationGroup *shrink = [self _shrinkAnimationAtPoint:otherItem.center]; 182 | if (otherItem.tag == item.tag) { 183 | continue; 184 | } 185 | [otherItem.layer addAnimation:shrink forKey:@"shrink"]; 186 | 187 | otherItem.center = otherItem.startPoint; 188 | } 189 | _expanded = NO; 190 | 191 | // rotate start button 192 | float angle = [self isExpanded] ? -M_PI_4 : 0.0f; 193 | [UIView animateWithDuration:animationDuration animations:^{ 194 | self.startButton.transform = CGAffineTransformMakeRotation(angle); 195 | }]; 196 | 197 | if ([_delegate respondsToSelector:@selector(awesomeMenu:didSelectIndex:)]) 198 | { 199 | [_delegate awesomeMenu:self didSelectIndex:item.tag - 1000]; 200 | } 201 | } 202 | 203 | #pragma mark - Instance methods 204 | 205 | - (void)setMenuItems:(NSArray *)menuItems 206 | { 207 | if (menuItems == _menuItems) 208 | { 209 | return; 210 | } 211 | _menuItems = [menuItems copy]; 212 | 213 | 214 | // clean subviews 215 | for (UIView *v in self.subviews) 216 | { 217 | if (v.tag >= 1000) 218 | { 219 | [v removeFromSuperview]; 220 | } 221 | } 222 | } 223 | 224 | - (AwesomeMenuItem *)menuItemAtIndex:(NSUInteger)index 225 | { 226 | if (index >= [self.menuItems count]) { 227 | return nil; 228 | } 229 | return self.menuItems[index]; 230 | } 231 | 232 | - (void)open 233 | { 234 | if (_isAnimating || [self isExpanded]) { 235 | return; 236 | } 237 | [self setExpanded:YES]; 238 | } 239 | 240 | - (void)close 241 | { 242 | if (_isAnimating || ![self isExpanded]) { 243 | return; 244 | } 245 | [self setExpanded:NO]; 246 | } 247 | 248 | - (void)_setMenu { 249 | NSUInteger count = [self.menuItems count]; 250 | for (int i = 0; i < count; i ++) 251 | { 252 | AwesomeMenuItem *item = [self.menuItems objectAtIndex:i]; 253 | item.tag = 1000 + i; 254 | item.startPoint = startPoint; 255 | 256 | // avoid overlap 257 | if (menuWholeAngle >= M_PI * 2) { 258 | menuWholeAngle = menuWholeAngle - menuWholeAngle / count; 259 | } 260 | CGPoint endPoint = CGPointMake(startPoint.x + endRadius * sinf(i * menuWholeAngle / (count - 1)), startPoint.y - endRadius * cosf(i * menuWholeAngle / (count - 1))); 261 | item.endPoint = RotateCGPointAroundCenter(endPoint, startPoint, rotateAngle); 262 | CGPoint nearPoint = CGPointMake(startPoint.x + nearRadius * sinf(i * menuWholeAngle / (count - 1)), startPoint.y - nearRadius * cosf(i * menuWholeAngle / (count - 1))); 263 | item.nearPoint = RotateCGPointAroundCenter(nearPoint, startPoint, rotateAngle); 264 | CGPoint farPoint = CGPointMake(startPoint.x + farRadius * sinf(i * menuWholeAngle / (count - 1)), startPoint.y - farRadius * cosf(i * menuWholeAngle / (count - 1))); 265 | item.farPoint = RotateCGPointAroundCenter(farPoint, startPoint, rotateAngle); 266 | item.center = item.startPoint; 267 | item.delegate = self; 268 | [self insertSubview:item belowSubview:self.startButton]; 269 | } 270 | } 271 | 272 | - (BOOL)isExpanded 273 | { 274 | return _expanded; 275 | } 276 | - (void)setExpanded:(BOOL)expanded 277 | { 278 | if (expanded) { 279 | [self _setMenu]; 280 | if(self.delegate && [self.delegate respondsToSelector:@selector(awesomeMenuWillAnimateOpen:)]){ 281 | [self.delegate awesomeMenuWillAnimateOpen:self]; 282 | } 283 | } else { 284 | if(self.delegate && [self.delegate respondsToSelector:@selector(awesomeMenuWillAnimateClose:)]){ 285 | [self.delegate awesomeMenuWillAnimateClose:self]; 286 | } 287 | } 288 | 289 | _expanded = expanded; 290 | 291 | // rotate add button 292 | if (self.rotateAddButton) { 293 | float angle = [self isExpanded] ? -M_PI_4 : 0.0f; 294 | [UIView animateWithDuration:kAwesomeMenuStartMenuDefaultAnimationDuration animations:^{ 295 | self.startButton.transform = CGAffineTransformMakeRotation(angle); 296 | }]; 297 | } 298 | 299 | // expand or close animation 300 | if (!_timer) 301 | { 302 | _flag = [self isExpanded] ? 0 : ([self.menuItems count] - 1); 303 | SEL selector = [self isExpanded] ? @selector(_expandAnimation) : @selector(_closeAnimation); 304 | 305 | // Adding timer to runloop to make sure UI event won't block the timer from firing 306 | _timer = [NSTimer timerWithTimeInterval:timeOffset target:self selector:selector userInfo:nil repeats:YES]; 307 | [[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSRunLoopCommonModes]; 308 | _isAnimating = YES; 309 | } 310 | } 311 | 312 | #pragma mark - Private methods 313 | 314 | - (void)_expandAnimation 315 | { 316 | 317 | if (_flag == [self.menuItems count]) 318 | { 319 | _isAnimating = NO; 320 | [_timer invalidate]; 321 | _timer = nil; 322 | return; 323 | } 324 | 325 | NSUInteger tag = 1000 + _flag; 326 | AwesomeMenuItem *item = (AwesomeMenuItem *)[self viewWithTag:tag]; 327 | 328 | CAKeyframeAnimation *rotateAnimation = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation.z"]; 329 | rotateAnimation.values = [NSArray arrayWithObjects:[NSNumber numberWithFloat:expandRotation],[NSNumber numberWithFloat:0.0f], nil]; 330 | rotateAnimation.duration = animationDuration; 331 | rotateAnimation.keyTimes = [NSArray arrayWithObjects: 332 | [NSNumber numberWithFloat:.3], 333 | [NSNumber numberWithFloat:.4], nil]; 334 | 335 | CAKeyframeAnimation *positionAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"]; 336 | positionAnimation.duration = animationDuration; 337 | CGMutablePathRef path = CGPathCreateMutable(); 338 | CGPathMoveToPoint(path, NULL, item.startPoint.x, item.startPoint.y); 339 | CGPathAddLineToPoint(path, NULL, item.farPoint.x, item.farPoint.y); 340 | CGPathAddLineToPoint(path, NULL, item.nearPoint.x, item.nearPoint.y); 341 | CGPathAddLineToPoint(path, NULL, item.endPoint.x, item.endPoint.y); 342 | positionAnimation.path = path; 343 | CGPathRelease(path); 344 | 345 | CAAnimationGroup *animationgroup = [CAAnimationGroup animation]; 346 | animationgroup.animations = [NSArray arrayWithObjects:positionAnimation, rotateAnimation, nil]; 347 | animationgroup.duration = animationDuration; 348 | animationgroup.fillMode = kCAFillModeForwards; 349 | animationgroup.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]; 350 | animationgroup.delegate = self; 351 | if(_flag == [self.menuItems count] - 1){ 352 | [animationgroup setValue:@"firstAnimation" forKey:@"id"]; 353 | } 354 | 355 | [item.layer addAnimation:animationgroup forKey:@"Expand"]; 356 | item.center = item.endPoint; 357 | 358 | _flag ++; 359 | 360 | } 361 | 362 | - (void)_closeAnimation 363 | { 364 | if (_flag == -1) 365 | { 366 | _isAnimating = NO; 367 | [_timer invalidate]; 368 | _timer = nil; 369 | return; 370 | } 371 | 372 | NSUInteger tag = 1000 + _flag; 373 | AwesomeMenuItem *item = (AwesomeMenuItem *)[self viewWithTag:tag]; 374 | 375 | CAKeyframeAnimation *rotateAnimation = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation.z"]; 376 | rotateAnimation.values = [NSArray arrayWithObjects:[NSNumber numberWithFloat:0.0f],[NSNumber numberWithFloat:closeRotation],[NSNumber numberWithFloat:0.0f], nil]; 377 | rotateAnimation.duration = animationDuration; 378 | rotateAnimation.keyTimes = [NSArray arrayWithObjects: 379 | [NSNumber numberWithFloat:.0], 380 | [NSNumber numberWithFloat:.4], 381 | [NSNumber numberWithFloat:.5], nil]; 382 | 383 | CAKeyframeAnimation *positionAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"]; 384 | positionAnimation.duration = animationDuration; 385 | CGMutablePathRef path = CGPathCreateMutable(); 386 | CGPathMoveToPoint(path, NULL, item.endPoint.x, item.endPoint.y); 387 | CGPathAddLineToPoint(path, NULL, item.farPoint.x, item.farPoint.y); 388 | CGPathAddLineToPoint(path, NULL, item.startPoint.x, item.startPoint.y); 389 | positionAnimation.path = path; 390 | CGPathRelease(path); 391 | 392 | CAAnimationGroup *animationgroup = [CAAnimationGroup animation]; 393 | animationgroup.animations = [NSArray arrayWithObjects:positionAnimation, rotateAnimation, nil]; 394 | animationgroup.duration = animationDuration; 395 | animationgroup.fillMode = kCAFillModeForwards; 396 | animationgroup.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]; 397 | animationgroup.delegate = self; 398 | if(_flag == 0){ 399 | [animationgroup setValue:@"lastAnimation" forKey:@"id"]; 400 | } 401 | 402 | [item.layer addAnimation:animationgroup forKey:@"Close"]; 403 | item.center = item.startPoint; 404 | 405 | _flag --; 406 | } 407 | - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag { 408 | if([[anim valueForKey:@"id"] isEqual:@"lastAnimation"]) { 409 | if(self.delegate && [self.delegate respondsToSelector:@selector(awesomeMenuDidFinishAnimationClose:)]){ 410 | [self.delegate awesomeMenuDidFinishAnimationClose:self]; 411 | } 412 | } 413 | if([[anim valueForKey:@"id"] isEqual:@"firstAnimation"]) { 414 | if(self.delegate && [self.delegate respondsToSelector:@selector(awesomeMenuDidFinishAnimationOpen:)]){ 415 | [self.delegate awesomeMenuDidFinishAnimationOpen:self]; 416 | } 417 | } 418 | } 419 | - (CAAnimationGroup *)_blowupAnimationAtPoint:(CGPoint)p 420 | { 421 | CAKeyframeAnimation *positionAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"]; 422 | positionAnimation.values = [NSArray arrayWithObjects:[NSValue valueWithCGPoint:p], nil]; 423 | positionAnimation.keyTimes = [NSArray arrayWithObjects: [NSNumber numberWithFloat:.3], nil]; 424 | 425 | CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:@"transform"]; 426 | scaleAnimation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(3, 3, 1)]; 427 | 428 | CABasicAnimation *opacityAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"]; 429 | opacityAnimation.toValue = [NSNumber numberWithFloat:0.0f]; 430 | 431 | CAAnimationGroup *animationgroup = [CAAnimationGroup animation]; 432 | animationgroup.animations = [NSArray arrayWithObjects:positionAnimation, scaleAnimation, opacityAnimation, nil]; 433 | animationgroup.duration = animationDuration; 434 | animationgroup.fillMode = kCAFillModeForwards; 435 | 436 | return animationgroup; 437 | } 438 | 439 | - (CAAnimationGroup *)_shrinkAnimationAtPoint:(CGPoint)p 440 | { 441 | CAKeyframeAnimation *positionAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"]; 442 | positionAnimation.values = [NSArray arrayWithObjects:[NSValue valueWithCGPoint:p], nil]; 443 | positionAnimation.keyTimes = [NSArray arrayWithObjects: [NSNumber numberWithFloat:.3], nil]; 444 | 445 | CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:@"transform"]; 446 | scaleAnimation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(.01, .01, 1)]; 447 | 448 | CABasicAnimation *opacityAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"]; 449 | opacityAnimation.toValue = [NSNumber numberWithFloat:0.0f]; 450 | 451 | CAAnimationGroup *animationgroup = [CAAnimationGroup animation]; 452 | animationgroup.animations = [NSArray arrayWithObjects:positionAnimation, scaleAnimation, opacityAnimation, nil]; 453 | animationgroup.duration = animationDuration; 454 | animationgroup.fillMode = kCAFillModeForwards; 455 | 456 | return animationgroup; 457 | } 458 | 459 | 460 | @end 461 | -------------------------------------------------------------------------------- /AwesomeMenu/AwesomeMenu/AwesomeMenuItem.h: -------------------------------------------------------------------------------- 1 | // 2 | // AwesomeMenuItem.h 3 | // AwesomeMenu 4 | // 5 | // Created by Levey on 11/30/11. 6 | // Copyright (c) 2011 Levey & Other Contributors. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @protocol AwesomeMenuItemDelegate; 12 | 13 | @interface AwesomeMenuItem : UIImageView 14 | { 15 | UIImageView *_contentImageView; 16 | CGPoint _startPoint; 17 | CGPoint _endPoint; 18 | CGPoint _nearPoint; // near 19 | CGPoint _farPoint; // far 20 | 21 | id __weak _delegate; 22 | } 23 | 24 | @property (nonatomic, strong, readonly) UIImageView *contentImageView; 25 | 26 | @property (nonatomic) CGPoint startPoint; 27 | @property (nonatomic) CGPoint endPoint; 28 | @property (nonatomic) CGPoint nearPoint; 29 | @property (nonatomic) CGPoint farPoint; 30 | 31 | @property (nonatomic, weak) id delegate; 32 | 33 | - (id)initWithImage:(UIImage *)img 34 | highlightedImage:(UIImage *)himg 35 | ContentImage:(UIImage *)cimg 36 | highlightedContentImage:(UIImage *)hcimg; 37 | 38 | 39 | @end 40 | 41 | @protocol AwesomeMenuItemDelegate 42 | - (void)AwesomeMenuItemTouchesBegan:(AwesomeMenuItem *)item; 43 | - (void)AwesomeMenuItemTouchesEnd:(AwesomeMenuItem *)item; 44 | @end -------------------------------------------------------------------------------- /AwesomeMenu/AwesomeMenu/AwesomeMenuItem.m: -------------------------------------------------------------------------------- 1 | // 2 | // AwesomeMenuItem.m 3 | // AwesomeMenu 4 | // 5 | // Created by Levey on 11/30/11. 6 | // Copyright (c) 2011 Levey & Other Contributors. All rights reserved. 7 | // 8 | 9 | #import "AwesomeMenuItem.h" 10 | static inline CGRect ScaleRect(CGRect rect, float n) {return CGRectMake((rect.size.width - rect.size.width * n)/ 2, (rect.size.height - rect.size.height * n) / 2, rect.size.width * n, rect.size.height * n);} 11 | @implementation AwesomeMenuItem 12 | 13 | @synthesize contentImageView = _contentImageView; 14 | 15 | @synthesize startPoint = _startPoint; 16 | @synthesize endPoint = _endPoint; 17 | @synthesize nearPoint = _nearPoint; 18 | @synthesize farPoint = _farPoint; 19 | @synthesize delegate = _delegate; 20 | 21 | #pragma mark - initialization & cleaning up 22 | - (id)initWithImage:(UIImage *)img 23 | highlightedImage:(UIImage *)himg 24 | ContentImage:(UIImage *)cimg 25 | highlightedContentImage:(UIImage *)hcimg; 26 | { 27 | if (self = [super init]) 28 | { 29 | self.image = img; 30 | self.highlightedImage = himg; 31 | self.userInteractionEnabled = YES; 32 | _contentImageView = [[UIImageView alloc] initWithImage:cimg]; 33 | _contentImageView.highlightedImage = hcimg; 34 | [self addSubview:_contentImageView]; 35 | } 36 | return self; 37 | } 38 | 39 | #pragma mark - UIView's methods 40 | - (void)layoutSubviews 41 | { 42 | [super layoutSubviews]; 43 | 44 | self.bounds = CGRectMake(0, 0, self.image.size.width, self.image.size.height); 45 | 46 | float width = _contentImageView.image.size.width; 47 | float height = _contentImageView.image.size.height; 48 | _contentImageView.frame = CGRectMake(self.bounds.size.width/2 - width/2, self.bounds.size.height/2 - height/2, width, height); 49 | } 50 | 51 | - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 52 | { 53 | self.highlighted = YES; 54 | if ([_delegate respondsToSelector:@selector(AwesomeMenuItemTouchesBegan:)]) 55 | { 56 | [_delegate AwesomeMenuItemTouchesBegan:self]; 57 | } 58 | 59 | } 60 | - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 61 | { 62 | // if move out of 2x rect, cancel highlighted. 63 | CGPoint location = [[touches anyObject] locationInView:self]; 64 | if (!CGRectContainsPoint(ScaleRect(self.bounds, 2.0f), location)) 65 | { 66 | self.highlighted = NO; 67 | } 68 | 69 | } 70 | - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 71 | { 72 | self.highlighted = NO; 73 | // if stop in the area of 2x rect, response to the touches event. 74 | CGPoint location = [[touches anyObject] locationInView:self]; 75 | if (CGRectContainsPoint(ScaleRect(self.bounds, 2.0f), location)) 76 | { 77 | if ([_delegate respondsToSelector:@selector(AwesomeMenuItemTouchesEnd:)]) 78 | { 79 | [_delegate AwesomeMenuItemTouchesEnd:self]; 80 | } 81 | } 82 | } 83 | 84 | - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event 85 | { 86 | self.highlighted = NO; 87 | } 88 | 89 | #pragma mark - instant methods 90 | - (void)setHighlighted:(BOOL)highlighted 91 | { 92 | [super setHighlighted:highlighted]; 93 | [_contentImageView setHighlighted:highlighted]; 94 | } 95 | 96 | 97 | @end 98 | -------------------------------------------------------------------------------- /AwesomeMenu/Images/bg-addbutton-highlighted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levey/AwesomeMenu/f52b91cea704562d10f3f453da4b74104696ab46/AwesomeMenu/Images/bg-addbutton-highlighted.png -------------------------------------------------------------------------------- /AwesomeMenu/Images/bg-addbutton-highlighted@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levey/AwesomeMenu/f52b91cea704562d10f3f453da4b74104696ab46/AwesomeMenu/Images/bg-addbutton-highlighted@2x.png -------------------------------------------------------------------------------- /AwesomeMenu/Images/bg-addbutton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levey/AwesomeMenu/f52b91cea704562d10f3f453da4b74104696ab46/AwesomeMenu/Images/bg-addbutton.png -------------------------------------------------------------------------------- /AwesomeMenu/Images/bg-addbutton@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levey/AwesomeMenu/f52b91cea704562d10f3f453da4b74104696ab46/AwesomeMenu/Images/bg-addbutton@2x.png -------------------------------------------------------------------------------- /AwesomeMenu/Images/bg-menuitem-highlighted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levey/AwesomeMenu/f52b91cea704562d10f3f453da4b74104696ab46/AwesomeMenu/Images/bg-menuitem-highlighted.png -------------------------------------------------------------------------------- /AwesomeMenu/Images/bg-menuitem-highlighted@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levey/AwesomeMenu/f52b91cea704562d10f3f453da4b74104696ab46/AwesomeMenu/Images/bg-menuitem-highlighted@2x.png -------------------------------------------------------------------------------- /AwesomeMenu/Images/bg-menuitem.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levey/AwesomeMenu/f52b91cea704562d10f3f453da4b74104696ab46/AwesomeMenu/Images/bg-menuitem.png -------------------------------------------------------------------------------- /AwesomeMenu/Images/bg-menuitem@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levey/AwesomeMenu/f52b91cea704562d10f3f453da4b74104696ab46/AwesomeMenu/Images/bg-menuitem@2x.png -------------------------------------------------------------------------------- /AwesomeMenu/Images/icon-plus-highlighted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levey/AwesomeMenu/f52b91cea704562d10f3f453da4b74104696ab46/AwesomeMenu/Images/icon-plus-highlighted.png -------------------------------------------------------------------------------- /AwesomeMenu/Images/icon-plus-highlighted@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levey/AwesomeMenu/f52b91cea704562d10f3f453da4b74104696ab46/AwesomeMenu/Images/icon-plus-highlighted@2x.png -------------------------------------------------------------------------------- /AwesomeMenu/Images/icon-plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levey/AwesomeMenu/f52b91cea704562d10f3f453da4b74104696ab46/AwesomeMenu/Images/icon-plus.png -------------------------------------------------------------------------------- /AwesomeMenu/Images/icon-plus@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levey/AwesomeMenu/f52b91cea704562d10f3f453da4b74104696ab46/AwesomeMenu/Images/icon-plus@2x.png -------------------------------------------------------------------------------- /AwesomeMenu/Images/icon-star.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levey/AwesomeMenu/f52b91cea704562d10f3f453da4b74104696ab46/AwesomeMenu/Images/icon-star.png -------------------------------------------------------------------------------- /AwesomeMenu/Images/icon-star@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levey/AwesomeMenu/f52b91cea704562d10f3f453da4b74104696ab46/AwesomeMenu/Images/icon-star@2x.png -------------------------------------------------------------------------------- /AwesomeMenu/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /AwesomeMenu/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // AwesomeMenu 4 | // 5 | // Created by Levey on 11/30/11. 6 | // Copyright (c) 2011 Levey & Other Contributors. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "AppDelegate.h" 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levey/AwesomeMenu/f52b91cea704562d10f3f453da4b74104696ab46/Default-568h@2x.png -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | I'm happy you are using AwesomeMenu in your project. 2 | 3 | Let me know at levey.zhu@gmail.com. 4 | 5 | OK, this is the MIT License. 6 | 7 | Copyright (c) 2011 levey.slyfairy.com 8 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 9 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### DO NOT USE IT TO COPY PATH! 2 | 3 | --- 4 | 5 | AwesomeMenu is a menu with the same look as the story menu of [Path](https://path.com/). 6 | 7 | --- 8 | 9 | **How To**: 10 | 11 | 12 | Create the menu by setting up the menu items: 13 | 14 | UIImage *storyMenuItemImage = [UIImage imageNamed:@"bg-menuitem.png"]; 15 | UIImage *storyMenuItemImagePressed = [UIImage imageNamed:@"bg-menuitem-highlighted.png"]; 16 | UIImage *starImage = [UIImage imageNamed:@"icon-star.png"]; 17 | AwesomeMenuItem *starMenuItem1 = [[AwesomeMenuItem alloc] initWithImage:storyMenuItemImage 18 | highlightedImage:storyMenuItemImagePressed 19 | ContentImage:starImage 20 | highlightedContentImage:nil]; 21 | AwesomeMenuItem *starMenuItem2 = [[AwesomeMenuItem alloc] initWithImage:storyMenuItemImage 22 | highlightedImage:storyMenuItemImagePressed 23 | ContentImage:starImage 24 | highlightedContentImage:nil]; 25 | // the start item, similar to "add" button of Path 26 | AwesomeMenuItem *startItem = [[AwesomeMenuItem alloc] initWithImage:[UIImage imageNamed:@"bg-addbutton.png"] 27 | highlightedImage:[UIImage imageNamed:@"bg-addbutton-highlighted.png"] 28 | ContentImage:[UIImage imageNamed:@"icon-plus.png"] 29 | highlightedContentImage:[UIImage imageNamed:@"icon-plus-highlighted.png"]]; 30 | 31 | Then, setup the menu and options: 32 | 33 | AwesomeMenu *menu = [[AwesomeMenu alloc] initWithFrame:self.window.bounds startItem:startItem optionMenus:[NSArray arrayWithObjects:starMenuItem1, starMenuItem2]]; 34 | menu.delegate = self; 35 | [self.window addSubview:menu]; 36 | 37 | You can also use menu options: 38 | 39 | to locate the center of "Add" button: 40 | 41 | menu.startPoint = CGPointMake(160.0, 240.0); 42 | 43 | to set the rotate angle: 44 | 45 | menu.rotateAngle = 0.0; 46 | 47 | to set the whole menu angle: 48 | 49 | menu.menuWholeAngle = M_PI * 2; 50 | 51 | to set the delay of every menu flying out animation: 52 | 53 | menu.timeOffset = 0.036f; 54 | 55 | to adjust the bounce animation: 56 | 57 | menu.farRadius = 140.0f; 58 | menu.nearRadius = 110.0f; 59 | 60 | to set the distance between the "Add" button and Menu Items: 61 | 62 | menu.endRadius = 120.0f; 63 | 64 | --- 65 | 66 | Twitter: [@LeveyZhu](https://twitter.com/#!/LeveyZhu) 67 | 68 | Sina Weibo: [@LeveyZhu](http://weibo.com/leveyzhu) 69 | 70 | Thanks for [pashields](https://github.com/pashields) providing the [youtube demo](http://www.youtube.com/watch?v=vddaYMtETjo) :) 71 | 72 | Thanks for [acoomans](https://github.com/acoomans/QuadCurveMenu) for the options. 73 | 74 | 75 | ![screenshots](http://k.minus.com/ib1kHc4lnLB8bd.gif) ![screenshots](http://k.minus.com/iovTFVTQQ192K.gif) ![screenshots](http://k.minus.com/i4BrO2tfCJxzk.gif) 76 | --------------------------------------------------------------------------------