├── .gitignore ├── MultiColumnTableView.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── MultiColumnTableView ├── EWHeaderHighlightLayer.h ├── EWHeaderHighlightLayer.m ├── EWMultiColumnTableView.h ├── EWMultiColumnTableView.m ├── EWMultiColumnTableViewBGScrollView.h ├── EWMultiColumnTableViewBGScrollView.m ├── EWMultiColumnTableViewCell.h ├── EWMultiColumnTableViewCell.m ├── EWMultiColumnTableViewContentBackgroundView.h ├── EWMultiColumnTableViewContentBackgroundView.m ├── EWMultiColumnTableViewDefaults.h ├── MultiColumnTableView-Info.plist ├── MultiColumnTableView-Prefix.pch ├── MultiColumnTableViewAppDelegate.h ├── MultiColumnTableViewAppDelegate.m ├── MultiColumnTableViewViewController.h ├── MultiColumnTableViewViewController.m ├── NSObject+DelayedBlock.h ├── NSObject+DelayedBlock.m ├── UIView+AddLine.h ├── UIView+AddLine.m ├── en.lproj │ ├── InfoPlist.strings │ ├── MainWindow.xib │ └── MultiColumnTableViewViewController.xib └── main.m └── README /.gitignore: -------------------------------------------------------------------------------- 1 | project.xcuserdata/ 2 | xcuserdata/ 3 | .~ 4 | .*.swp 5 | .DS_Store 6 | -------------------------------------------------------------------------------- /MultiColumnTableView.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 459AFE9E14591A2C001AA8B6 /* NSObject+DelayedBlock.m in Sources */ = {isa = PBXBuildFile; fileRef = 459AFE9D14591A2C001AA8B6 /* NSObject+DelayedBlock.m */; }; 11 | BB29157A13D6E76000CFA999 /* EWMultiColumnTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = BB29156E13D6E76000CFA999 /* EWMultiColumnTableView.m */; }; 12 | BB29157B13D6E76000CFA999 /* EWMultiColumnTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = BB29157013D6E76000CFA999 /* EWMultiColumnTableViewCell.m */; }; 13 | BB29157C13D6E76000CFA999 /* EWMultiColumnTableViewContentBackgroundView.m in Sources */ = {isa = PBXBuildFile; fileRef = BB29157313D6E76000CFA999 /* EWMultiColumnTableViewContentBackgroundView.m */; }; 14 | BB29157D13D6E76000CFA999 /* EWMultiColumnTableViewBGScrollView.m in Sources */ = {isa = PBXBuildFile; fileRef = BB29157513D6E76000CFA999 /* EWMultiColumnTableViewBGScrollView.m */; }; 15 | BB29157E13D6E76000CFA999 /* EWHeaderHighlightLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = BB29157713D6E76000CFA999 /* EWHeaderHighlightLayer.m */; }; 16 | BB29157F13D6E76000CFA999 /* UIView+AddLine.m in Sources */ = {isa = PBXBuildFile; fileRef = BB29157913D6E76000CFA999 /* UIView+AddLine.m */; }; 17 | BBB77CE913A38A850080351B /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BBB77CE813A38A850080351B /* QuartzCore.framework */; }; 18 | BBF25B16139F20A800CE773F /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BBF25B15139F20A800CE773F /* UIKit.framework */; }; 19 | BBF25B18139F20A800CE773F /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BBF25B17139F20A800CE773F /* Foundation.framework */; }; 20 | BBF25B1A139F20A800CE773F /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BBF25B19139F20A800CE773F /* CoreGraphics.framework */; }; 21 | BBF25B20139F20A800CE773F /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = BBF25B1E139F20A800CE773F /* InfoPlist.strings */; }; 22 | BBF25B23139F20A800CE773F /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = BBF25B22139F20A800CE773F /* main.m */; }; 23 | BBF25B26139F20A800CE773F /* MultiColumnTableViewAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = BBF25B25139F20A800CE773F /* MultiColumnTableViewAppDelegate.m */; }; 24 | BBF25B29139F20A800CE773F /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = BBF25B27139F20A800CE773F /* MainWindow.xib */; }; 25 | BBF25B2C139F20A800CE773F /* MultiColumnTableViewViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BBF25B2B139F20A800CE773F /* MultiColumnTableViewViewController.m */; }; 26 | BBF25B2F139F20A800CE773F /* MultiColumnTableViewViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = BBF25B2D139F20A800CE773F /* MultiColumnTableViewViewController.xib */; }; 27 | /* End PBXBuildFile section */ 28 | 29 | /* Begin PBXFileReference section */ 30 | 459AFE9C14591A2C001AA8B6 /* NSObject+DelayedBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+DelayedBlock.h"; sourceTree = ""; }; 31 | 459AFE9D14591A2C001AA8B6 /* NSObject+DelayedBlock.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+DelayedBlock.m"; sourceTree = ""; }; 32 | BB29156D13D6E76000CFA999 /* EWMultiColumnTableView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EWMultiColumnTableView.h; sourceTree = ""; }; 33 | BB29156E13D6E76000CFA999 /* EWMultiColumnTableView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EWMultiColumnTableView.m; sourceTree = ""; }; 34 | BB29156F13D6E76000CFA999 /* EWMultiColumnTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EWMultiColumnTableViewCell.h; sourceTree = ""; }; 35 | BB29157013D6E76000CFA999 /* EWMultiColumnTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EWMultiColumnTableViewCell.m; sourceTree = ""; }; 36 | BB29157113D6E76000CFA999 /* EWMultiColumnTableViewDefaults.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EWMultiColumnTableViewDefaults.h; sourceTree = ""; }; 37 | BB29157213D6E76000CFA999 /* EWMultiColumnTableViewContentBackgroundView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EWMultiColumnTableViewContentBackgroundView.h; sourceTree = ""; }; 38 | BB29157313D6E76000CFA999 /* EWMultiColumnTableViewContentBackgroundView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EWMultiColumnTableViewContentBackgroundView.m; sourceTree = ""; }; 39 | BB29157413D6E76000CFA999 /* EWMultiColumnTableViewBGScrollView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EWMultiColumnTableViewBGScrollView.h; sourceTree = ""; }; 40 | BB29157513D6E76000CFA999 /* EWMultiColumnTableViewBGScrollView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EWMultiColumnTableViewBGScrollView.m; sourceTree = ""; }; 41 | BB29157613D6E76000CFA999 /* EWHeaderHighlightLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EWHeaderHighlightLayer.h; sourceTree = ""; }; 42 | BB29157713D6E76000CFA999 /* EWHeaderHighlightLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EWHeaderHighlightLayer.m; sourceTree = ""; }; 43 | BB29157813D6E76000CFA999 /* UIView+AddLine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+AddLine.h"; sourceTree = ""; }; 44 | BB29157913D6E76000CFA999 /* UIView+AddLine.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+AddLine.m"; sourceTree = ""; }; 45 | BBB77CE813A38A850080351B /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; 46 | BBF25B11139F20A800CE773F /* MultiColumnTableView.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MultiColumnTableView.app; sourceTree = BUILT_PRODUCTS_DIR; }; 47 | BBF25B15139F20A800CE773F /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 48 | BBF25B17139F20A800CE773F /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 49 | BBF25B19139F20A800CE773F /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 50 | BBF25B1D139F20A800CE773F /* MultiColumnTableView-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "MultiColumnTableView-Info.plist"; sourceTree = ""; }; 51 | BBF25B1F139F20A800CE773F /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 52 | BBF25B21139F20A800CE773F /* MultiColumnTableView-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "MultiColumnTableView-Prefix.pch"; sourceTree = ""; }; 53 | BBF25B22139F20A800CE773F /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 54 | BBF25B24139F20A800CE773F /* MultiColumnTableViewAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MultiColumnTableViewAppDelegate.h; sourceTree = ""; }; 55 | BBF25B25139F20A800CE773F /* MultiColumnTableViewAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MultiColumnTableViewAppDelegate.m; sourceTree = ""; }; 56 | BBF25B28139F20A800CE773F /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MainWindow.xib; sourceTree = ""; }; 57 | BBF25B2A139F20A800CE773F /* MultiColumnTableViewViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MultiColumnTableViewViewController.h; sourceTree = ""; }; 58 | BBF25B2B139F20A800CE773F /* MultiColumnTableViewViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MultiColumnTableViewViewController.m; sourceTree = ""; }; 59 | BBF25B2E139F20A800CE773F /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MultiColumnTableViewViewController.xib; sourceTree = ""; }; 60 | /* End PBXFileReference section */ 61 | 62 | /* Begin PBXFrameworksBuildPhase section */ 63 | BBF25B0E139F20A800CE773F /* Frameworks */ = { 64 | isa = PBXFrameworksBuildPhase; 65 | buildActionMask = 2147483647; 66 | files = ( 67 | BBB77CE913A38A850080351B /* QuartzCore.framework in Frameworks */, 68 | BBF25B16139F20A800CE773F /* UIKit.framework in Frameworks */, 69 | BBF25B18139F20A800CE773F /* Foundation.framework in Frameworks */, 70 | BBF25B1A139F20A800CE773F /* CoreGraphics.framework in Frameworks */, 71 | ); 72 | runOnlyForDeploymentPostprocessing = 0; 73 | }; 74 | /* End PBXFrameworksBuildPhase section */ 75 | 76 | /* Begin PBXGroup section */ 77 | BB8C983E13C74ABA00FC2FAC /* MultiColumnTableView */ = { 78 | isa = PBXGroup; 79 | children = ( 80 | BB29156D13D6E76000CFA999 /* EWMultiColumnTableView.h */, 81 | BB29156E13D6E76000CFA999 /* EWMultiColumnTableView.m */, 82 | BB29156F13D6E76000CFA999 /* EWMultiColumnTableViewCell.h */, 83 | BB29157013D6E76000CFA999 /* EWMultiColumnTableViewCell.m */, 84 | BB29157113D6E76000CFA999 /* EWMultiColumnTableViewDefaults.h */, 85 | BB29157213D6E76000CFA999 /* EWMultiColumnTableViewContentBackgroundView.h */, 86 | BB29157313D6E76000CFA999 /* EWMultiColumnTableViewContentBackgroundView.m */, 87 | BB29157413D6E76000CFA999 /* EWMultiColumnTableViewBGScrollView.h */, 88 | BB29157513D6E76000CFA999 /* EWMultiColumnTableViewBGScrollView.m */, 89 | BB29157613D6E76000CFA999 /* EWHeaderHighlightLayer.h */, 90 | BB29157713D6E76000CFA999 /* EWHeaderHighlightLayer.m */, 91 | BB29157813D6E76000CFA999 /* UIView+AddLine.h */, 92 | BB29157913D6E76000CFA999 /* UIView+AddLine.m */, 93 | ); 94 | name = MultiColumnTableView; 95 | sourceTree = ""; 96 | }; 97 | BBF25B06139F20A800CE773F = { 98 | isa = PBXGroup; 99 | children = ( 100 | BBF25B1B139F20A800CE773F /* MultiColumnTableView */, 101 | BBF25B14139F20A800CE773F /* Frameworks */, 102 | BBF25B12139F20A800CE773F /* Products */, 103 | ); 104 | sourceTree = ""; 105 | }; 106 | BBF25B12139F20A800CE773F /* Products */ = { 107 | isa = PBXGroup; 108 | children = ( 109 | BBF25B11139F20A800CE773F /* MultiColumnTableView.app */, 110 | ); 111 | name = Products; 112 | sourceTree = ""; 113 | }; 114 | BBF25B14139F20A800CE773F /* Frameworks */ = { 115 | isa = PBXGroup; 116 | children = ( 117 | BBB77CE813A38A850080351B /* QuartzCore.framework */, 118 | BBF25B15139F20A800CE773F /* UIKit.framework */, 119 | BBF25B17139F20A800CE773F /* Foundation.framework */, 120 | BBF25B19139F20A800CE773F /* CoreGraphics.framework */, 121 | ); 122 | name = Frameworks; 123 | sourceTree = ""; 124 | }; 125 | BBF25B1B139F20A800CE773F /* MultiColumnTableView */ = { 126 | isa = PBXGroup; 127 | children = ( 128 | 459AFE9C14591A2C001AA8B6 /* NSObject+DelayedBlock.h */, 129 | 459AFE9D14591A2C001AA8B6 /* NSObject+DelayedBlock.m */, 130 | BBF25B24139F20A800CE773F /* MultiColumnTableViewAppDelegate.h */, 131 | BBF25B25139F20A800CE773F /* MultiColumnTableViewAppDelegate.m */, 132 | BBF25B27139F20A800CE773F /* MainWindow.xib */, 133 | BBF25B2A139F20A800CE773F /* MultiColumnTableViewViewController.h */, 134 | BBF25B2B139F20A800CE773F /* MultiColumnTableViewViewController.m */, 135 | BBF25B2D139F20A800CE773F /* MultiColumnTableViewViewController.xib */, 136 | BB8C983E13C74ABA00FC2FAC /* MultiColumnTableView */, 137 | BBF25B1C139F20A800CE773F /* Supporting Files */, 138 | ); 139 | path = MultiColumnTableView; 140 | sourceTree = ""; 141 | }; 142 | BBF25B1C139F20A800CE773F /* Supporting Files */ = { 143 | isa = PBXGroup; 144 | children = ( 145 | BBF25B1D139F20A800CE773F /* MultiColumnTableView-Info.plist */, 146 | BBF25B1E139F20A800CE773F /* InfoPlist.strings */, 147 | BBF25B21139F20A800CE773F /* MultiColumnTableView-Prefix.pch */, 148 | BBF25B22139F20A800CE773F /* main.m */, 149 | ); 150 | name = "Supporting Files"; 151 | sourceTree = ""; 152 | }; 153 | /* End PBXGroup section */ 154 | 155 | /* Begin PBXNativeTarget section */ 156 | BBF25B10139F20A800CE773F /* MultiColumnTableView */ = { 157 | isa = PBXNativeTarget; 158 | buildConfigurationList = BBF25B32139F20A800CE773F /* Build configuration list for PBXNativeTarget "MultiColumnTableView" */; 159 | buildPhases = ( 160 | BBF25B0D139F20A800CE773F /* Sources */, 161 | BBF25B0E139F20A800CE773F /* Frameworks */, 162 | BBF25B0F139F20A800CE773F /* Resources */, 163 | ); 164 | buildRules = ( 165 | ); 166 | dependencies = ( 167 | ); 168 | name = MultiColumnTableView; 169 | productName = MultiColumnTableView; 170 | productReference = BBF25B11139F20A800CE773F /* MultiColumnTableView.app */; 171 | productType = "com.apple.product-type.application"; 172 | }; 173 | /* End PBXNativeTarget section */ 174 | 175 | /* Begin PBXProject section */ 176 | BBF25B08139F20A800CE773F /* Project object */ = { 177 | isa = PBXProject; 178 | attributes = { 179 | ORGANIZATIONNAME = Newegg.com; 180 | }; 181 | buildConfigurationList = BBF25B0B139F20A800CE773F /* Build configuration list for PBXProject "MultiColumnTableView" */; 182 | compatibilityVersion = "Xcode 3.2"; 183 | developmentRegion = English; 184 | hasScannedForEncodings = 0; 185 | knownRegions = ( 186 | en, 187 | ); 188 | mainGroup = BBF25B06139F20A800CE773F; 189 | productRefGroup = BBF25B12139F20A800CE773F /* Products */; 190 | projectDirPath = ""; 191 | projectRoot = ""; 192 | targets = ( 193 | BBF25B10139F20A800CE773F /* MultiColumnTableView */, 194 | ); 195 | }; 196 | /* End PBXProject section */ 197 | 198 | /* Begin PBXResourcesBuildPhase section */ 199 | BBF25B0F139F20A800CE773F /* Resources */ = { 200 | isa = PBXResourcesBuildPhase; 201 | buildActionMask = 2147483647; 202 | files = ( 203 | BBF25B20139F20A800CE773F /* InfoPlist.strings in Resources */, 204 | BBF25B29139F20A800CE773F /* MainWindow.xib in Resources */, 205 | BBF25B2F139F20A800CE773F /* MultiColumnTableViewViewController.xib in Resources */, 206 | ); 207 | runOnlyForDeploymentPostprocessing = 0; 208 | }; 209 | /* End PBXResourcesBuildPhase section */ 210 | 211 | /* Begin PBXSourcesBuildPhase section */ 212 | BBF25B0D139F20A800CE773F /* Sources */ = { 213 | isa = PBXSourcesBuildPhase; 214 | buildActionMask = 2147483647; 215 | files = ( 216 | BBF25B23139F20A800CE773F /* main.m in Sources */, 217 | BBF25B26139F20A800CE773F /* MultiColumnTableViewAppDelegate.m in Sources */, 218 | BBF25B2C139F20A800CE773F /* MultiColumnTableViewViewController.m in Sources */, 219 | BB29157A13D6E76000CFA999 /* EWMultiColumnTableView.m in Sources */, 220 | BB29157B13D6E76000CFA999 /* EWMultiColumnTableViewCell.m in Sources */, 221 | BB29157C13D6E76000CFA999 /* EWMultiColumnTableViewContentBackgroundView.m in Sources */, 222 | BB29157D13D6E76000CFA999 /* EWMultiColumnTableViewBGScrollView.m in Sources */, 223 | BB29157E13D6E76000CFA999 /* EWHeaderHighlightLayer.m in Sources */, 224 | BB29157F13D6E76000CFA999 /* UIView+AddLine.m in Sources */, 225 | 459AFE9E14591A2C001AA8B6 /* NSObject+DelayedBlock.m in Sources */, 226 | ); 227 | runOnlyForDeploymentPostprocessing = 0; 228 | }; 229 | /* End PBXSourcesBuildPhase section */ 230 | 231 | /* Begin PBXVariantGroup section */ 232 | BBF25B1E139F20A800CE773F /* InfoPlist.strings */ = { 233 | isa = PBXVariantGroup; 234 | children = ( 235 | BBF25B1F139F20A800CE773F /* en */, 236 | ); 237 | name = InfoPlist.strings; 238 | sourceTree = ""; 239 | }; 240 | BBF25B27139F20A800CE773F /* MainWindow.xib */ = { 241 | isa = PBXVariantGroup; 242 | children = ( 243 | BBF25B28139F20A800CE773F /* en */, 244 | ); 245 | name = MainWindow.xib; 246 | sourceTree = ""; 247 | }; 248 | BBF25B2D139F20A800CE773F /* MultiColumnTableViewViewController.xib */ = { 249 | isa = PBXVariantGroup; 250 | children = ( 251 | BBF25B2E139F20A800CE773F /* en */, 252 | ); 253 | name = MultiColumnTableViewViewController.xib; 254 | sourceTree = ""; 255 | }; 256 | /* End PBXVariantGroup section */ 257 | 258 | /* Begin XCBuildConfiguration section */ 259 | BBF25B30139F20A800CE773F /* Debug */ = { 260 | isa = XCBuildConfiguration; 261 | buildSettings = { 262 | ARCHS = "$(ARCHS_UNIVERSAL_IPHONE_OS)"; 263 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 264 | GCC_C_LANGUAGE_STANDARD = gnu99; 265 | GCC_OPTIMIZATION_LEVEL = 0; 266 | GCC_PREPROCESSOR_DEFINITIONS = DEBUG; 267 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 268 | GCC_VERSION = com.apple.compilers.llvmgcc42; 269 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 270 | GCC_WARN_UNUSED_VARIABLE = YES; 271 | IPHONEOS_DEPLOYMENT_TARGET = 4.3; 272 | SDKROOT = iphoneos; 273 | TARGETED_DEVICE_FAMILY = 2; 274 | }; 275 | name = Debug; 276 | }; 277 | BBF25B31139F20A800CE773F /* Release */ = { 278 | isa = XCBuildConfiguration; 279 | buildSettings = { 280 | ARCHS = "$(ARCHS_UNIVERSAL_IPHONE_OS)"; 281 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 282 | GCC_C_LANGUAGE_STANDARD = gnu99; 283 | GCC_VERSION = com.apple.compilers.llvmgcc42; 284 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 285 | GCC_WARN_UNUSED_VARIABLE = YES; 286 | IPHONEOS_DEPLOYMENT_TARGET = 4.3; 287 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; 288 | SDKROOT = iphoneos; 289 | TARGETED_DEVICE_FAMILY = 2; 290 | }; 291 | name = Release; 292 | }; 293 | BBF25B33139F20A800CE773F /* Debug */ = { 294 | isa = XCBuildConfiguration; 295 | buildSettings = { 296 | ALWAYS_SEARCH_USER_PATHS = NO; 297 | COPY_PHASE_STRIP = NO; 298 | GCC_DYNAMIC_NO_PIC = NO; 299 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 300 | GCC_PREFIX_HEADER = "MultiColumnTableView/MultiColumnTableView-Prefix.pch"; 301 | INFOPLIST_FILE = "MultiColumnTableView/MultiColumnTableView-Info.plist"; 302 | PRODUCT_NAME = "$(TARGET_NAME)"; 303 | WRAPPER_EXTENSION = app; 304 | }; 305 | name = Debug; 306 | }; 307 | BBF25B34139F20A800CE773F /* Release */ = { 308 | isa = XCBuildConfiguration; 309 | buildSettings = { 310 | ALWAYS_SEARCH_USER_PATHS = NO; 311 | COPY_PHASE_STRIP = YES; 312 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 313 | GCC_PREFIX_HEADER = "MultiColumnTableView/MultiColumnTableView-Prefix.pch"; 314 | INFOPLIST_FILE = "MultiColumnTableView/MultiColumnTableView-Info.plist"; 315 | PRODUCT_NAME = "$(TARGET_NAME)"; 316 | VALIDATE_PRODUCT = YES; 317 | WRAPPER_EXTENSION = app; 318 | }; 319 | name = Release; 320 | }; 321 | /* End XCBuildConfiguration section */ 322 | 323 | /* Begin XCConfigurationList section */ 324 | BBF25B0B139F20A800CE773F /* Build configuration list for PBXProject "MultiColumnTableView" */ = { 325 | isa = XCConfigurationList; 326 | buildConfigurations = ( 327 | BBF25B30139F20A800CE773F /* Debug */, 328 | BBF25B31139F20A800CE773F /* Release */, 329 | ); 330 | defaultConfigurationIsVisible = 0; 331 | defaultConfigurationName = Release; 332 | }; 333 | BBF25B32139F20A800CE773F /* Build configuration list for PBXNativeTarget "MultiColumnTableView" */ = { 334 | isa = XCConfigurationList; 335 | buildConfigurations = ( 336 | BBF25B33139F20A800CE773F /* Debug */, 337 | BBF25B34139F20A800CE773F /* Release */, 338 | ); 339 | defaultConfigurationIsVisible = 0; 340 | defaultConfigurationName = Release; 341 | }; 342 | /* End XCConfigurationList section */ 343 | }; 344 | rootObject = BBF25B08139F20A800CE773F /* Project object */; 345 | } 346 | -------------------------------------------------------------------------------- /MultiColumnTableView.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /MultiColumnTableView/EWHeaderHighlightLayer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011 Eli Wang 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 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell 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 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 | * IN THE SOFTWARE. 21 | */ 22 | 23 | 24 | #import 25 | #import 26 | 27 | @interface EWHeaderHighlightLayer : CALayer { 28 | 29 | } 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /MultiColumnTableView/EWHeaderHighlightLayer.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011 Eli Wang 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 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell 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 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 | * IN THE SOFTWARE. 21 | */ 22 | 23 | 24 | #import "EWHeaderHighlightLayer.h" 25 | 26 | 27 | @implementation EWHeaderHighlightLayer 28 | 29 | - (void)drawInContext:(CGContextRef)ctx 30 | { 31 | CGContextSetRGBStrokeColor(ctx, 0.0f, 1.0f, 0.0f, 1.0f); 32 | CGContextMoveToPoint(ctx, 0.0f, 0.0f); 33 | CGContextSetLineWidth(ctx, 4.0f); 34 | CGContextAddLineToPoint(ctx, self.frame.size.width, self.frame.size.height); 35 | CGContextStrokePath(ctx); 36 | } 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /MultiColumnTableView/EWMultiColumnTableView.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011 Eli Wang 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 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell 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 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 | * IN THE SOFTWARE. 21 | */ 22 | 23 | 24 | #import 25 | #import 26 | #import "EWMultiColumnTableViewContentBackgroundView.h" 27 | #import "EWMultiColumnTableViewDefaults.h" 28 | #import "EWMultiColumnTableViewBGScrollView.h" 29 | 30 | @protocol EWMultiColumnTableViewDataSource; 31 | 32 | typedef enum __EWMultiColumnTableViewColumnPosition { 33 | EWMultiColumnTableViewColumnPositionLeft, 34 | EWMultiColumnTableViewColumnPositionMiddle, 35 | EWMultiColumnTableViewColumnPositionRight 36 | } EWMultiColumnTableViewColumnPosition; 37 | 38 | 39 | @interface EWMultiColumnTableView : UIView { 40 | BOOL respondsToReuseIdAtIndexPath; 41 | BOOL respondsToNumberOfSections; 42 | 43 | BOOL respondsToHeightForCell; 44 | BOOL respondsToHeightForHeaderCell; 45 | BOOL respondsToLeftHeaderCell; 46 | BOOL respondsToWidthForHeaderCell; 47 | BOOL respondsToWidthForColumn; 48 | 49 | BOOL respondsToHeightForSectionHeaderCell; 50 | BOOL respondsToHeightForHeaderCellInSectionHeader; 51 | 52 | BOOL respondsToSetContentForHeaderCellAtRow; 53 | BOOL respondsToHeaderCellForColumn; 54 | BOOL respondsToSetContentForHeaderCellAtColumn; 55 | BOOL respondsToHeightForTopHeaderCell; 56 | 57 | NSInteger selectedColumn; 58 | 59 | EWMultiColumnTableViewBGScrollView *scrlView; 60 | UITableView *headerTblView; 61 | EWMultiColumnTableViewContentBackgroundView *tblView; 62 | 63 | // Keep if or not each section is folded. YES for folded, NO for expanded. 64 | NSMutableArray *sectionFoldingStatus; 65 | NSMutableArray *indexPathTable; 66 | 67 | UIView *tblViewHeader; 68 | 69 | CALayer *highlightColumnLayer; 70 | } 71 | 72 | @property (nonatomic, assign) id dataSource; 73 | 74 | @property (nonatomic, assign) CGFloat cellHeight; 75 | @property (nonatomic, assign) CGFloat cellWidth; 76 | @property (nonatomic, assign) CGFloat topHeaderHeight; 77 | @property (nonatomic, assign) CGFloat leftHeaderWidth; 78 | @property (nonatomic, assign) CGFloat sectionHeaderHeight; 79 | @property (nonatomic, assign) CGFloat boldSeperatorLineWidth; 80 | @property (nonatomic, assign) CGFloat normalSeperatorLineWidth; 81 | 82 | @property (nonatomic, retain) UIColor *boldSeperatorLineColor; 83 | @property (nonatomic, retain) UIColor *normalSeperatorLineColor; 84 | 85 | @property (nonatomic, retain) UIColor *leftHeaderBackgroundColor; 86 | @property (nonatomic, retain) UIColor *sectionHeaderBackgroundColor; 87 | 88 | @property (nonatomic, retain) UIColor *topHeaderBackgroundColor; 89 | 90 | @property (nonatomic, assign) BOOL sectionFoldedByDefault; 91 | @property (nonatomic, assign) BOOL sectionHeaderEnabled; 92 | 93 | - (void)reloadData; 94 | - (BOOL)sectionIsFolded:(NSInteger)section; 95 | 96 | - (void)scrollToColumn:(NSInteger)col position:(EWMultiColumnTableViewColumnPosition)pos animated:(BOOL)animated; 97 | 98 | @end 99 | 100 | 101 | 102 | @protocol EWMultiColumnTableViewDataSource 103 | 104 | - (UIView *)tableView:(EWMultiColumnTableView *)tableView cellForIndexPath:(NSIndexPath *)indexPath column:(NSInteger)col; 105 | - (void)tableView:(EWMultiColumnTableView *)tableView setContentForCell:(UIView *)cell indexPath:(NSIndexPath *)indexPath column:(NSInteger)col; 106 | - (NSInteger)tableView:(EWMultiColumnTableView *)tableView numberOfRowsInSection:(NSInteger)section; 107 | - (NSInteger)numberOfColumnsInTableView:(EWMultiColumnTableView *)tableView; 108 | 109 | 110 | @optional 111 | 112 | - (CGFloat)tableView:(EWMultiColumnTableView *)tableView heightForCellAtIndexPath:(NSIndexPath *)indexPath column:(NSInteger)column; 113 | 114 | - (CGFloat)tableView:(EWMultiColumnTableView *)tableView widthForColumn:(NSInteger)column; 115 | 116 | // If not implemented, a default cell id will be given. 117 | - (NSString *)tableView:(EWMultiColumnTableView *)tableView reuseIdForIndexPath:(NSIndexPath *)multiColIndexPath; 118 | 119 | #pragma mark - Header Cell 120 | #pragma mark height and width 121 | - (CGFloat)tableView:(EWMultiColumnTableView *)tableView heightForHeaderCellAtIndexPath:(NSIndexPath *)indexPath; 122 | // Top header row 123 | - (CGFloat)heightForHeaderCellOfTableView:(EWMultiColumnTableView *)tableView; 124 | // Left header column 125 | - (CGFloat)widthForHeaderCellOfTableView:(EWMultiColumnTableView *)tableView; 126 | 127 | #pragma mark cell and content 128 | // Create a new header cell in left 129 | - (UIView *)tableView:(EWMultiColumnTableView *)tableView headerCellForIndexPath:(NSIndexPath *)indexPath; 130 | // set content for a resuable header cell 131 | - (void)tableView:(EWMultiColumnTableView *)tableView setContentForHeaderCell:(UIView *)cell atIndexPath:(NSIndexPath *)multiColIndexPath; 132 | 133 | - (UIView *)tableView:(EWMultiColumnTableView *)tableView headerCellForColumn:(NSInteger)col; 134 | - (void)tableView:(EWMultiColumnTableView *)tableView setContentForHeaderCell:(UIView *)cell atColumn:(NSInteger)col; 135 | - (UIView *)topleftHeaderCellOfTableView:(EWMultiColumnTableView *)tableView; 136 | 137 | 138 | 139 | 140 | #pragma mark - Action callback 141 | - (void)tableView:(EWMultiColumnTableView *)tableView swapDataOfColumn:(NSInteger)col1 andColumn:(NSInteger)col2; 142 | 143 | 144 | 145 | 146 | #pragma mark - Section and section header 147 | 148 | - (NSInteger)numberOfSectionsInTableView:(EWMultiColumnTableView *)tableView; 149 | 150 | #pragma mark section header normal cell 151 | // new cell 152 | - (UIView *)tableView:(EWMultiColumnTableView *)tableView sectionHeaderCellForSection:(NSInteger)section column:(NSInteger)col; 153 | // set content 154 | - (void)tableView:(EWMultiColumnTableView *)tableView setContentForSectionHeaderCell:(UIView *)cell section:(NSInteger)section column:(NSInteger)col; 155 | // height 156 | - (CGFloat)tableView:(EWMultiColumnTableView *)tableView heightForSectionHeaderCellAtSection:(NSInteger)section column:(NSInteger)col; 157 | 158 | #pragma mark table header in section header 159 | // new cell 160 | - (UIView *)tableView:(EWMultiColumnTableView *)tableView headerCellInSectionHeaderForSection:(NSInteger)section; 161 | - (void)tableView:(EWMultiColumnTableView *)tableView setContentForHeaderCellInSectionHeader:(UIView *)cell AtSection:(NSInteger)section; 162 | // height 163 | - (CGFloat)tableView:(EWMultiColumnTableView *)tableView heightForHeaderCellInSectionHeaderAtSection:(NSInteger)section; 164 | 165 | @end 166 | -------------------------------------------------------------------------------- /MultiColumnTableView/EWMultiColumnTableView.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011 Eli Wang 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 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell 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 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 | * IN THE SOFTWARE. 21 | */ 22 | 23 | 24 | #import "EWMultiColumnTableView.h" 25 | #import 26 | #import "EWHeaderHighlightLayer.h" 27 | #import "EWMultiColumnTableViewCell.h" 28 | #import "UIView+AddLine.h" 29 | 30 | 31 | #define HeaderCellTag -1 32 | #define AddHeightTo(v, h) { CGRect f = v.frame; f.size.height += h; v.frame = f; } 33 | 34 | @interface EWMultiColumnTableView() 35 | 36 | - (void)adjustWidth; 37 | - (void)setupHeaderTblView; 38 | - (void)rebuildIndexPathTable; 39 | - (void)orientationChanged:(NSNotification *)notification; 40 | - (void)highlightColumn:(NSInteger)col; 41 | - (void)clearHighlightColumn; 42 | - (void)reset; 43 | 44 | - (void)toggleFoldOfSection:(NSInteger)section withRowNumber:(NSInteger)row rowAnimation:(UITableViewRowAnimation)animation; 45 | 46 | - (UITableViewCell *)tblView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath; 47 | - (UITableViewCell *)tblView:(UITableView *)tableView regularCellForRowAtIndexPath:(NSIndexPath *)multiColIndexPath; 48 | - (UITableViewCell *)tblView:(UITableView *)tableView sectionHeaderCellForRowAtIndexPath:(NSIndexPath *)multiColIndexPath; 49 | - (UITableViewCell *)headerTblView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)multiColIndexPath; 50 | 51 | - (NSInteger)numberOfSections; 52 | - (CGFloat)heightForCellAtIndexPath:(NSIndexPath *)indexPath column:(NSInteger)column; 53 | - (CGFloat)widthForColumn:(NSInteger)column; 54 | - (CGFloat)heightForHeaderCellAtIndexPath:(NSIndexPath *)indexPath; 55 | - (CGFloat)heightForTopHeaderCell; 56 | - (CGFloat)widthForLeftHeaderCell; 57 | - (CGFloat)heightForSectionHeaderCellAtSection:(NSInteger)section column:(NSInteger)col; 58 | - (CGFloat)heightForHeaderCellInSectionHeaderAtSection:(NSInteger)section; 59 | 60 | 61 | - (CGRect)highlightRectForColumn:(NSInteger)col; 62 | 63 | 64 | - (void)columnLongPressed:(UILongPressGestureRecognizer *)recognizer; 65 | 66 | - (NSInteger)columnOfPointInTblView:(CGPoint)point; 67 | - (NSMutableArray *)indexPathsOfSection:(NSInteger)section headerRow:(NSInteger)row; 68 | - (void)swapColumn:(NSInteger)col1 andColumn:(NSInteger)col2; 69 | 70 | @end 71 | 72 | 73 | 74 | 75 | 76 | 77 | @implementation EWMultiColumnTableView 78 | 79 | @synthesize dataSource; 80 | @synthesize cellHeight, cellWidth, topHeaderHeight, leftHeaderWidth, sectionHeaderHeight; 81 | @synthesize leftHeaderBackgroundColor, sectionHeaderBackgroundColor, sectionFoldedByDefault; 82 | @synthesize sectionHeaderEnabled; 83 | 84 | @synthesize normalSeperatorLineColor, normalSeperatorLineWidth, boldSeperatorLineColor, boldSeperatorLineWidth; 85 | @synthesize topHeaderBackgroundColor; 86 | 87 | 88 | #pragma constructors and dealloc 89 | 90 | - (id)initWithFrame:(CGRect)frame 91 | { 92 | if ((self = [super initWithFrame:frame])) { 93 | 94 | self.layer.borderColor = [[UIColor colorWithWhite:EWMultiColumnTable_BorderColorGray alpha:1.0f] CGColor]; 95 | self.layer.cornerRadius = EWMultiColumnTable_CornerRadius; 96 | self.layer.borderWidth = EWMultiColumnTable_BorderWidth; 97 | self.clipsToBounds = YES; 98 | self.backgroundColor = [UIColor clearColor]; 99 | self.contentMode = UIViewContentModeRedraw; 100 | 101 | cellHeight = EWMultiColumnTable_DefaultCellHeight; 102 | cellWidth = EWMultiColumnTable_DefaultCellWidth; 103 | topHeaderHeight = EWMultiColumnTable_DefaultTopHeaderHeight; 104 | leftHeaderWidth = EWMultiColumnTable_DefaultLeftHeaderWidth; 105 | sectionHeaderHeight = EWMultiColumnTable_DefaultSectionHeaderHeight; 106 | 107 | boldSeperatorLineWidth = EWMultiColumnTable_BoldLineWidth; 108 | normalSeperatorLineWidth = EWMultiColumnTable_NormalLineWidth; 109 | self.boldSeperatorLineColor = [UIColor colorWithWhite:EWMultiColumnTable_LineGray alpha:1.0f]; 110 | self.normalSeperatorLineColor = [UIColor colorWithWhite:EWMultiColumnTable_LineGray alpha:1.0f]; 111 | 112 | self.leftHeaderBackgroundColor = [UIColor colorWithWhite:249.0f/255.0f alpha:1.0f]; 113 | self.sectionHeaderBackgroundColor = [UIColor colorWithWhite:241.0f/255.0f alpha:1.0f]; 114 | self.topHeaderBackgroundColor = [UIColor whiteColor]; 115 | sectionFoldedByDefault = NO; 116 | 117 | 118 | selectedColumn = -1; 119 | sectionFoldingStatus = [[NSMutableArray alloc] initWithCapacity:10]; 120 | 121 | scrlView = [[EWMultiColumnTableViewBGScrollView alloc] initWithFrame:self.bounds]; 122 | scrlView.parent = self; 123 | scrlView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; 124 | [self addSubview:scrlView]; 125 | 126 | tblView = [[EWMultiColumnTableViewContentBackgroundView alloc] initWithFrame:scrlView.bounds]; 127 | tblView.dataSource = self; 128 | tblView.delegate = self; 129 | tblView.autoresizingMask = UIViewAutoresizingFlexibleHeight; 130 | tblView.separatorStyle = UITableViewCellSeparatorStyleNone; 131 | tblView.backgroundColor = [UIColor clearColor]; 132 | [scrlView addSubview:tblView]; 133 | 134 | UILongPressGestureRecognizer *recognizer = [[[UILongPressGestureRecognizer alloc] 135 | initWithTarget:self action:@selector(columnLongPressed:)] autorelease]; 136 | recognizer.minimumPressDuration = 1.0; 137 | [tblView addGestureRecognizer:recognizer]; 138 | 139 | NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; 140 | [center addObserver:self selector:@selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:nil]; 141 | } 142 | 143 | return self; 144 | } 145 | 146 | - (void)dealloc 147 | { 148 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 149 | [tblView release]; 150 | [headerTblView release]; 151 | [scrlView release]; 152 | [sectionFoldingStatus release]; 153 | [indexPathTable release]; 154 | [highlightColumnLayer release]; 155 | [tblViewHeader release]; 156 | 157 | [leftHeaderBackgroundColor release]; 158 | [sectionHeaderBackgroundColor release]; 159 | [normalSeperatorLineColor release]; 160 | [boldSeperatorLineColor release]; 161 | [topHeaderBackgroundColor release]; 162 | [super dealloc]; 163 | } 164 | 165 | - (void)drawRect:(CGRect)rect 166 | { 167 | [super drawRect:rect]; 168 | CGContextRef context = UIGraphicsGetCurrentContext(); 169 | 170 | CGContextSetLineWidth(context, boldSeperatorLineWidth); 171 | CGContextSetAllowsAntialiasing(context, 0); 172 | 173 | CGContextSetStrokeColorWithColor(context, [boldSeperatorLineColor CGColor]); 174 | 175 | if (respondsToLeftHeaderCell) { 176 | CGFloat x = [self widthForLeftHeaderCell] + boldSeperatorLineWidth / 2.0f; 177 | CGContextMoveToPoint(context, x, 0.0f); 178 | CGContextAddLineToPoint(context, x, self.frame.size.height); 179 | } 180 | CGContextStrokePath(context); 181 | 182 | 183 | } 184 | 185 | #pragma mark - Methods 186 | 187 | - (void)reloadData 188 | { 189 | [self reset]; 190 | 191 | 192 | [headerTblView reloadData]; 193 | [tblView reloadData]; 194 | [self adjustWidth]; 195 | } 196 | 197 | - (BOOL)sectionIsFolded:(NSInteger)section 198 | { 199 | return [[sectionFoldingStatus objectAtIndex:section] boolValue]; 200 | } 201 | 202 | - (void)scrollToColumn:(NSInteger)col position:(EWMultiColumnTableViewColumnPosition)pos animated:(BOOL)animated 203 | { 204 | CGFloat x = 0.0f; 205 | 206 | for (int i = 0; i < col; i++) { 207 | x += [self widthForColumn:i] + normalSeperatorLineWidth; 208 | } 209 | 210 | switch (pos) { 211 | case EWMultiColumnTableViewColumnPositionMiddle: 212 | x -= (scrlView.bounds.size.width - (2 * normalSeperatorLineWidth + [self widthForColumn:col])) / 2; 213 | if (x < 0.0f) x = 0.0f; 214 | break; 215 | case EWMultiColumnTableViewColumnPositionRight: 216 | x -= scrlView.bounds.size.width - (2 * normalSeperatorLineWidth + [self widthForColumn:col]); 217 | if (x < 0.0f) x = 0.0f; 218 | break; 219 | default: 220 | break; 221 | 222 | } 223 | 224 | [scrlView setContentOffset:CGPointMake(x, 0) animated:animated]; 225 | } 226 | 227 | #pragma mark - Properties 228 | 229 | - (void)setDataSource:(id)dataSource_ 230 | { 231 | if (dataSource != dataSource_) { 232 | dataSource = dataSource_; 233 | 234 | respondsToReuseIdAtIndexPath = [dataSource_ respondsToSelector:@selector(tableView:reuseIdForIndexPath:)]; 235 | respondsToNumberOfSections = [dataSource_ respondsToSelector:@selector(numberOfSectionsInTableView:)]; 236 | 237 | respondsToHeightForCell = [dataSource_ respondsToSelector:@selector(tableView:heightForCellAtIndexPath:column:)]; 238 | respondsToLeftHeaderCell = [dataSource_ respondsToSelector:@selector(tableView:headerCellForIndexPath:)]; 239 | respondsToHeightForHeaderCell = [dataSource_ respondsToSelector:@selector(tableView:heightForHeaderCellAtIndexPath:)]; 240 | respondsToWidthForHeaderCell = [dataSource_ respondsToSelector:@selector(widthForHeaderCellOfTableView:)]; 241 | respondsToSetContentForHeaderCellAtRow = [dataSource_ respondsToSelector:@selector(tableView:setContentForHeaderCell:atRow:)]; 242 | respondsToHeaderCellForColumn = [dataSource_ respondsToSelector:@selector(tableView:headerCellForColumn:)]; 243 | respondsToSetContentForHeaderCellAtColumn = [dataSource_ respondsToSelector:@selector(tableView:setContentForHeaderCell:atColumn:)]; 244 | respondsToWidthForColumn = [dataSource_ respondsToSelector:@selector(tableView:widthForColumn:)]; 245 | respondsToHeightForTopHeaderCell = [dataSource_ respondsToSelector:@selector(heightForHeaderCellOfTableView:)]; 246 | respondsToHeightForSectionHeaderCell = [dataSource_ respondsToSelector:@selector(tableView:heightForSectionHeaderCellAtSection:column:)]; 247 | respondsToHeightForHeaderCellInSectionHeader = [dataSource_ respondsToSelector:@selector(tableView:heightForHeaderCellInSectionHeaderAtSection:)]; 248 | 249 | // set contentSize of the scrollView and the width of the tableView 250 | [self adjustWidth]; 251 | 252 | // Initialize sectionFoldingStatus 253 | [sectionFoldingStatus release]; 254 | sectionFoldingStatus = [[NSMutableArray alloc] initWithCapacity:[self numberOfSections]]; 255 | for (int i = 0; i < [self numberOfSections]; i++) { 256 | [sectionFoldingStatus addObject:[NSNumber numberWithBool:sectionFoldedByDefault]]; 257 | } 258 | 259 | [self reset]; 260 | 261 | if (respondsToLeftHeaderCell) 262 | [self setupHeaderTblView]; 263 | 264 | } 265 | } 266 | 267 | #pragma mark - UITableViewDataSource & UITableViewDelegate 268 | 269 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 270 | { 271 | NSInteger numOfRows = 0; 272 | NSInteger numOfSec = [self numberOfSections]; 273 | 274 | 275 | for (int i = 0; i < numOfSec; i++) { 276 | if (sectionHeaderEnabled) 277 | numOfRows++; 278 | 279 | if (!sectionHeaderEnabled || ![[sectionFoldingStatus objectAtIndex:i] boolValue]) 280 | numOfRows += [dataSource tableView:self numberOfRowsInSection:i]; 281 | } 282 | 283 | return numOfRows; 284 | } 285 | 286 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 287 | { 288 | if (tableView == tblView) { 289 | return [self tblView:tableView cellForRowAtIndexPath:indexPath]; 290 | } else { 291 | return [self headerTblView:tableView cellForRowAtIndexPath:indexPath]; 292 | } 293 | } 294 | 295 | - (UITableViewCell *)tblView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 296 | { 297 | NSIndexPath *multiColIndexPath = [indexPathTable objectAtIndex:indexPath.row]; 298 | 299 | if (sectionHeaderEnabled && [multiColIndexPath length] == 1) 300 | return [self tblView:tableView sectionHeaderCellForRowAtIndexPath:multiColIndexPath]; 301 | else 302 | return [self tblView:tableView regularCellForRowAtIndexPath:multiColIndexPath]; 303 | } 304 | 305 | - (UITableViewCell *)tblView:(UITableView *)tableView regularCellForRowAtIndexPath:(NSIndexPath *)multiColIndexPath 306 | { 307 | NSInteger numOfCols = [dataSource numberOfColumnsInTableView:self]; 308 | 309 | static NSString *CellID; 310 | 311 | if (respondsToReuseIdAtIndexPath) 312 | CellID = [dataSource tableView:self reuseIdForIndexPath:multiColIndexPath] ?: @"MultiColumnCell"; 313 | else 314 | CellID = @"MultiColumnCell"; 315 | 316 | EWMultiColumnTableViewCell *cell = (EWMultiColumnTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellID]; 317 | 318 | if (cell == nil) { 319 | cell = [[[EWMultiColumnTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellID] autorelease]; 320 | cell.selectionStyle = UITableViewCellSelectionStyleNone; 321 | [cell addBottomLineWithWidth:normalSeperatorLineWidth color:normalSeperatorLineColor]; 322 | } 323 | 324 | NSInteger columnsDiff = numOfCols - [[cell columnCells] count]; 325 | 326 | if (columnsDiff > 0) { 327 | // Add the grid cells - call the delegate method to init the grid cells 328 | CGFloat x = 0.0f; 329 | UIView *lastCol = [[cell columnCells] lastObject]; 330 | if (lastCol) x = lastCol.frame.origin.x + lastCol.frame.size.width; 331 | 332 | for (int i = 0; i < columnsDiff; i++) { 333 | UIView *gridCell = [dataSource tableView:self cellForIndexPath:multiColIndexPath column:i]; 334 | CGRect f = gridCell.frame; 335 | f.origin.x += x; 336 | gridCell.frame = f; 337 | [cell.contentView addSubview:gridCell]; 338 | 339 | CGFloat colWidth = [self widthForColumn:i]; 340 | 341 | x += colWidth + normalSeperatorLineWidth; 342 | [[cell columnCells] addObject:gridCell]; 343 | } 344 | } else if (columnsDiff < 0) { 345 | columnsDiff = -columnsDiff; 346 | for (int i = 0; i < columnsDiff; i++) { 347 | [[[cell columnCells] lastObject] removeFromSuperview]; 348 | [[cell columnCells] removeLastObject]; 349 | } 350 | } 351 | 352 | 353 | // call delegate method to set the cells of the other columns 354 | 355 | for (int i = 0; i < numOfCols; i++) { 356 | [dataSource tableView:self setContentForCell:[[cell columnCells] objectAtIndex:i] 357 | indexPath:multiColIndexPath column:i]; 358 | } 359 | 360 | AddHeightTo(cell, normalSeperatorLineWidth); 361 | 362 | return cell; 363 | } 364 | 365 | - (UITableViewCell *)tblView:(UITableView *)tableView sectionHeaderCellForRowAtIndexPath:(NSIndexPath *)multiColIndexPath 366 | { 367 | NSInteger numOfCols = [dataSource numberOfColumnsInTableView:self]; 368 | NSInteger section = [multiColIndexPath indexAtPosition:0]; 369 | 370 | static NSString *CellID = @"SectionHeaderCell"; 371 | 372 | EWMultiColumnTableViewCell *cell = (EWMultiColumnTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellID]; 373 | 374 | if (cell == nil) { 375 | cell = [[[EWMultiColumnTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellID] autorelease]; 376 | cell.selectionStyle = UITableViewCellSelectionStyleNone; 377 | cell.contentView.backgroundColor = sectionHeaderBackgroundColor; 378 | [cell addBottomLineWithWidth:normalSeperatorLineWidth color:normalSeperatorLineColor]; 379 | } 380 | 381 | NSInteger columnsDiff = numOfCols - [[cell columnCells] count]; 382 | 383 | if (columnsDiff > 0) { 384 | // Add the grid cells - call the delegate method to init the grid cells 385 | CGFloat x = 0.0f; 386 | UIView *lastCol = [[cell columnCells] lastObject]; 387 | if (lastCol) x = lastCol.frame.origin.x + lastCol.frame.size.width; 388 | 389 | for (int i = 0; i < columnsDiff; i++) { 390 | UIView *gridCell = [dataSource tableView:self sectionHeaderCellForSection:section column:i]; 391 | 392 | CGRect f = gridCell.frame; 393 | f.origin.x += x; 394 | gridCell.frame = f; 395 | [cell.contentView addSubview:gridCell]; 396 | 397 | CGFloat colWidth = [self widthForColumn:i]; 398 | 399 | x += colWidth + normalSeperatorLineWidth; 400 | [[cell columnCells] addObject:gridCell]; 401 | } 402 | } else if (columnsDiff < 0) { 403 | columnsDiff = -columnsDiff; 404 | for (int i = 0; i < columnsDiff; i++) { 405 | [[[cell columnCells] lastObject] removeFromSuperview]; 406 | [[cell columnCells] removeLastObject]; 407 | } 408 | } 409 | 410 | 411 | // call delegate method to set the cells of the other columns 412 | 413 | for (int i = 0; i < numOfCols; i++) { 414 | [dataSource tableView:self setContentForSectionHeaderCell:[[cell columnCells] objectAtIndex:i] 415 | section:section column:i]; 416 | } 417 | 418 | AddHeightTo(cell, normalSeperatorLineWidth); 419 | 420 | return cell; 421 | } 422 | 423 | - (UITableViewCell *)headerTblView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 424 | { 425 | NSIndexPath *multiColIndexPath = [indexPathTable objectAtIndex:indexPath.row]; 426 | static NSString *CellID; 427 | if (sectionHeaderEnabled && [multiColIndexPath length] == 1) 428 | CellID = @"HeaderCellInSectionHeader"; 429 | else 430 | CellID = @"HeaderCell"; 431 | 432 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellID]; 433 | 434 | if (cell == nil) { 435 | cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellID] autorelease]; 436 | cell.selectionStyle = UITableViewCellSelectionStyleNone; 437 | 438 | UIView *headerCellView; 439 | 440 | if (sectionHeaderEnabled && [multiColIndexPath length] == 1) { 441 | headerCellView = [dataSource tableView:self headerCellInSectionHeaderForSection:[multiColIndexPath indexAtPosition:0]]; 442 | cell.contentView.backgroundColor = sectionHeaderBackgroundColor; 443 | } else { 444 | headerCellView = [dataSource tableView:self headerCellForIndexPath:indexPath]; 445 | } 446 | 447 | headerCellView.tag = HeaderCellTag; 448 | [cell.contentView addSubview:headerCellView]; 449 | [cell addBottomLineWithWidth:normalSeperatorLineWidth color:normalSeperatorLineColor]; 450 | } 451 | 452 | if (sectionHeaderEnabled && [multiColIndexPath length] == 1) 453 | [dataSource tableView:self setContentForHeaderCellInSectionHeader:[cell viewWithTag:HeaderCellTag] 454 | AtSection:[multiColIndexPath indexAtPosition:0]]; 455 | else 456 | [dataSource tableView:self setContentForHeaderCell:[cell viewWithTag:HeaderCellTag] 457 | atIndexPath:multiColIndexPath]; 458 | 459 | AddHeightTo(cell, normalSeperatorLineWidth); 460 | 461 | return cell; 462 | } 463 | 464 | - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 465 | { 466 | NSIndexPath *multiColIndexPath = [indexPathTable objectAtIndex:indexPath.row]; 467 | 468 | if (sectionHeaderEnabled && [multiColIndexPath length] == 1) { 469 | // Calculate section header 470 | 471 | NSInteger section = [multiColIndexPath indexAtPosition:0]; 472 | CGFloat height = [self heightForHeaderCellInSectionHeaderAtSection:section]; 473 | 474 | // calculate the height of the cells in this row 475 | NSInteger numOfCols = [dataSource numberOfColumnsInTableView:self]; 476 | for (int i = 0; i < numOfCols; i++) { 477 | // call delegate method to calculate the individual cell 478 | CGFloat h = [self heightForSectionHeaderCellAtSection:section column:i]; 479 | 480 | if (h > height) height = h; 481 | } 482 | 483 | // return the Maximum of them. 484 | return height + normalSeperatorLineWidth; 485 | 486 | } else { 487 | // Calculate normal row 488 | 489 | CGFloat height = [self heightForHeaderCellAtIndexPath:multiColIndexPath]; 490 | 491 | // calculate the height of the cells in this row 492 | NSInteger numOfCols = [dataSource numberOfColumnsInTableView:self]; 493 | for (int i = 0; i < numOfCols; i++) { 494 | // call delegate method to calculate the individual cell 495 | CGFloat h = [self heightForCellAtIndexPath:multiColIndexPath column:i]; 496 | 497 | if (h > height) height = h; 498 | } 499 | 500 | // return the Maximum of them. 501 | return height + normalSeperatorLineWidth; 502 | } 503 | } 504 | 505 | - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section 506 | { 507 | if (tableView == tblView) { 508 | [tblViewHeader release]; 509 | tblViewHeader = [[UIView alloc] initWithFrame:CGRectZero]; 510 | tblViewHeader.clipsToBounds = YES; 511 | tblViewHeader.backgroundColor = [UIColor clearColor]; 512 | 513 | NSInteger cols = [dataSource numberOfColumnsInTableView:self]; 514 | CGFloat x = 0.0f, height = 0.0f; 515 | 516 | for (int i = 0; i < cols; i++) { 517 | UIView *headerCell = [dataSource tableView:self headerCellForColumn:i]; 518 | CGRect f = headerCell.frame; 519 | f.origin.x = x; 520 | headerCell.frame = f; 521 | [tblViewHeader addSubview:headerCell]; 522 | height = MAX(height, f.size.height); 523 | 524 | x += [self widthForColumn:i] + normalSeperatorLineWidth; 525 | } 526 | 527 | CGRect f = tblViewHeader.frame; 528 | CGFloat width = MAX(x - normalSeperatorLineWidth, tblView.frame.size.width); 529 | f.size = CGSizeMake(width, height); 530 | tblViewHeader.frame = f; 531 | tblViewHeader.backgroundColor = self.topHeaderBackgroundColor; 532 | 533 | [tblViewHeader addBottomLineWithWidth:boldSeperatorLineWidth color:boldSeperatorLineColor]; 534 | 535 | return tblViewHeader; 536 | } else { 537 | if ([dataSource respondsToSelector:@selector(topleftHeaderCellOfTableView:)]) { 538 | UIView *header = [dataSource topleftHeaderCellOfTableView:self]; 539 | 540 | UIView *container = [[[UIView alloc] initWithFrame:header.frame] autorelease]; 541 | CGRect f = container.frame; 542 | f.size.height = [self heightForTopHeaderCell]; 543 | container.frame = f; 544 | 545 | [container addSubview:header]; 546 | [container addBottomLineWithWidth:boldSeperatorLineWidth color:boldSeperatorLineColor]; 547 | 548 | return container; 549 | } else { 550 | return [[[UIView alloc] initWithFrame:CGRectZero] autorelease]; 551 | } 552 | } 553 | } 554 | 555 | - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section 556 | { 557 | return [self heightForTopHeaderCell] + boldSeperatorLineWidth; 558 | } 559 | 560 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 561 | { 562 | if (tableView == headerTblView) { 563 | NSIndexPath *multiColIndexPath = [indexPathTable objectAtIndex:indexPath.row]; 564 | if (sectionHeaderEnabled && [multiColIndexPath length] == 1) { 565 | [self toggleFoldOfSection:[multiColIndexPath indexAtPosition:0] 566 | withRowNumber:indexPath.row rowAnimation:UITableViewRowAnimationTop]; 567 | } 568 | 569 | } 570 | } 571 | 572 | #pragma mark - UIScrollViewDelegate 573 | 574 | - (void)scrollViewDidScroll:(UIScrollView *)scrollView 575 | { 576 | UIScrollView *target; 577 | if (scrollView == tblView) 578 | target = headerTblView; 579 | else 580 | target = tblView; 581 | 582 | target.contentOffset = scrollView.contentOffset; 583 | } 584 | 585 | 586 | 587 | #pragma mark - Private Methods 588 | 589 | #pragma mark Procedures 590 | 591 | - (void)reset 592 | { 593 | NSInteger numOfSec = [self numberOfSections]; 594 | if (sectionHeaderEnabled && [sectionFoldingStatus count] == 0) { 595 | for (int i = 0; i < numOfSec; i++) { 596 | [sectionFoldingStatus addObject:[NSNumber numberWithBool:sectionFoldedByDefault]]; 597 | } 598 | } 599 | 600 | [indexPathTable release]; 601 | indexPathTable = [[NSMutableArray alloc] initWithCapacity:numOfSec * 5]; 602 | [self rebuildIndexPathTable]; 603 | [scrlView redraw]; 604 | 605 | } 606 | 607 | - (void)adjustWidth 608 | { 609 | CGFloat width = 0.0f; 610 | NSInteger cols = [dataSource numberOfColumnsInTableView:self]; 611 | for (int i = 0; i < cols; i++) { 612 | width += [self widthForColumn:i] + normalSeperatorLineWidth; 613 | } 614 | 615 | width -= normalSeperatorLineWidth; 616 | scrlView.contentSize = CGSizeMake(width, 0.0f); 617 | 618 | CGRect f = tblView.frame; 619 | f.size.width = MAX(self.frame.size.width - [self widthForLeftHeaderCell], width); 620 | tblView.frame = f; 621 | } 622 | 623 | - (void)setupHeaderTblView 624 | { 625 | CGFloat headerCellWidth = [self widthForLeftHeaderCell]; 626 | 627 | [headerTblView removeFromSuperview]; 628 | [headerTblView release]; 629 | headerTblView = [[UITableView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, headerCellWidth, self.frame.size.height)]; 630 | headerTblView.autoresizingMask = UIViewAutoresizingFlexibleHeight; 631 | headerTblView.delegate = self; 632 | headerTblView.dataSource = self; 633 | headerTblView.separatorStyle = UITableViewCellSeparatorStyleNone; 634 | headerTblView.showsVerticalScrollIndicator = NO; 635 | headerTblView.backgroundColor = leftHeaderBackgroundColor; 636 | [self addSubview:headerTblView]; 637 | 638 | scrlView.frame = CGRectMake(headerCellWidth + boldSeperatorLineWidth, 0.0f, 639 | self.frame.size.width - headerCellWidth - boldSeperatorLineWidth, self.frame.size.height); 640 | } 641 | 642 | - (void)rebuildIndexPathTable 643 | { 644 | [indexPathTable removeAllObjects]; 645 | 646 | NSInteger numOfSec = [self numberOfSections]; 647 | for (int i = 0; i < numOfSec; i++) { 648 | if (sectionHeaderEnabled) 649 | [indexPathTable addObject:[NSIndexPath indexPathWithIndex:i]]; 650 | 651 | if (!sectionHeaderEnabled || ![[sectionFoldingStatus objectAtIndex:i] boolValue]) { 652 | NSInteger numOfRows = [dataSource tableView:self numberOfRowsInSection:i]; 653 | for (int j = 0; j < numOfRows; j++) { 654 | [indexPathTable addObject:[NSIndexPath indexPathForRow:j inSection:i]]; 655 | } 656 | } 657 | } 658 | 659 | } 660 | 661 | - (void)swapColumn:(NSInteger)col1 andColumn:(NSInteger)col2 662 | { 663 | [dataSource tableView:self swapDataOfColumn:col1 andColumn:col2]; 664 | [tblView reloadData]; 665 | [scrlView redraw]; 666 | } 667 | 668 | - (void)toggleFoldOfSection:(NSInteger)section withRowNumber:(NSInteger)row rowAnimation:(UITableViewRowAnimation)animation 669 | { 670 | @synchronized(self) { 671 | BOOL folded = [[sectionFoldingStatus objectAtIndex:section] boolValue]; 672 | [sectionFoldingStatus replaceObjectAtIndex:section withObject:[NSNumber numberWithBool:!folded]]; 673 | 674 | NSMutableArray *indexPaths = [self indexPathsOfSection: section headerRow:row]; 675 | [self rebuildIndexPathTable]; 676 | 677 | [tblView beginUpdates]; 678 | [headerTblView beginUpdates]; 679 | if (folded) { 680 | [tblView insertRowsAtIndexPaths:indexPaths withRowAnimation:animation]; 681 | [headerTblView insertRowsAtIndexPaths:indexPaths withRowAnimation:animation]; 682 | } else { 683 | [tblView deleteRowsAtIndexPaths:indexPaths withRowAnimation:animation]; 684 | [headerTblView deleteRowsAtIndexPaths:indexPaths withRowAnimation:animation]; 685 | } 686 | [tblView endUpdates]; 687 | [headerTblView endUpdates]; 688 | } 689 | 690 | } 691 | 692 | - (void)highlightColumn:(NSInteger)col 693 | { 694 | if (highlightColumnLayer == nil) { 695 | highlightColumnLayer = [[CALayer alloc] init]; 696 | highlightColumnLayer.borderColor = [[UIColor colorWithRed:232.0f/255.0f green:142.0f/255.0f blue:20.0f/255.0f alpha:1.0f] CGColor]; 697 | highlightColumnLayer.borderWidth = ColumnHighlightWidth; 698 | highlightColumnLayer.shadowRadius = 5.0f; 699 | highlightColumnLayer.shadowOpacity = 0.5f; 700 | [self.layer addSublayer:highlightColumnLayer]; 701 | } 702 | 703 | 704 | [CATransaction begin]; 705 | [CATransaction setValue: (id) kCFBooleanTrue forKey: kCATransactionDisableActions]; 706 | highlightColumnLayer.frame = [self highlightRectForColumn:selectedColumn]; 707 | [CATransaction commit]; 708 | 709 | 710 | } 711 | 712 | - (void)clearHighlightColumn 713 | { 714 | [highlightColumnLayer removeFromSuperlayer]; 715 | [highlightColumnLayer release]; 716 | highlightColumnLayer = nil; 717 | } 718 | 719 | #pragma mark Computations 720 | 721 | 722 | - (CGFloat)heightForCellAtIndexPath:(NSIndexPath *)indexPath column:(NSInteger)column 723 | { 724 | if (respondsToHeightForCell) 725 | return [dataSource tableView:self heightForCellAtIndexPath:indexPath column:column]; 726 | else 727 | return cellHeight; 728 | } 729 | 730 | - (CGFloat)widthForColumn:(NSInteger)column 731 | { 732 | if (respondsToWidthForColumn) 733 | return [dataSource tableView:self widthForColumn:column]; 734 | else 735 | return cellWidth; 736 | } 737 | 738 | - (CGFloat)heightForHeaderCellAtIndexPath:(NSIndexPath *)indexPath; 739 | { 740 | if (respondsToHeightForHeaderCell) 741 | return [dataSource tableView:self heightForHeaderCellAtIndexPath:indexPath]; 742 | else 743 | return sectionHeaderHeight; 744 | } 745 | 746 | - (CGFloat)heightForTopHeaderCell 747 | { 748 | if (respondsToHeightForTopHeaderCell) 749 | return [dataSource heightForHeaderCellOfTableView:self]; 750 | else 751 | return topHeaderHeight; 752 | } 753 | 754 | - (CGFloat)widthForLeftHeaderCell 755 | { 756 | if (respondsToLeftHeaderCell) { 757 | if (respondsToWidthForHeaderCell) 758 | return [dataSource widthForHeaderCellOfTableView:self]; 759 | else 760 | return leftHeaderWidth; 761 | } else { 762 | return 0.0f; 763 | } 764 | } 765 | 766 | - (CGFloat)heightForSectionHeaderCellAtSection:(NSInteger)section column:(NSInteger)col 767 | { 768 | if (respondsToHeightForSectionHeaderCell) 769 | return [dataSource tableView:self heightForSectionHeaderCellAtSection:section column:col]; 770 | else 771 | return sectionHeaderHeight; 772 | } 773 | 774 | - (CGFloat)heightForHeaderCellInSectionHeaderAtSection:(NSInteger)section 775 | { 776 | if (respondsToHeightForHeaderCellInSectionHeader) 777 | return [dataSource tableView:self heightForHeaderCellInSectionHeaderAtSection:section]; 778 | else 779 | return cellHeight; 780 | } 781 | 782 | 783 | - (NSInteger)numberOfSections 784 | { 785 | if (respondsToNumberOfSections) 786 | return [dataSource numberOfSectionsInTableView:self]; 787 | else 788 | return 1; 789 | } 790 | 791 | - (NSInteger)columnOfPointInTblView:(CGPoint)point 792 | { 793 | CGFloat x = point.x, w = 0.0f; 794 | NSInteger cols = [dataSource numberOfColumnsInTableView:self]; 795 | 796 | for (int i = 0; i < cols; i++) { 797 | w += [self widthForColumn:i]; 798 | if (x < w) 799 | return i; 800 | } 801 | 802 | return -1; 803 | } 804 | 805 | - (NSMutableArray *)indexPathsOfSection:(NSInteger)section headerRow:(NSInteger)row 806 | { 807 | NSInteger numberOfRows = [dataSource tableView:self numberOfRowsInSection:section]; 808 | NSMutableArray *indexPaths = [NSMutableArray arrayWithCapacity:10]; 809 | for (int i = 1; i <= numberOfRows; i++) { 810 | [indexPaths addObject:[NSIndexPath indexPathForRow:row + i inSection:0]]; 811 | } 812 | return indexPaths; 813 | } 814 | 815 | - (CGRect)highlightRectForColumn:(NSInteger)col 816 | { 817 | CGFloat x = headerTblView.frame.size.width - scrlView.contentOffset.x + boldSeperatorLineWidth; 818 | for (int i = 0; i < col; i++) { 819 | x += [self widthForColumn:i] + normalSeperatorLineWidth; 820 | } 821 | 822 | CGFloat w = [self widthForColumn:col]; 823 | 824 | return CGRectMake(x, EWMultiColumnTable_BorderWidth, w, self.frame.size.height - EWMultiColumnTable_BorderWidth * 2); 825 | } 826 | 827 | #pragma mark Event Handelers 828 | 829 | - (void)orientationChanged:(NSNotification *)notification 830 | { 831 | [self adjustWidth]; 832 | } 833 | 834 | - (void)columnLongPressed:(UILongPressGestureRecognizer *)recognizer 835 | { 836 | if ([dataSource respondsToSelector:@selector(tableView:swapDataOfColumn:andColumn:)]) { 837 | switch (recognizer.state) { 838 | case UIGestureRecognizerStateBegan: { 839 | // create the drag overlay layer 840 | CGPoint point = [recognizer locationInView:scrlView]; 841 | selectedColumn = [self columnOfPointInTblView:point]; 842 | 843 | // Highlight the column 844 | [self highlightColumn:selectedColumn]; 845 | break; 846 | } case UIGestureRecognizerStateChanged: { 847 | // move the dragging layer to the destination. 848 | CGPoint point = [recognizer locationInView:scrlView]; 849 | NSInteger currentCol = [self columnOfPointInTblView:point]; 850 | 851 | if (currentCol >= 0 && currentCol != selectedColumn) { 852 | [self swapColumn:selectedColumn andColumn:currentCol]; 853 | selectedColumn = currentCol; 854 | [self highlightColumn:selectedColumn]; 855 | } 856 | 857 | break; 858 | } 859 | case UIGestureRecognizerStateEnded: 860 | case UIGestureRecognizerStateCancelled: { 861 | [self clearHighlightColumn]; 862 | selectedColumn = -1; 863 | // swap the column 864 | break; 865 | } 866 | default: 867 | NSLog(@"recognizer.state: %d", recognizer.state); 868 | break; 869 | } 870 | } 871 | 872 | } 873 | 874 | @end 875 | -------------------------------------------------------------------------------- /MultiColumnTableView/EWMultiColumnTableViewBGScrollView.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011 Eli Wang 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 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell 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 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 | * IN THE SOFTWARE. 21 | */ 22 | 23 | 24 | #import 25 | 26 | @class EWMultiColumnTableView; 27 | 28 | 29 | @interface EWMultiColumnTableViewBGScrollView : UIScrollView { 30 | NSMutableArray *lines; 31 | } 32 | 33 | @property (nonatomic, assign) EWMultiColumnTableView *parent; 34 | 35 | // This method will draw the vertical lines. It adds UIViews as lines ABOVE all views. call it after the table reloads 36 | // to make sure the lines visible 37 | - (void)redraw; 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /MultiColumnTableView/EWMultiColumnTableViewBGScrollView.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011 Eli Wang 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 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell 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 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 | * IN THE SOFTWARE. 21 | */ 22 | 23 | 24 | #import "EWMultiColumnTableViewBGScrollView.h" 25 | #import "EWMultiColumnTableView.h" 26 | #import 27 | #import "UIView+AddLine.h" 28 | 29 | 30 | @implementation EWMultiColumnTableViewBGScrollView 31 | 32 | @synthesize parent; 33 | 34 | - (void)dealloc 35 | { 36 | [lines release]; 37 | [super dealloc]; 38 | } 39 | 40 | - (void)redraw 41 | { 42 | if (lines == nil) lines = [[NSMutableArray alloc] initWithCapacity:10]; 43 | 44 | for (UIView *v in lines) { 45 | [v removeFromSuperview]; 46 | } 47 | 48 | [lines removeAllObjects]; 49 | 50 | UIView *v = [[[UIView alloc] initWithFrame:CGRectMake(0.0f - parent.normalSeperatorLineWidth, 0.0f, 51 | parent.normalSeperatorLineWidth, self.frame.size.height)] autorelease]; 52 | v.backgroundColor = parent.normalSeperatorLineColor; 53 | [self addSubview:v]; 54 | [lines addObject:v]; 55 | 56 | CGFloat x = 0.0f; 57 | for (int i = 0; i < [parent.dataSource numberOfColumnsInTableView:parent]; i++) { 58 | CGFloat width; 59 | if ([parent.dataSource respondsToSelector:@selector(tableView:widthForColumn:)]) 60 | width = [parent.dataSource tableView:parent widthForColumn:i]; 61 | else 62 | width = parent.cellWidth; 63 | 64 | x += width + parent.normalSeperatorLineWidth; 65 | v = [self addVerticalLineWithWidth:parent.normalSeperatorLineWidth color:parent.normalSeperatorLineColor atX:x]; 66 | [lines addObject:v]; 67 | } 68 | 69 | } 70 | 71 | @end 72 | -------------------------------------------------------------------------------- /MultiColumnTableView/EWMultiColumnTableViewCell.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011 Eli Wang 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 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell 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 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 | * IN THE SOFTWARE. 21 | */ 22 | 23 | 24 | #import 25 | 26 | 27 | @interface EWMultiColumnTableViewCell : UITableViewCell { 28 | 29 | } 30 | 31 | @property (nonatomic, readonly) NSMutableArray *columnCells; 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /MultiColumnTableView/EWMultiColumnTableViewCell.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011 Eli Wang 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 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell 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 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 | * IN THE SOFTWARE. 21 | */ 22 | 23 | 24 | #import "EWMultiColumnTableViewCell.h" 25 | 26 | 27 | @implementation EWMultiColumnTableViewCell 28 | 29 | @synthesize columnCells; 30 | 31 | - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier 32 | { 33 | self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; 34 | if (self) { 35 | columnCells = [[NSMutableArray alloc] initWithCapacity:5]; 36 | } 37 | return self; 38 | } 39 | 40 | - (void)dealloc 41 | { 42 | [columnCells release]; 43 | [super dealloc]; 44 | } 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /MultiColumnTableView/EWMultiColumnTableViewContentBackgroundView.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011 Eli Wang 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 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell 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 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 | * IN THE SOFTWARE. 21 | */ 22 | 23 | 24 | #import 25 | 26 | #define ColumnHighlightWidth 4.0f 27 | 28 | 29 | @interface EWMultiColumnTableViewContentBackgroundView : UITableView { 30 | 31 | } 32 | 33 | @property (nonatomic, assign) CGRect highlightedRect; 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /MultiColumnTableView/EWMultiColumnTableViewContentBackgroundView.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011 Eli Wang 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 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell 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 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 | * IN THE SOFTWARE. 21 | */ 22 | 23 | 24 | #import "EWMultiColumnTableViewContentBackgroundView.h" 25 | 26 | 27 | @implementation EWMultiColumnTableViewContentBackgroundView 28 | 29 | @synthesize highlightedRect; 30 | 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /MultiColumnTableView/EWMultiColumnTableViewDefaults.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011 Eli Wang 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 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell 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 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 | * IN THE SOFTWARE. 21 | */ 22 | 23 | 24 | #define EWMultiColumnTable_CornerRadius 3.0f 25 | #define EWMultiColumnTable_BorderWidth 1.0f 26 | #define EWMultiColumnTable_BorderColorGray 212.0f/255.0f 27 | 28 | #define EWMultiColumnTable_DefaultCellHeight 31.0f 29 | #define EWMultiColumnTable_DefaultCellWidth 252.0f 30 | #define EWMultiColumnTable_DefaultTopHeaderHeight 298.0f 31 | #define EWMultiColumnTable_DefaultLeftHeaderWidth 111.0f 32 | #define EWMultiColumnTable_DefaultSectionHeaderHeight 31.0f 33 | #define EWMultiColumnTable_DefaultHeaderCellWidth 80.0f 34 | #define EWMultiColumnTable_BoldLineWidth 3.0f 35 | #define EWMultiColumnTable_NormalLineWidth 1.0f 36 | #define EWMultiColumnTable_LineGray 223.0f/255.0f 37 | -------------------------------------------------------------------------------- /MultiColumnTableView/MultiColumnTableView-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIconFile 12 | 13 | CFBundleIdentifier 14 | com.yourcompany.${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 | NSMainNibFile 30 | MainWindow 31 | UISupportedInterfaceOrientations~ipad 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationPortraitUpsideDown 35 | UIInterfaceOrientationLandscapeLeft 36 | UIInterfaceOrientationLandscapeRight 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /MultiColumnTableView/MultiColumnTableView-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'MultiColumnTableView' target in the 'MultiColumnTableView' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_3_0 8 | #warning "This project uses features only available in iPhone SDK 3.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #endif 15 | -------------------------------------------------------------------------------- /MultiColumnTableView/MultiColumnTableViewAppDelegate.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011 Eli Wang 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 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell 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 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 | * IN THE SOFTWARE. 21 | */ 22 | 23 | 24 | #import 25 | 26 | @class MultiColumnTableViewViewController; 27 | 28 | @interface MultiColumnTableViewAppDelegate : NSObject { 29 | 30 | } 31 | 32 | @property (nonatomic, retain) IBOutlet UIWindow *window; 33 | 34 | @property (nonatomic, retain) IBOutlet MultiColumnTableViewViewController *viewController; 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /MultiColumnTableView/MultiColumnTableViewAppDelegate.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011 Eli Wang 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 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell 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 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 | * IN THE SOFTWARE. 21 | */ 22 | 23 | 24 | #import "MultiColumnTableViewAppDelegate.h" 25 | 26 | #import "MultiColumnTableViewViewController.h" 27 | 28 | @implementation MultiColumnTableViewAppDelegate 29 | 30 | 31 | @synthesize window=_window; 32 | 33 | @synthesize viewController=_viewController; 34 | 35 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 36 | { 37 | // Override point for customization after application launch. 38 | 39 | self.window.rootViewController = self.viewController; 40 | [self.window makeKeyAndVisible]; 41 | return YES; 42 | } 43 | 44 | - (void)applicationWillResignActive:(UIApplication *)application 45 | { 46 | /* 47 | Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 48 | Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 49 | */ 50 | } 51 | 52 | - (void)applicationDidEnterBackground:(UIApplication *)application 53 | { 54 | /* 55 | Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 56 | If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 57 | */ 58 | } 59 | 60 | - (void)applicationWillEnterForeground:(UIApplication *)application 61 | { 62 | /* 63 | Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 64 | */ 65 | } 66 | 67 | - (void)applicationDidBecomeActive:(UIApplication *)application 68 | { 69 | /* 70 | Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 71 | */ 72 | } 73 | 74 | - (void)applicationWillTerminate:(UIApplication *)application 75 | { 76 | /* 77 | Called when the application is about to terminate. 78 | Save data if appropriate. 79 | See also applicationDidEnterBackground:. 80 | */ 81 | } 82 | 83 | - (void)dealloc 84 | { 85 | [_window release]; 86 | [_viewController release]; 87 | [super dealloc]; 88 | } 89 | 90 | @end 91 | -------------------------------------------------------------------------------- /MultiColumnTableView/MultiColumnTableViewViewController.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011 Eli Wang 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 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell 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 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 | * IN THE SOFTWARE. 21 | */ 22 | 23 | 24 | #import 25 | #import "EWMultiColumnTableView.h" 26 | 27 | @interface MultiColumnTableViewViewController : UIViewController { 28 | NSMutableArray *data; 29 | NSMutableArray *sectionHeaderData; 30 | 31 | CGFloat colWidth; 32 | NSInteger numberOfSections; 33 | NSInteger numberOfColumns; 34 | 35 | EWMultiColumnTableView *tblView; 36 | } 37 | 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /MultiColumnTableView/MultiColumnTableViewViewController.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011 Eli Wang 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 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell 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 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 | * IN THE SOFTWARE. 21 | */ 22 | 23 | 24 | #import "MultiColumnTableViewViewController.h" 25 | #import "NSObject+DelayedBlock.h" 26 | 27 | #define ROWS 100 28 | 29 | @interface MultiColumnTableViewViewController() 30 | 31 | - (void)handleDoubleTap:(UITapGestureRecognizer *)recognizer; 32 | 33 | @end 34 | 35 | 36 | 37 | 38 | 39 | @implementation MultiColumnTableViewViewController 40 | 41 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 42 | { 43 | if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) { 44 | srand(time(0)); 45 | } 46 | 47 | return self; 48 | } 49 | 50 | 51 | - (void)dealloc 52 | { 53 | [data release]; 54 | [tblView release]; 55 | [sectionHeaderData release]; 56 | [super dealloc]; 57 | } 58 | 59 | - (void)didReceiveMemoryWarning 60 | { 61 | // Releases the view if it doesn't have a superview. 62 | [super didReceiveMemoryWarning]; 63 | 64 | // Release any cached data, images, etc that aren't in use. 65 | } 66 | 67 | #pragma mark - View lifecycle 68 | 69 | 70 | // Implement viewDidLoad to do additional setup after loading the view, typically from a nib. 71 | - (void)viewDidLoad 72 | { 73 | [super viewDidLoad]; 74 | numberOfColumns = 5; 75 | numberOfSections = 5; 76 | 77 | int sectionDistro[] = {5, 7, 4, 9, 2}; 78 | colWidth = 240.0f; 79 | 80 | data = [[NSMutableArray alloc] initWithCapacity:numberOfSections * 5]; 81 | sectionHeaderData = [[NSMutableArray alloc] initWithCapacity:numberOfSections]; 82 | 83 | for (int i = 0; i < numberOfSections; i++) { 84 | 85 | int rows = sectionDistro[i]; 86 | NSMutableArray *a = [NSMutableArray arrayWithCapacity:numberOfColumns]; 87 | for (int j = 0; j < numberOfColumns; j++) { 88 | 89 | int d = rand() % 100; 90 | 91 | NSMutableString *text = [NSMutableString stringWithFormat:@"S %d C %d", i, j]; 92 | if (d < 66) { 93 | [text appendFormat:@"\nsecond line"]; 94 | } 95 | 96 | if (d < 33) { 97 | [text appendFormat:@"\nthird line"]; 98 | } 99 | 100 | 101 | [a addObject:text]; 102 | } 103 | [sectionHeaderData addObject:a]; 104 | 105 | NSMutableArray *sectionArray = [NSMutableArray arrayWithCapacity:10]; 106 | for (int k = 0; k < rows; k++) { 107 | 108 | NSMutableArray *rowArray = [NSMutableArray arrayWithCapacity:numberOfColumns]; 109 | for (int j = 0; j < numberOfColumns; j++) { 110 | int d = rand() % 100; 111 | 112 | NSMutableString *text = [NSMutableString stringWithFormat:@"(%d, %d, %d)", i, k, j]; 113 | if (d < 66) { 114 | [text appendFormat:@"\nsecond line"]; 115 | } 116 | 117 | if (d < 33) { 118 | [text appendFormat:@"\nthird line"]; 119 | } 120 | 121 | [rowArray addObject:text]; 122 | } 123 | 124 | [sectionArray addObject:rowArray]; 125 | } 126 | 127 | [data addObject:sectionArray]; 128 | } 129 | 130 | 131 | tblView = [[EWMultiColumnTableView alloc] initWithFrame:CGRectInset(self.view.bounds, 5.0f, 5.0f)]; 132 | tblView.sectionHeaderEnabled = YES; 133 | // tblView.cellWidth = 100.0f; 134 | // tblView.boldSeperatorLineColor = [UIColor blueColor]; 135 | // tblView.normalSeperatorLineColor = [UIColor blueColor]; 136 | // tblView.boldSeperatorLineWidth = 10.0f; 137 | // tblView.normalSeperatorLineWidth = 10.0f; 138 | tblView.dataSource = self; 139 | tblView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; 140 | [self.view addSubview:tblView]; 141 | 142 | [self performBlock:^{ 143 | 144 | [tblView scrollToColumn:3 position:EWMultiColumnTableViewColumnPositionMiddle animated:YES]; 145 | } afterDelay:0.5]; 146 | } 147 | 148 | 149 | - (void)viewDidUnload 150 | { 151 | [super viewDidUnload]; 152 | // Release any retained subviews of the main view. 153 | 154 | // e.g. self.myOutlet = nil; 155 | [tblView release]; 156 | tblView = nil; 157 | } 158 | 159 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 160 | { 161 | // Return YES for supported orientations 162 | return YES; 163 | } 164 | 165 | #pragma mark - EWMultiColumnTableViewDataSource 166 | 167 | - (NSInteger)numberOfSectionsInTableView:(EWMultiColumnTableView *)tableView 168 | { 169 | return numberOfSections; 170 | } 171 | 172 | - (UIView *)tableView:(EWMultiColumnTableView *)tableView cellForIndexPath:(NSIndexPath *)indexPath column:(NSInteger)col 173 | { 174 | UILabel *l = [[[UILabel alloc] initWithFrame:CGRectMake(0.0f, 0.0f, colWidth, 40.0f)] autorelease]; 175 | l.numberOfLines = 0; 176 | l.lineBreakMode = UILineBreakModeWordWrap; 177 | 178 | return l; 179 | } 180 | 181 | 182 | - (void)tableView:(EWMultiColumnTableView *)tableView setContentForCell:(UIView *)cell indexPath:(NSIndexPath *)indexPath column:(NSInteger)col{ 183 | UILabel *l = (UILabel *)cell; 184 | l.text = [[[data objectAtIndex:indexPath.section] objectAtIndex:indexPath.row] objectAtIndex:col]; 185 | 186 | CGRect f = l.frame; 187 | f.size.width = [self tableView:tableView widthForColumn:col]; 188 | l.frame = f; 189 | 190 | [l sizeToFit]; 191 | } 192 | 193 | - (CGFloat)tableView:(EWMultiColumnTableView *)tableView heightForCellAtIndexPath:(NSIndexPath *)indexPath column:(NSInteger)col 194 | { 195 | NSString *str = [[[data objectAtIndex:indexPath.section] objectAtIndex:indexPath.row] objectAtIndex:col]; 196 | CGSize s = [str sizeWithFont:[UIFont systemFontOfSize:[UIFont systemFontSize]] 197 | constrainedToSize:CGSizeMake([self tableView:tableView widthForColumn:col], MAXFLOAT) lineBreakMode:UILineBreakModeWordWrap]; 198 | 199 | return s.height + 20.0f; 200 | } 201 | 202 | - (CGFloat)tableView:(EWMultiColumnTableView *)tableView widthForColumn:(NSInteger)column 203 | { 204 | return colWidth; 205 | } 206 | 207 | - (NSInteger)tableView:(EWMultiColumnTableView *)tableView numberOfRowsInSection:(NSInteger)section 208 | { 209 | return [[data objectAtIndex:section] count]; 210 | } 211 | 212 | - (UIView *)tableView:(EWMultiColumnTableView *)tableView sectionHeaderCellForSection:(NSInteger)section column:(NSInteger)col 213 | { 214 | UILabel *l = [[[UILabel alloc] initWithFrame:CGRectMake(0.0f, 0.0f, [self tableView:tableView widthForColumn:col], 40.0f)] autorelease]; 215 | l.backgroundColor = [UIColor yellowColor]; 216 | return l; 217 | } 218 | 219 | - (void)tableView:(EWMultiColumnTableView *)tableView setContentForSectionHeaderCell:(UIView *)cell section:(NSInteger)section column:(NSInteger)col 220 | { 221 | UILabel *l = (UILabel *)cell; 222 | l.text = [NSString stringWithFormat:@"S %d C %d", section, col]; 223 | 224 | CGRect f = l.frame; 225 | f.size.width = [self tableView:tableView widthForColumn:col]; 226 | l.frame = f; 227 | 228 | [l sizeToFit]; 229 | } 230 | 231 | - (NSInteger)numberOfColumnsInTableView:(EWMultiColumnTableView *)tableView 232 | { 233 | return numberOfColumns; 234 | } 235 | 236 | #pragma mark Header Cell 237 | 238 | - (UIView *)tableView:(EWMultiColumnTableView *)tableView headerCellForIndexPath:(NSIndexPath *)indexPath 239 | { 240 | return [[[UILabel alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 100.0f, 40.0f)] autorelease]; 241 | } 242 | 243 | - (void)tableView:(EWMultiColumnTableView *)tableView setContentForHeaderCell:(UIView *)cell atIndexPath:(NSIndexPath *)indexPath 244 | { 245 | UILabel *l = (UILabel *)cell; 246 | l.text = [NSString stringWithFormat:@"Line: (%d, %d)", indexPath.section, indexPath.row]; 247 | } 248 | 249 | - (CGFloat)tableView:(EWMultiColumnTableView *)tableView heightForHeaderCellAtIndexPath:(NSIndexPath *)indexPath 250 | { 251 | return 40.0f; 252 | } 253 | 254 | - (CGFloat)tableView:(EWMultiColumnTableView *)tableView heightForSectionHeaderCellAtSection:(NSInteger)section column:(NSInteger)col 255 | { 256 | return 50.0f; 257 | } 258 | 259 | - (UIView *)tableView:(EWMultiColumnTableView *)tableView headerCellInSectionHeaderForSection:(NSInteger)section 260 | { 261 | UILabel *l = [[[UILabel alloc] initWithFrame:CGRectMake(0.0f, 0.0f, [self widthForHeaderCellOfTableView:tableView], 30.0f)] autorelease]; 262 | l.backgroundColor = [UIColor orangeColor]; 263 | return l; 264 | 265 | } 266 | 267 | - (void)tableView:(EWMultiColumnTableView *)tableView setContentForHeaderCellInSectionHeader:(UIView *)cell AtSection:(NSInteger)section 268 | { 269 | UILabel *l = (UILabel *)cell; 270 | l.text = [NSString stringWithFormat:@"Section %d", section]; 271 | } 272 | 273 | - (CGFloat)widthForHeaderCellOfTableView:(EWMultiColumnTableView *)tableView 274 | { 275 | return 200.0f; 276 | } 277 | 278 | 279 | - (UIView *)tableView:(EWMultiColumnTableView *)tableView headerCellForColumn:(NSInteger)col 280 | { 281 | UILabel *l = [[[UILabel alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 250.0f, 300.0f)] autorelease]; 282 | l.text = [NSString stringWithFormat:@"Column: %d", col]; 283 | l.userInteractionEnabled = YES; 284 | 285 | l.tag = col; 286 | UITapGestureRecognizer *recognizer = [[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleDoubleTap:)] autorelease]; 287 | recognizer.numberOfTapsRequired = 2; 288 | [l addGestureRecognizer:recognizer]; 289 | 290 | return l; 291 | } 292 | 293 | - (UIView *)topleftHeaderCellOfTableView:(EWMultiColumnTableView *)tableView 294 | { 295 | UILabel *l = [[[UILabel alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 250.0f, [self heightForHeaderCellOfTableView:tableView])] autorelease]; 296 | l.text = @"Products"; 297 | 298 | return l; 299 | } 300 | 301 | - (CGFloat)heightForHeaderCellOfTableView:(EWMultiColumnTableView *)tableView 302 | { 303 | return 300.0f; 304 | } 305 | 306 | - (void)tableView:(EWMultiColumnTableView *)tableView swapDataOfColumn:(NSInteger)col1 andColumn:(NSInteger)col2 307 | { 308 | for (int i = 0; i < [self numberOfSectionsInTableView:tableView]; i++) { 309 | NSMutableArray *section = [data objectAtIndex:i]; 310 | for (int j = 0; j < [self tableView:tableView numberOfRowsInSection:i]; j++) { 311 | NSMutableArray *a = [section objectAtIndex:j]; 312 | id tmp = [[a objectAtIndex:col2] retain]; 313 | 314 | [a replaceObjectAtIndex:col2 withObject:[a objectAtIndex:col1]]; 315 | [a replaceObjectAtIndex:col1 withObject:tmp]; 316 | [tmp release]; 317 | } 318 | } 319 | } 320 | 321 | - (void)handleDoubleTap:(UITapGestureRecognizer *)recognizer 322 | { 323 | int col = [recognizer.view tag]; 324 | for (NSMutableArray *array in sectionHeaderData) { 325 | [array removeObjectAtIndex:col]; 326 | // [array addObject:@""]; 327 | } 328 | 329 | for (NSMutableArray *section in data) { 330 | for (NSMutableArray *row in section) { 331 | [row removeObjectAtIndex:col]; 332 | // [row addObject:@""]; 333 | } 334 | } 335 | 336 | numberOfColumns--; 337 | 338 | [tblView reloadData]; 339 | 340 | } 341 | 342 | @end 343 | -------------------------------------------------------------------------------- /MultiColumnTableView/NSObject+DelayedBlock.h: -------------------------------------------------------------------------------- 1 | // 2 | // DelayedBlock.h 3 | // RenaultTraining 4 | // 5 | // Created by Eli Wang on 11-8-23. 6 | // Copyright 2011年 ekohe.com. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSObject (DelayedBlock) 12 | 13 | - (void)performBlock:(void (^)(void))block afterDelay:(NSTimeInterval)delay; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /MultiColumnTableView/NSObject+DelayedBlock.m: -------------------------------------------------------------------------------- 1 | // 2 | // DelayedBlock.m 3 | // RenaultTraining 4 | // 5 | // Created by Eli Wang on 11-8-23. 6 | // Copyright 2011年 ekohe.com. All rights reserved. 7 | // 8 | 9 | #import "NSObject+DelayedBlock.h" 10 | 11 | @implementation NSObject (DelayedBlock) 12 | 13 | - (void)performBlock:(void (^)(void))block afterDelay:(NSTimeInterval)delay 14 | { 15 | int64_t delta = (int64_t)(1.0e9 * delay); 16 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, delta), dispatch_get_main_queue(), block); 17 | } 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /MultiColumnTableView/UIView+AddLine.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011 Eli Wang 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 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell 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 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 | * IN THE SOFTWARE. 21 | */ 22 | 23 | 24 | #import 25 | 26 | 27 | @interface UIView(AddLine) 28 | 29 | - (void)addBottomLineWithWidth:(CGFloat)width color:(UIColor *)color; 30 | 31 | - (UIView *)addVerticalLineWithWidth:(CGFloat)width color:(UIColor *)color atX:(CGFloat)x; 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /MultiColumnTableView/UIView+AddLine.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011 Eli Wang 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 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell 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 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 | * IN THE SOFTWARE. 21 | */ 22 | 23 | 24 | #import "UIView+AddLine.h" 25 | 26 | 27 | @implementation UIView(AddLine) 28 | 29 | - (void)addBottomLineWithWidth:(CGFloat)width color:(UIColor *)color 30 | { 31 | CGRect f = self.frame; 32 | f.size.height += width; 33 | self.frame = f; 34 | 35 | UIView *bottomLine = [[[UIView alloc] initWithFrame:CGRectMake(0.0, self.frame.size.height - width, 36 | self.frame.size.width, width)] autorelease]; 37 | bottomLine.backgroundColor = color; 38 | bottomLine.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin; 39 | 40 | [self addSubview:bottomLine]; 41 | } 42 | 43 | - (UIView *)addVerticalLineWithWidth:(CGFloat)width color:(UIColor *)color atX:(CGFloat)x 44 | { 45 | UIView *vLine = [[[UIView alloc] initWithFrame:CGRectMake(x, 0.0f, width, self.frame.size.height)] autorelease]; 46 | vLine.backgroundColor = color; 47 | vLine.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleRightMargin; 48 | 49 | [self addSubview:vLine]; 50 | 51 | return vLine; 52 | } 53 | 54 | @end 55 | -------------------------------------------------------------------------------- /MultiColumnTableView/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /MultiColumnTableView/en.lproj/MainWindow.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 800 5 | 10D540 6 | 760 7 | 1038.29 8 | 460.00 9 | 10 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 11 | 81 12 | 13 | 14 | YES 15 | 16 | 17 | 18 | YES 19 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 20 | 21 | 22 | YES 23 | 24 | YES 25 | 26 | 27 | YES 28 | 29 | 30 | 31 | YES 32 | 33 | IBFilesOwner 34 | IBCocoaTouchFramework 35 | 36 | 37 | IBFirstResponder 38 | IBCocoaTouchFramework 39 | 40 | 41 | 42 | 292 43 | {768, 1024} 44 | 45 | 46 | 1 47 | MSAxIDEAA 48 | 49 | NO 50 | NO 51 | 52 | 2 53 | 54 | IBIPadFramework 55 | YES 56 | 57 | 58 | IBIPadFramework 59 | 60 | 61 | MultiColumnTableViewViewController 62 | 63 | IBIPadFramework 64 | 65 | 66 | 67 | 68 | YES 69 | 70 | 71 | viewController 72 | 73 | 74 | 75 | 8 76 | 77 | 78 | 79 | delegate 80 | 81 | 82 | 83 | 9 84 | 85 | 86 | 87 | window 88 | 89 | 90 | 91 | 10 92 | 93 | 94 | 95 | 96 | YES 97 | 98 | 0 99 | 100 | 101 | 102 | 103 | 104 | -1 105 | 106 | 107 | File's Owner 108 | 109 | 110 | -2 111 | 112 | 113 | 114 | 115 | 2 116 | 117 | 118 | 119 | 120 | 6 121 | 122 | 123 | MultiColumnTableView App Delegate 124 | 125 | 126 | 7 127 | 128 | 129 | 130 | 131 | 132 | 133 | YES 134 | 135 | YES 136 | -1.CustomClassName 137 | -2.CustomClassName 138 | 2.IBEditorWindowLastContentRect 139 | 2.IBPluginDependency 140 | 6.CustomClassName 141 | 6.IBPluginDependency 142 | 7.CustomClassName 143 | 7.IBEditorWindowLastContentRect 144 | 7.IBPluginDependency 145 | 146 | 147 | YES 148 | UIApplication 149 | UIResponder 150 | {{200, 57}, {783, 799}} 151 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 152 | MultiColumnTableViewAppDelegate 153 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 154 | MultiColumnTableViewViewController 155 | {{512, 351}, {320, 480}} 156 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 157 | 158 | 159 | 160 | YES 161 | 162 | 163 | YES 164 | 165 | 166 | 167 | 168 | YES 169 | 170 | 171 | YES 172 | 173 | 174 | 175 | 10 176 | 177 | 178 | 179 | YES 180 | 181 | MultiColumnTableViewAppDelegate 182 | NSObject 183 | 184 | YES 185 | 186 | YES 187 | viewController 188 | window 189 | 190 | 191 | YES 192 | MultiColumnTableViewViewController 193 | UIWindow 194 | 195 | 196 | 197 | IBProjectSource 198 | MultiColumnTableViewAppDelegate.h 199 | 200 | 201 | 202 | MultiColumnTableViewViewController 203 | UIViewController 204 | 205 | IBProjectSource 206 | MultiColumnTableViewViewController.h 207 | 208 | 209 | 210 | 211 | YES 212 | 213 | NSObject 214 | 215 | IBFrameworkSource 216 | Foundation.framework/Headers/NSError.h 217 | 218 | 219 | 220 | NSObject 221 | 222 | IBFrameworkSource 223 | Foundation.framework/Headers/NSFileManager.h 224 | 225 | 226 | 227 | NSObject 228 | 229 | IBFrameworkSource 230 | Foundation.framework/Headers/NSKeyValueCoding.h 231 | 232 | 233 | 234 | NSObject 235 | 236 | IBFrameworkSource 237 | Foundation.framework/Headers/NSKeyValueObserving.h 238 | 239 | 240 | 241 | NSObject 242 | 243 | IBFrameworkSource 244 | Foundation.framework/Headers/NSKeyedArchiver.h 245 | 246 | 247 | 248 | NSObject 249 | 250 | IBFrameworkSource 251 | Foundation.framework/Headers/NSNetServices.h 252 | 253 | 254 | 255 | NSObject 256 | 257 | IBFrameworkSource 258 | Foundation.framework/Headers/NSObject.h 259 | 260 | 261 | 262 | NSObject 263 | 264 | IBFrameworkSource 265 | Foundation.framework/Headers/NSPort.h 266 | 267 | 268 | 269 | NSObject 270 | 271 | IBFrameworkSource 272 | Foundation.framework/Headers/NSRunLoop.h 273 | 274 | 275 | 276 | NSObject 277 | 278 | IBFrameworkSource 279 | Foundation.framework/Headers/NSStream.h 280 | 281 | 282 | 283 | NSObject 284 | 285 | IBFrameworkSource 286 | Foundation.framework/Headers/NSThread.h 287 | 288 | 289 | 290 | NSObject 291 | 292 | IBFrameworkSource 293 | Foundation.framework/Headers/NSURL.h 294 | 295 | 296 | 297 | NSObject 298 | 299 | IBFrameworkSource 300 | Foundation.framework/Headers/NSURLConnection.h 301 | 302 | 303 | 304 | NSObject 305 | 306 | IBFrameworkSource 307 | Foundation.framework/Headers/NSXMLParser.h 308 | 309 | 310 | 311 | NSObject 312 | 313 | IBFrameworkSource 314 | UIKit.framework/Headers/UIAccessibility.h 315 | 316 | 317 | 318 | NSObject 319 | 320 | IBFrameworkSource 321 | UIKit.framework/Headers/UINibLoading.h 322 | 323 | 324 | 325 | NSObject 326 | 327 | IBFrameworkSource 328 | UIKit.framework/Headers/UIResponder.h 329 | 330 | 331 | 332 | UIApplication 333 | UIResponder 334 | 335 | IBFrameworkSource 336 | UIKit.framework/Headers/UIApplication.h 337 | 338 | 339 | 340 | UIResponder 341 | NSObject 342 | 343 | 344 | 345 | UIResponder 346 | 347 | IBFrameworkSource 348 | UIKit.framework/Headers/UITextInput.h 349 | 350 | 351 | 352 | UISearchBar 353 | UIView 354 | 355 | IBFrameworkSource 356 | UIKit.framework/Headers/UISearchBar.h 357 | 358 | 359 | 360 | UISearchDisplayController 361 | NSObject 362 | 363 | IBFrameworkSource 364 | UIKit.framework/Headers/UISearchDisplayController.h 365 | 366 | 367 | 368 | UIView 369 | 370 | IBFrameworkSource 371 | UIKit.framework/Headers/UITextField.h 372 | 373 | 374 | 375 | UIView 376 | UIResponder 377 | 378 | IBFrameworkSource 379 | UIKit.framework/Headers/UIView.h 380 | 381 | 382 | 383 | UIViewController 384 | 385 | IBFrameworkSource 386 | UIKit.framework/Headers/UINavigationController.h 387 | 388 | 389 | 390 | UIViewController 391 | 392 | IBFrameworkSource 393 | UIKit.framework/Headers/UISplitViewController.h 394 | 395 | 396 | 397 | UIViewController 398 | 399 | IBFrameworkSource 400 | UIKit.framework/Headers/UITabBarController.h 401 | 402 | 403 | 404 | UIViewController 405 | UIResponder 406 | 407 | IBFrameworkSource 408 | UIKit.framework/Headers/UIViewController.h 409 | 410 | 411 | 412 | UIWindow 413 | UIView 414 | 415 | IBFrameworkSource 416 | UIKit.framework/Headers/UIWindow.h 417 | 418 | 419 | 420 | 421 | 0 422 | IBIPadFramework 423 | 424 | com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS 425 | 426 | 427 | 428 | com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 429 | 430 | 431 | YES 432 | MultiColumnTableView.xcodeproj 433 | 3 434 | 81 435 | 436 | 437 | -------------------------------------------------------------------------------- /MultiColumnTableView/en.lproj/MultiColumnTableViewViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 800 5 | 10J869 6 | 1306 7 | 1038.35 8 | 461.00 9 | 10 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 11 | 301 12 | 13 | 14 | YES 15 | IBProxyObject 16 | IBUIView 17 | 18 | 19 | YES 20 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 21 | 22 | 23 | YES 24 | 25 | YES 26 | 27 | 28 | 29 | 30 | YES 31 | 32 | IBFilesOwner 33 | IBIPadFramework 34 | 35 | 36 | IBFirstResponder 37 | IBIPadFramework 38 | 39 | 40 | 41 | 292 42 | {768, 1004} 43 | 44 | 45 | 46 | 3 47 | MQA 48 | 49 | 2 50 | 51 | 52 | IBIPadFramework 53 | 54 | 55 | 56 | 57 | YES 58 | 59 | 60 | view 61 | 62 | 63 | 64 | 22 65 | 66 | 67 | 68 | 69 | YES 70 | 71 | 0 72 | 73 | 74 | 75 | 76 | 77 | -1 78 | 79 | 80 | File's Owner 81 | 82 | 83 | -2 84 | 85 | 86 | 87 | 88 | 21 89 | 90 | 91 | 92 | 93 | 94 | 95 | YES 96 | 97 | YES 98 | -1.CustomClassName 99 | -2.CustomClassName 100 | 21.IBPluginDependency 101 | 102 | 103 | YES 104 | MultiColumnTableViewViewController 105 | UIResponder 106 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 107 | 108 | 109 | 110 | YES 111 | 112 | 113 | 114 | 115 | 116 | YES 117 | 118 | 119 | 120 | 121 | 22 122 | 123 | 124 | 125 | YES 126 | 127 | MultiColumnTableViewViewController 128 | UIViewController 129 | 130 | IBProjectSource 131 | ./Classes/MultiColumnTableViewViewController.h 132 | 133 | 134 | 135 | 136 | 0 137 | IBIPadFramework 138 | 139 | com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS 140 | 141 | 142 | 143 | com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 144 | 145 | 146 | YES 147 | 3 148 | 301 149 | 150 | 151 | -------------------------------------------------------------------------------- /MultiColumnTableView/main.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011 Eli Wang 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 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell 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 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 | * IN THE SOFTWARE. 21 | */ 22 | 23 | 24 | #import 25 | 26 | int main(int argc, char *argv[]) 27 | { 28 | NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 29 | int retVal = UIApplicationMain(argc, argv, nil, nil); 30 | [pool release]; 31 | return retVal; 32 | } 33 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Base on the UITableView containing only one column, this project implements a multi-column table view for iOS. It has a horizontal scrollable table body, a fixed left and top table header. It also supports foldable sections, and draggable columns. 2 | --------------------------------------------------------------------------------