├── .gitignore ├── NSRectangle.xcodeproj └── project.pbxproj ├── NSRectangle ├── MAAppDelegate.h ├── MAAppDelegate.m ├── MACoordinateSystem.h ├── MACoordinateSystem.m ├── MARectangle.h ├── MARectangle.m ├── NSRectangle-Info.plist ├── NSRectangle-Prefix.pch ├── NSScreen+MARectangleAdditions.h ├── NSScreen+MARectangleAdditions.m ├── NSView+MARectangleAdditions.h ├── NSView+MARectangleAdditions.m ├── NSWindow+MARectangleAdditions.h ├── NSWindow+MARectangleAdditions.m ├── en.lproj │ ├── Credits.rtf │ ├── InfoPlist.strings │ └── MainMenu.xib └── main.m ├── NSRectangleTests ├── NSRectangleTests-Info.plist ├── NSRectangleTests.h ├── NSRectangleTests.m └── en.lproj │ └── InfoPlist.strings └── README.markdown /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | xcuserdata 3 | *.xcworkspace 4 | .DS_Store 5 | -------------------------------------------------------------------------------- /NSRectangle.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | C2B3C4AA15004C3E00742239 /* NSView+MARectangleAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = C2B3C4A915004C3E00742239 /* NSView+MARectangleAdditions.m */; }; 11 | C2B3C4AE15004ECB00742239 /* NSWindow+MARectangleAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = C2B3C4AD15004ECB00742239 /* NSWindow+MARectangleAdditions.m */; }; 12 | C2B3C4B115004F5B00742239 /* NSScreen+MARectangleAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = C2B3C4B015004F5B00742239 /* NSScreen+MARectangleAdditions.m */; }; 13 | C2E5DC7015002021008AE3A3 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C2E5DC6F15002021008AE3A3 /* Cocoa.framework */; }; 14 | C2E5DC7A15002021008AE3A3 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = C2E5DC7815002021008AE3A3 /* InfoPlist.strings */; }; 15 | C2E5DC7C15002021008AE3A3 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C2E5DC7B15002021008AE3A3 /* main.m */; }; 16 | C2E5DC8015002021008AE3A3 /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = C2E5DC7E15002021008AE3A3 /* Credits.rtf */; }; 17 | C2E5DC8315002021008AE3A3 /* MAAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = C2E5DC8215002021008AE3A3 /* MAAppDelegate.m */; }; 18 | C2E5DC8615002021008AE3A3 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = C2E5DC8415002021008AE3A3 /* MainMenu.xib */; }; 19 | C2E5DC8E15002021008AE3A3 /* SenTestingKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C2E5DC8D15002021008AE3A3 /* SenTestingKit.framework */; }; 20 | C2E5DC8F15002021008AE3A3 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C2E5DC6F15002021008AE3A3 /* Cocoa.framework */; }; 21 | C2E5DC9715002021008AE3A3 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = C2E5DC9515002021008AE3A3 /* InfoPlist.strings */; }; 22 | C2E5DC9A15002021008AE3A3 /* NSRectangleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = C2E5DC9915002021008AE3A3 /* NSRectangleTests.m */; }; 23 | C2E5DCA51500203E008AE3A3 /* MARectangle.m in Sources */ = {isa = PBXBuildFile; fileRef = C2E5DCA41500203E008AE3A3 /* MARectangle.m */; }; 24 | C2E5DCA8150020CD008AE3A3 /* MACoordinateSystem.m in Sources */ = {isa = PBXBuildFile; fileRef = C2E5DCA7150020CD008AE3A3 /* MACoordinateSystem.m */; }; 25 | /* End PBXBuildFile section */ 26 | 27 | /* Begin PBXContainerItemProxy section */ 28 | C2E5DC9015002021008AE3A3 /* PBXContainerItemProxy */ = { 29 | isa = PBXContainerItemProxy; 30 | containerPortal = C2E5DC6215002021008AE3A3 /* Project object */; 31 | proxyType = 1; 32 | remoteGlobalIDString = C2E5DC6A15002021008AE3A3; 33 | remoteInfo = NSRectangle; 34 | }; 35 | /* End PBXContainerItemProxy section */ 36 | 37 | /* Begin PBXFileReference section */ 38 | C2B3C4A815004C3E00742239 /* NSView+MARectangleAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSView+MARectangleAdditions.h"; sourceTree = ""; }; 39 | C2B3C4A915004C3E00742239 /* NSView+MARectangleAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSView+MARectangleAdditions.m"; sourceTree = ""; }; 40 | C2B3C4AC15004ECB00742239 /* NSWindow+MARectangleAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSWindow+MARectangleAdditions.h"; sourceTree = ""; }; 41 | C2B3C4AD15004ECB00742239 /* NSWindow+MARectangleAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSWindow+MARectangleAdditions.m"; sourceTree = ""; }; 42 | C2B3C4AF15004F5B00742239 /* NSScreen+MARectangleAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSScreen+MARectangleAdditions.h"; sourceTree = ""; }; 43 | C2B3C4B015004F5B00742239 /* NSScreen+MARectangleAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSScreen+MARectangleAdditions.m"; sourceTree = ""; }; 44 | C2E5DC6B15002021008AE3A3 /* NSRectangle.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = NSRectangle.app; sourceTree = BUILT_PRODUCTS_DIR; }; 45 | C2E5DC6F15002021008AE3A3 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; 46 | C2E5DC7215002021008AE3A3 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; 47 | C2E5DC7315002021008AE3A3 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; 48 | C2E5DC7415002021008AE3A3 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 49 | C2E5DC7715002021008AE3A3 /* NSRectangle-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "NSRectangle-Info.plist"; sourceTree = ""; }; 50 | C2E5DC7915002021008AE3A3 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 51 | C2E5DC7B15002021008AE3A3 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 52 | C2E5DC7D15002021008AE3A3 /* NSRectangle-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSRectangle-Prefix.pch"; sourceTree = ""; }; 53 | C2E5DC7F15002021008AE3A3 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = en; path = en.lproj/Credits.rtf; sourceTree = ""; }; 54 | C2E5DC8115002021008AE3A3 /* MAAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MAAppDelegate.h; sourceTree = ""; }; 55 | C2E5DC8215002021008AE3A3 /* MAAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MAAppDelegate.m; sourceTree = ""; }; 56 | C2E5DC8515002021008AE3A3 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MainMenu.xib; sourceTree = ""; }; 57 | C2E5DC8C15002021008AE3A3 /* NSRectangleTests.octest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NSRectangleTests.octest; sourceTree = BUILT_PRODUCTS_DIR; }; 58 | C2E5DC8D15002021008AE3A3 /* SenTestingKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SenTestingKit.framework; path = Library/Frameworks/SenTestingKit.framework; sourceTree = DEVELOPER_DIR; }; 59 | C2E5DC9415002021008AE3A3 /* NSRectangleTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "NSRectangleTests-Info.plist"; sourceTree = ""; }; 60 | C2E5DC9615002021008AE3A3 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 61 | C2E5DC9815002021008AE3A3 /* NSRectangleTests.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NSRectangleTests.h; sourceTree = ""; }; 62 | C2E5DC9915002021008AE3A3 /* NSRectangleTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NSRectangleTests.m; sourceTree = ""; }; 63 | C2E5DCA31500203E008AE3A3 /* MARectangle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MARectangle.h; sourceTree = ""; }; 64 | C2E5DCA41500203E008AE3A3 /* MARectangle.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MARectangle.m; sourceTree = ""; }; 65 | C2E5DCA6150020CD008AE3A3 /* MACoordinateSystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MACoordinateSystem.h; sourceTree = ""; }; 66 | C2E5DCA7150020CD008AE3A3 /* MACoordinateSystem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MACoordinateSystem.m; sourceTree = ""; }; 67 | /* End PBXFileReference section */ 68 | 69 | /* Begin PBXFrameworksBuildPhase section */ 70 | C2E5DC6815002021008AE3A3 /* Frameworks */ = { 71 | isa = PBXFrameworksBuildPhase; 72 | buildActionMask = 2147483647; 73 | files = ( 74 | C2E5DC7015002021008AE3A3 /* Cocoa.framework in Frameworks */, 75 | ); 76 | runOnlyForDeploymentPostprocessing = 0; 77 | }; 78 | C2E5DC8815002021008AE3A3 /* Frameworks */ = { 79 | isa = PBXFrameworksBuildPhase; 80 | buildActionMask = 2147483647; 81 | files = ( 82 | C2E5DC8E15002021008AE3A3 /* SenTestingKit.framework in Frameworks */, 83 | C2E5DC8F15002021008AE3A3 /* Cocoa.framework in Frameworks */, 84 | ); 85 | runOnlyForDeploymentPostprocessing = 0; 86 | }; 87 | /* End PBXFrameworksBuildPhase section */ 88 | 89 | /* Begin PBXGroup section */ 90 | C2E5DC6015002021008AE3A3 = { 91 | isa = PBXGroup; 92 | children = ( 93 | C2E5DC7515002021008AE3A3 /* NSRectangle */, 94 | C2E5DC9215002021008AE3A3 /* NSRectangleTests */, 95 | C2E5DC6E15002021008AE3A3 /* Frameworks */, 96 | C2E5DC6C15002021008AE3A3 /* Products */, 97 | ); 98 | sourceTree = ""; 99 | }; 100 | C2E5DC6C15002021008AE3A3 /* Products */ = { 101 | isa = PBXGroup; 102 | children = ( 103 | C2E5DC6B15002021008AE3A3 /* NSRectangle.app */, 104 | C2E5DC8C15002021008AE3A3 /* NSRectangleTests.octest */, 105 | ); 106 | name = Products; 107 | sourceTree = ""; 108 | }; 109 | C2E5DC6E15002021008AE3A3 /* Frameworks */ = { 110 | isa = PBXGroup; 111 | children = ( 112 | C2E5DC6F15002021008AE3A3 /* Cocoa.framework */, 113 | C2E5DC8D15002021008AE3A3 /* SenTestingKit.framework */, 114 | C2E5DC7115002021008AE3A3 /* Other Frameworks */, 115 | ); 116 | name = Frameworks; 117 | sourceTree = ""; 118 | }; 119 | C2E5DC7115002021008AE3A3 /* Other Frameworks */ = { 120 | isa = PBXGroup; 121 | children = ( 122 | C2E5DC7215002021008AE3A3 /* AppKit.framework */, 123 | C2E5DC7315002021008AE3A3 /* CoreData.framework */, 124 | C2E5DC7415002021008AE3A3 /* Foundation.framework */, 125 | ); 126 | name = "Other Frameworks"; 127 | sourceTree = ""; 128 | }; 129 | C2E5DC7515002021008AE3A3 /* NSRectangle */ = { 130 | isa = PBXGroup; 131 | children = ( 132 | C2E5DC8115002021008AE3A3 /* MAAppDelegate.h */, 133 | C2E5DC8215002021008AE3A3 /* MAAppDelegate.m */, 134 | C2E5DCA31500203E008AE3A3 /* MARectangle.h */, 135 | C2E5DCA41500203E008AE3A3 /* MARectangle.m */, 136 | C2E5DCA6150020CD008AE3A3 /* MACoordinateSystem.h */, 137 | C2E5DCA7150020CD008AE3A3 /* MACoordinateSystem.m */, 138 | C2B3C4A815004C3E00742239 /* NSView+MARectangleAdditions.h */, 139 | C2B3C4A915004C3E00742239 /* NSView+MARectangleAdditions.m */, 140 | C2B3C4AC15004ECB00742239 /* NSWindow+MARectangleAdditions.h */, 141 | C2B3C4AD15004ECB00742239 /* NSWindow+MARectangleAdditions.m */, 142 | C2B3C4AF15004F5B00742239 /* NSScreen+MARectangleAdditions.h */, 143 | C2B3C4B015004F5B00742239 /* NSScreen+MARectangleAdditions.m */, 144 | C2E5DC8415002021008AE3A3 /* MainMenu.xib */, 145 | C2E5DC7615002021008AE3A3 /* Supporting Files */, 146 | ); 147 | path = NSRectangle; 148 | sourceTree = ""; 149 | }; 150 | C2E5DC7615002021008AE3A3 /* Supporting Files */ = { 151 | isa = PBXGroup; 152 | children = ( 153 | C2E5DC7715002021008AE3A3 /* NSRectangle-Info.plist */, 154 | C2E5DC7815002021008AE3A3 /* InfoPlist.strings */, 155 | C2E5DC7B15002021008AE3A3 /* main.m */, 156 | C2E5DC7D15002021008AE3A3 /* NSRectangle-Prefix.pch */, 157 | C2E5DC7E15002021008AE3A3 /* Credits.rtf */, 158 | ); 159 | name = "Supporting Files"; 160 | sourceTree = ""; 161 | }; 162 | C2E5DC9215002021008AE3A3 /* NSRectangleTests */ = { 163 | isa = PBXGroup; 164 | children = ( 165 | C2E5DC9815002021008AE3A3 /* NSRectangleTests.h */, 166 | C2E5DC9915002021008AE3A3 /* NSRectangleTests.m */, 167 | C2E5DC9315002021008AE3A3 /* Supporting Files */, 168 | ); 169 | path = NSRectangleTests; 170 | sourceTree = ""; 171 | }; 172 | C2E5DC9315002021008AE3A3 /* Supporting Files */ = { 173 | isa = PBXGroup; 174 | children = ( 175 | C2E5DC9415002021008AE3A3 /* NSRectangleTests-Info.plist */, 176 | C2E5DC9515002021008AE3A3 /* InfoPlist.strings */, 177 | ); 178 | name = "Supporting Files"; 179 | sourceTree = ""; 180 | }; 181 | /* End PBXGroup section */ 182 | 183 | /* Begin PBXNativeTarget section */ 184 | C2E5DC6A15002021008AE3A3 /* NSRectangle */ = { 185 | isa = PBXNativeTarget; 186 | buildConfigurationList = C2E5DC9D15002021008AE3A3 /* Build configuration list for PBXNativeTarget "NSRectangle" */; 187 | buildPhases = ( 188 | C2E5DC6715002021008AE3A3 /* Sources */, 189 | C2E5DC6815002021008AE3A3 /* Frameworks */, 190 | C2E5DC6915002021008AE3A3 /* Resources */, 191 | ); 192 | buildRules = ( 193 | ); 194 | dependencies = ( 195 | ); 196 | name = NSRectangle; 197 | productName = NSRectangle; 198 | productReference = C2E5DC6B15002021008AE3A3 /* NSRectangle.app */; 199 | productType = "com.apple.product-type.application"; 200 | }; 201 | C2E5DC8B15002021008AE3A3 /* NSRectangleTests */ = { 202 | isa = PBXNativeTarget; 203 | buildConfigurationList = C2E5DCA015002021008AE3A3 /* Build configuration list for PBXNativeTarget "NSRectangleTests" */; 204 | buildPhases = ( 205 | C2E5DC8715002021008AE3A3 /* Sources */, 206 | C2E5DC8815002021008AE3A3 /* Frameworks */, 207 | C2E5DC8915002021008AE3A3 /* Resources */, 208 | C2E5DC8A15002021008AE3A3 /* ShellScript */, 209 | ); 210 | buildRules = ( 211 | ); 212 | dependencies = ( 213 | C2E5DC9115002021008AE3A3 /* PBXTargetDependency */, 214 | ); 215 | name = NSRectangleTests; 216 | productName = NSRectangleTests; 217 | productReference = C2E5DC8C15002021008AE3A3 /* NSRectangleTests.octest */; 218 | productType = "com.apple.product-type.bundle"; 219 | }; 220 | /* End PBXNativeTarget section */ 221 | 222 | /* Begin PBXProject section */ 223 | C2E5DC6215002021008AE3A3 /* Project object */ = { 224 | isa = PBXProject; 225 | attributes = { 226 | CLASSPREFIX = MA; 227 | LastUpgradeCheck = 0430; 228 | }; 229 | buildConfigurationList = C2E5DC6515002021008AE3A3 /* Build configuration list for PBXProject "NSRectangle" */; 230 | compatibilityVersion = "Xcode 3.2"; 231 | developmentRegion = English; 232 | hasScannedForEncodings = 0; 233 | knownRegions = ( 234 | en, 235 | ); 236 | mainGroup = C2E5DC6015002021008AE3A3; 237 | productRefGroup = C2E5DC6C15002021008AE3A3 /* Products */; 238 | projectDirPath = ""; 239 | projectRoot = ""; 240 | targets = ( 241 | C2E5DC6A15002021008AE3A3 /* NSRectangle */, 242 | C2E5DC8B15002021008AE3A3 /* NSRectangleTests */, 243 | ); 244 | }; 245 | /* End PBXProject section */ 246 | 247 | /* Begin PBXResourcesBuildPhase section */ 248 | C2E5DC6915002021008AE3A3 /* Resources */ = { 249 | isa = PBXResourcesBuildPhase; 250 | buildActionMask = 2147483647; 251 | files = ( 252 | C2E5DC7A15002021008AE3A3 /* InfoPlist.strings in Resources */, 253 | C2E5DC8015002021008AE3A3 /* Credits.rtf in Resources */, 254 | C2E5DC8615002021008AE3A3 /* MainMenu.xib in Resources */, 255 | ); 256 | runOnlyForDeploymentPostprocessing = 0; 257 | }; 258 | C2E5DC8915002021008AE3A3 /* Resources */ = { 259 | isa = PBXResourcesBuildPhase; 260 | buildActionMask = 2147483647; 261 | files = ( 262 | C2E5DC9715002021008AE3A3 /* InfoPlist.strings in Resources */, 263 | ); 264 | runOnlyForDeploymentPostprocessing = 0; 265 | }; 266 | /* End PBXResourcesBuildPhase section */ 267 | 268 | /* Begin PBXShellScriptBuildPhase section */ 269 | C2E5DC8A15002021008AE3A3 /* ShellScript */ = { 270 | isa = PBXShellScriptBuildPhase; 271 | buildActionMask = 2147483647; 272 | files = ( 273 | ); 274 | inputPaths = ( 275 | ); 276 | outputPaths = ( 277 | ); 278 | runOnlyForDeploymentPostprocessing = 0; 279 | shellPath = /bin/sh; 280 | shellScript = "# Run the unit tests in this test bundle.\n\"${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests\"\n"; 281 | }; 282 | /* End PBXShellScriptBuildPhase section */ 283 | 284 | /* Begin PBXSourcesBuildPhase section */ 285 | C2E5DC6715002021008AE3A3 /* Sources */ = { 286 | isa = PBXSourcesBuildPhase; 287 | buildActionMask = 2147483647; 288 | files = ( 289 | C2E5DC7C15002021008AE3A3 /* main.m in Sources */, 290 | C2E5DC8315002021008AE3A3 /* MAAppDelegate.m in Sources */, 291 | C2E5DCA51500203E008AE3A3 /* MARectangle.m in Sources */, 292 | C2E5DCA8150020CD008AE3A3 /* MACoordinateSystem.m in Sources */, 293 | C2B3C4AA15004C3E00742239 /* NSView+MARectangleAdditions.m in Sources */, 294 | C2B3C4AE15004ECB00742239 /* NSWindow+MARectangleAdditions.m in Sources */, 295 | C2B3C4B115004F5B00742239 /* NSScreen+MARectangleAdditions.m in Sources */, 296 | ); 297 | runOnlyForDeploymentPostprocessing = 0; 298 | }; 299 | C2E5DC8715002021008AE3A3 /* Sources */ = { 300 | isa = PBXSourcesBuildPhase; 301 | buildActionMask = 2147483647; 302 | files = ( 303 | C2E5DC9A15002021008AE3A3 /* NSRectangleTests.m in Sources */, 304 | ); 305 | runOnlyForDeploymentPostprocessing = 0; 306 | }; 307 | /* End PBXSourcesBuildPhase section */ 308 | 309 | /* Begin PBXTargetDependency section */ 310 | C2E5DC9115002021008AE3A3 /* PBXTargetDependency */ = { 311 | isa = PBXTargetDependency; 312 | target = C2E5DC6A15002021008AE3A3 /* NSRectangle */; 313 | targetProxy = C2E5DC9015002021008AE3A3 /* PBXContainerItemProxy */; 314 | }; 315 | /* End PBXTargetDependency section */ 316 | 317 | /* Begin PBXVariantGroup section */ 318 | C2E5DC7815002021008AE3A3 /* InfoPlist.strings */ = { 319 | isa = PBXVariantGroup; 320 | children = ( 321 | C2E5DC7915002021008AE3A3 /* en */, 322 | ); 323 | name = InfoPlist.strings; 324 | sourceTree = ""; 325 | }; 326 | C2E5DC7E15002021008AE3A3 /* Credits.rtf */ = { 327 | isa = PBXVariantGroup; 328 | children = ( 329 | C2E5DC7F15002021008AE3A3 /* en */, 330 | ); 331 | name = Credits.rtf; 332 | sourceTree = ""; 333 | }; 334 | C2E5DC8415002021008AE3A3 /* MainMenu.xib */ = { 335 | isa = PBXVariantGroup; 336 | children = ( 337 | C2E5DC8515002021008AE3A3 /* en */, 338 | ); 339 | name = MainMenu.xib; 340 | sourceTree = ""; 341 | }; 342 | C2E5DC9515002021008AE3A3 /* InfoPlist.strings */ = { 343 | isa = PBXVariantGroup; 344 | children = ( 345 | C2E5DC9615002021008AE3A3 /* en */, 346 | ); 347 | name = InfoPlist.strings; 348 | sourceTree = ""; 349 | }; 350 | /* End PBXVariantGroup section */ 351 | 352 | /* Begin XCBuildConfiguration section */ 353 | C2E5DC9B15002021008AE3A3 /* Debug */ = { 354 | isa = XCBuildConfiguration; 355 | buildSettings = { 356 | ALWAYS_SEARCH_USER_PATHS = NO; 357 | ARCHS = "$(ARCHS_STANDARD_64_BIT)"; 358 | CLANG_ENABLE_OBJC_ARC = YES; 359 | COPY_PHASE_STRIP = NO; 360 | GCC_C_LANGUAGE_STANDARD = gnu99; 361 | GCC_DYNAMIC_NO_PIC = NO; 362 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 363 | GCC_OPTIMIZATION_LEVEL = 0; 364 | GCC_PREPROCESSOR_DEFINITIONS = ( 365 | "DEBUG=1", 366 | "$(inherited)", 367 | ); 368 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 369 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 370 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 371 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 372 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 373 | GCC_WARN_UNUSED_VARIABLE = YES; 374 | MACOSX_DEPLOYMENT_TARGET = 10.7; 375 | ONLY_ACTIVE_ARCH = YES; 376 | SDKROOT = macosx; 377 | }; 378 | name = Debug; 379 | }; 380 | C2E5DC9C15002021008AE3A3 /* Release */ = { 381 | isa = XCBuildConfiguration; 382 | buildSettings = { 383 | ALWAYS_SEARCH_USER_PATHS = NO; 384 | ARCHS = "$(ARCHS_STANDARD_64_BIT)"; 385 | CLANG_ENABLE_OBJC_ARC = YES; 386 | COPY_PHASE_STRIP = YES; 387 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 388 | GCC_C_LANGUAGE_STANDARD = gnu99; 389 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 390 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 391 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 392 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 393 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 394 | GCC_WARN_UNUSED_VARIABLE = YES; 395 | MACOSX_DEPLOYMENT_TARGET = 10.7; 396 | SDKROOT = macosx; 397 | }; 398 | name = Release; 399 | }; 400 | C2E5DC9E15002021008AE3A3 /* Debug */ = { 401 | isa = XCBuildConfiguration; 402 | buildSettings = { 403 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 404 | GCC_PREFIX_HEADER = "NSRectangle/NSRectangle-Prefix.pch"; 405 | INFOPLIST_FILE = "NSRectangle/NSRectangle-Info.plist"; 406 | PRODUCT_NAME = "$(TARGET_NAME)"; 407 | WRAPPER_EXTENSION = app; 408 | }; 409 | name = Debug; 410 | }; 411 | C2E5DC9F15002021008AE3A3 /* Release */ = { 412 | isa = XCBuildConfiguration; 413 | buildSettings = { 414 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 415 | GCC_PREFIX_HEADER = "NSRectangle/NSRectangle-Prefix.pch"; 416 | INFOPLIST_FILE = "NSRectangle/NSRectangle-Info.plist"; 417 | PRODUCT_NAME = "$(TARGET_NAME)"; 418 | WRAPPER_EXTENSION = app; 419 | }; 420 | name = Release; 421 | }; 422 | C2E5DCA115002021008AE3A3 /* Debug */ = { 423 | isa = XCBuildConfiguration; 424 | buildSettings = { 425 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/NSRectangle.app/Contents/MacOS/NSRectangle"; 426 | FRAMEWORK_SEARCH_PATHS = "$(DEVELOPER_LIBRARY_DIR)/Frameworks"; 427 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 428 | GCC_PREFIX_HEADER = "NSRectangle/NSRectangle-Prefix.pch"; 429 | INFOPLIST_FILE = "NSRectangleTests/NSRectangleTests-Info.plist"; 430 | PRODUCT_NAME = "$(TARGET_NAME)"; 431 | TEST_HOST = "$(BUNDLE_LOADER)"; 432 | WRAPPER_EXTENSION = octest; 433 | }; 434 | name = Debug; 435 | }; 436 | C2E5DCA215002021008AE3A3 /* Release */ = { 437 | isa = XCBuildConfiguration; 438 | buildSettings = { 439 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/NSRectangle.app/Contents/MacOS/NSRectangle"; 440 | FRAMEWORK_SEARCH_PATHS = "$(DEVELOPER_LIBRARY_DIR)/Frameworks"; 441 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 442 | GCC_PREFIX_HEADER = "NSRectangle/NSRectangle-Prefix.pch"; 443 | INFOPLIST_FILE = "NSRectangleTests/NSRectangleTests-Info.plist"; 444 | PRODUCT_NAME = "$(TARGET_NAME)"; 445 | TEST_HOST = "$(BUNDLE_LOADER)"; 446 | WRAPPER_EXTENSION = octest; 447 | }; 448 | name = Release; 449 | }; 450 | /* End XCBuildConfiguration section */ 451 | 452 | /* Begin XCConfigurationList section */ 453 | C2E5DC6515002021008AE3A3 /* Build configuration list for PBXProject "NSRectangle" */ = { 454 | isa = XCConfigurationList; 455 | buildConfigurations = ( 456 | C2E5DC9B15002021008AE3A3 /* Debug */, 457 | C2E5DC9C15002021008AE3A3 /* Release */, 458 | ); 459 | defaultConfigurationIsVisible = 0; 460 | defaultConfigurationName = Release; 461 | }; 462 | C2E5DC9D15002021008AE3A3 /* Build configuration list for PBXNativeTarget "NSRectangle" */ = { 463 | isa = XCConfigurationList; 464 | buildConfigurations = ( 465 | C2E5DC9E15002021008AE3A3 /* Debug */, 466 | C2E5DC9F15002021008AE3A3 /* Release */, 467 | ); 468 | defaultConfigurationIsVisible = 0; 469 | defaultConfigurationName = Release; 470 | }; 471 | C2E5DCA015002021008AE3A3 /* Build configuration list for PBXNativeTarget "NSRectangleTests" */ = { 472 | isa = XCConfigurationList; 473 | buildConfigurations = ( 474 | C2E5DCA115002021008AE3A3 /* Debug */, 475 | C2E5DCA215002021008AE3A3 /* Release */, 476 | ); 477 | defaultConfigurationIsVisible = 0; 478 | defaultConfigurationName = Release; 479 | }; 480 | /* End XCConfigurationList section */ 481 | }; 482 | rootObject = C2E5DC6215002021008AE3A3 /* Project object */; 483 | } 484 | -------------------------------------------------------------------------------- /NSRectangle/MAAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // MAAppDelegate.h 3 | // NSRectangle 4 | // 5 | // Created by Michael Ash on 3/1/12. 6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface MAAppDelegate : NSObject 12 | 13 | @property (assign) IBOutlet NSWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /NSRectangle/MAAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // MAAppDelegate.m 3 | // NSRectangle 4 | // 5 | // Created by Michael Ash on 3/1/12. 6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import "MAAppDelegate.h" 10 | 11 | #import "MARectangle.h" 12 | #import "NSScreen+MARectangleAdditions.h" 13 | #import "NSView+MARectangleAdditions.h" 14 | #import "NSWindow+MARectangleAdditions.h" 15 | 16 | 17 | @interface TestView : NSView @end 18 | @implementation TestView 19 | 20 | - (void)drawRect: (NSRect)r 21 | { 22 | NSRect bounds = [self bounds]; 23 | [[NSColor redColor] setStroke]; 24 | [NSBezierPath strokeLineFromPoint: bounds.origin toPoint: NSMakePoint(NSMaxX(bounds), NSMaxY(bounds))]; 25 | } 26 | 27 | @end 28 | 29 | @implementation MAAppDelegate { 30 | NSWindow *w; 31 | } 32 | 33 | @synthesize window = _window; 34 | 35 | - (void)applicationDidFinishLaunching:(NSNotification *)aNotification 36 | { 37 | TestView *v = [[TestView alloc] init]; 38 | [[_window contentView] addSubview: v]; 39 | [v ma_setFrameRectangle: [[_window contentView] ma_frameRectangle]]; 40 | 41 | MARectangle *newWindowRect = [[v ma_frameRectangle] withSize: [MASize sizeWithNSSize: NSMakeSize(50, 50) coordinateSystem: [NSScreen ma_coordinateSystem]]]; 42 | w = [[NSWindow alloc] initWithContentMARectangle: newWindowRect styleMask: NSTitledWindowMask backing: NSBackingStoreBuffered defer: YES]; 43 | TestView *v2 = [[TestView alloc] init]; 44 | [[w contentView] addSubview: v2]; 45 | [v2 ma_setFrameRectangle: [[w contentView] ma_frameRectangle]]; 46 | [w makeKeyAndOrderFront: nil]; 47 | } 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /NSRectangle/MACoordinateSystem.h: -------------------------------------------------------------------------------- 1 | // 2 | // MACoordinateSystem.h 3 | // NSRectangle 4 | // 5 | // Created by Michael Ash on 3/1/12. 6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface MACoordinateSystem : NSObject 12 | 13 | - (instancetype)initWithScreenCoordinateSystem; 14 | - (instancetype)initWithWindow: (NSWindow *)window; 15 | - (instancetype)initWithView: (NSView *)view; 16 | 17 | - (NSRect)convertRect: (NSRect)r toCoordinateSystem: (MACoordinateSystem *)coordinateSystem; 18 | - (NSPoint)convertPoint: (NSPoint)p toCoordinateSystem: (MACoordinateSystem *)coordinateSystem; 19 | - (NSSize)convertSize: (NSSize)s toCoordinateSystem: (MACoordinateSystem *)coordinateSystem; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /NSRectangle/MACoordinateSystem.m: -------------------------------------------------------------------------------- 1 | // 2 | // MACoordinateSystem.m 3 | // NSRectangle 4 | // 5 | // Created by Michael Ash on 3/1/12. 6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import "MACoordinateSystem.h" 10 | 11 | @protocol _MACoordinateAdjacentConversion 12 | 13 | - (NSRect)MACoordinateAdjacentConversion_convertRect: (NSRect)r to: (id <_MACoordinateAdjacentConversion>)target; 14 | 15 | - (void)MACoordinateAdjacentConversion_enumerateConversionChainTo: (id <_MACoordinateAdjacentConversion>)target withBlock: (void (^)(id <_MACoordinateAdjacentConversion> nextTarget))block; 16 | 17 | - (BOOL)MACoordinateAdjacentConversion_isView; 18 | - (BOOL)MACoordinateAdjacentConversion_isWindow; 19 | - (BOOL)MACoordinateAdjacentConversion_isScreen; 20 | 21 | @end 22 | 23 | @interface _MACoordinateSystemScreen : NSObject <_MACoordinateAdjacentConversion> 24 | + (_MACoordinateSystemScreen *)screen; 25 | @end 26 | @interface NSWindow (_MACoordinateAdjacentConversion) <_MACoordinateAdjacentConversion> 27 | @end 28 | @interface NSView (_MACoordinateAdjacentConversion) <_MACoordinateAdjacentConversion> 29 | @end 30 | 31 | @implementation _MACoordinateSystemScreen 32 | 33 | + (_MACoordinateSystemScreen *)screen 34 | { 35 | static _MACoordinateSystemScreen *screen; 36 | static dispatch_once_t pred; 37 | dispatch_once(&pred, ^{ screen = [[self alloc] init]; }); 38 | return screen; 39 | } 40 | 41 | - (NSRect)MACoordinateAdjacentConversion_convertRect: (NSRect)r to: (id <_MACoordinateAdjacentConversion>)target 42 | { 43 | if([target MACoordinateAdjacentConversion_isScreen]) 44 | return r; 45 | else if([target MACoordinateAdjacentConversion_isWindow]) 46 | return [(NSWindow *)target convertRectFromScreen: r]; 47 | 48 | NSLog(@"Cannot convert directly from screen to target %@", target); 49 | abort(); 50 | } 51 | 52 | - (void)MACoordinateAdjacentConversion_enumerateConversionChainTo: (id <_MACoordinateAdjacentConversion>)target withBlock: (void (^)(id <_MACoordinateAdjacentConversion> nextTarget))block 53 | { 54 | if([target MACoordinateAdjacentConversion_isWindow]) 55 | { 56 | block(target); 57 | } 58 | else if([target MACoordinateAdjacentConversion_isView]) 59 | { 60 | block([(NSView *)target window]); 61 | [target MACoordinateAdjacentConversion_enumerateConversionChainTo: target withBlock: block]; 62 | } 63 | } 64 | 65 | - (BOOL)MACoordinateAdjacentConversion_isView 66 | { 67 | return NO; 68 | } 69 | 70 | - (BOOL)MACoordinateAdjacentConversion_isWindow 71 | { 72 | return NO; 73 | } 74 | 75 | - (BOOL)MACoordinateAdjacentConversion_isScreen 76 | { 77 | return YES; 78 | } 79 | 80 | @end 81 | 82 | @implementation NSWindow (_MACoordinateAdjacentConversion) 83 | 84 | - (NSRect)MACoordinateAdjacentConversion_convertRect: (NSRect)r to: (id <_MACoordinateAdjacentConversion>)target 85 | { 86 | if([target MACoordinateAdjacentConversion_isScreen]) 87 | return [self convertRectToScreen: r]; 88 | else if([target MACoordinateAdjacentConversion_isView]) 89 | return [(NSView *)target convertRect: r fromView: nil]; 90 | 91 | NSLog(@"Cannot convert directly from window %@ to target %@", self, target); 92 | abort(); 93 | } 94 | 95 | - (void)MACoordinateAdjacentConversion_enumerateConversionChainTo: (id <_MACoordinateAdjacentConversion>)target withBlock: (void (^)(id <_MACoordinateAdjacentConversion> nextTarget))block 96 | { 97 | if([target MACoordinateAdjacentConversion_isView] && [(NSView *)target window] == self) 98 | { 99 | block(target); 100 | } 101 | else 102 | { 103 | block([_MACoordinateSystemScreen screen]); 104 | if(target != [_MACoordinateSystemScreen screen]) 105 | [[_MACoordinateSystemScreen screen] MACoordinateAdjacentConversion_enumerateConversionChainTo: target withBlock: block]; 106 | } 107 | } 108 | 109 | - (BOOL)MACoordinateAdjacentConversion_isView 110 | { 111 | return NO; 112 | } 113 | 114 | - (BOOL)MACoordinateAdjacentConversion_isWindow 115 | { 116 | return YES; 117 | } 118 | 119 | - (BOOL)MACoordinateAdjacentConversion_isScreen 120 | { 121 | return NO; 122 | } 123 | 124 | @end 125 | 126 | @implementation NSView (_MACoordinateAdjacentConversion) 127 | 128 | - (NSRect)MACoordinateAdjacentConversion_convertRect: (NSRect)r to: (id <_MACoordinateAdjacentConversion>)target 129 | { 130 | if([target MACoordinateAdjacentConversion_isView]) 131 | return [self convertRect: r toView: (NSView *)target]; 132 | else if([target MACoordinateAdjacentConversion_isWindow]) 133 | return [self convertRect: r toView: nil]; 134 | 135 | NSLog(@"Cannot convert directly from view %@ to target %@", self, target); 136 | abort(); 137 | } 138 | 139 | - (void)MACoordinateAdjacentConversion_enumerateConversionChainTo: (id <_MACoordinateAdjacentConversion>)target withBlock: (void (^)(id <_MACoordinateAdjacentConversion> nextTarget))block 140 | { 141 | if([target MACoordinateAdjacentConversion_isView] && [self ancestorSharedWithView: (NSView *)target]) 142 | { 143 | block(target); 144 | } 145 | else 146 | { 147 | block([self window]); 148 | if(target != [self window]) 149 | [[self window] MACoordinateAdjacentConversion_enumerateConversionChainTo: target withBlock: block]; 150 | } 151 | } 152 | 153 | - (BOOL)MACoordinateAdjacentConversion_isView 154 | { 155 | return YES; 156 | } 157 | 158 | - (BOOL)MACoordinateAdjacentConversion_isWindow 159 | { 160 | return NO; 161 | } 162 | 163 | - (BOOL)MACoordinateAdjacentConversion_isScreen 164 | { 165 | return NO; 166 | } 167 | 168 | @end 169 | 170 | @implementation MACoordinateSystem { 171 | id <_MACoordinateAdjacentConversion> _underlyingTarget; 172 | } 173 | 174 | - (instancetype)initWithTarget: (id <_MACoordinateAdjacentConversion>)target 175 | { 176 | if((self = [super init])) 177 | { 178 | _underlyingTarget = target; 179 | } 180 | return self; 181 | } 182 | 183 | - (instancetype)initWithScreenCoordinateSystem 184 | { 185 | return [self initWithTarget: [_MACoordinateSystemScreen screen]]; 186 | } 187 | 188 | - (instancetype)initWithWindow: (NSWindow *)window 189 | { 190 | return [self initWithTarget: window]; 191 | } 192 | 193 | - (instancetype)initWithView: (NSView *)view 194 | { 195 | return [self initWithTarget: view]; 196 | } 197 | 198 | - (NSString *)description 199 | { 200 | return [NSString stringWithFormat: @"<%@ %p: %@>", [self class], self, _underlyingTarget]; 201 | } 202 | 203 | - (NSRect)convertRect: (NSRect)r toCoordinateSystem: (MACoordinateSystem *)coordinateSystem 204 | { 205 | __block NSRect result = r; 206 | __block id <_MACoordinateAdjacentConversion> previousTarget = _underlyingTarget; 207 | [_underlyingTarget 208 | MACoordinateAdjacentConversion_enumerateConversionChainTo: coordinateSystem->_underlyingTarget 209 | withBlock: ^(id<_MACoordinateAdjacentConversion> nextTarget) { 210 | result = [previousTarget MACoordinateAdjacentConversion_convertRect: result to: nextTarget]; 211 | previousTarget = nextTarget; 212 | }]; 213 | return result; 214 | } 215 | 216 | - (NSPoint)convertPoint: (NSPoint)p toCoordinateSystem: (MACoordinateSystem *)coordinateSystem 217 | { 218 | return [self convertRect: (NSRect){ p, NSZeroSize } toCoordinateSystem: coordinateSystem].origin; 219 | } 220 | 221 | - (NSSize)convertSize: (NSSize)s toCoordinateSystem: (MACoordinateSystem *)coordinateSystem 222 | { 223 | return [self convertRect: (NSRect){ NSZeroPoint, s } toCoordinateSystem: coordinateSystem].size; 224 | 225 | } 226 | 227 | @end 228 | -------------------------------------------------------------------------------- /NSRectangle/MARectangle.h: -------------------------------------------------------------------------------- 1 | // 2 | // MARectangle.h 3 | // NSRectangle 4 | // 5 | // Created by Michael Ash on 3/1/12. 6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @class MACoordinateSystem; 13 | 14 | @interface MATwoElementCoordinate : NSObject 15 | 16 | - (instancetype)initWithElements: (CGFloat[2])elements coordinateSystem: (MACoordinateSystem *)coordinateSystem; 17 | - (CGFloat *)elements; 18 | - (MACoordinateSystem *)coordinateSystem; 19 | 20 | @end 21 | 22 | @interface MAPoint : MATwoElementCoordinate 23 | 24 | + (instancetype)pointWithNSPoint: (NSPoint)p coordinateSystem: (MACoordinateSystem *)coordinateSystem; 25 | - (NSPoint)pointValueInCoordinateSystem: (MACoordinateSystem *)coordinateSystem; 26 | 27 | @end 28 | 29 | @interface MASize : MATwoElementCoordinate 30 | 31 | + (instancetype)sizeWithNSSize: (NSSize)s coordinateSystem: (MACoordinateSystem *)coordinateSystem; 32 | - (NSSize)sizeValueInCoordinateSystem: (MACoordinateSystem *)coordinateSystem; 33 | 34 | @end 35 | 36 | 37 | @interface MARectangle : NSObject 38 | 39 | + (instancetype)rectangleWithRect: (NSRect)r coordinateSystem: (MACoordinateSystem *)coordinateSystem; 40 | - (instancetype)initWithRect: (NSRect)r coordinateSystem: (MACoordinateSystem *)coordinateSystem; 41 | 42 | - (NSRect)rectValueInCoordinateSystem: (MACoordinateSystem *)coordinateSystem; 43 | 44 | - (instancetype)byAddingSizeToOrigin: (MASize *)size; 45 | 46 | - (instancetype)byAddingX: (CGFloat)delta; 47 | - (instancetype)byAddingX: (CGFloat)delta inCoordinateSystem: (MACoordinateSystem *)coordinateSystem; 48 | - (instancetype)byAddingY: (CGFloat)delta; 49 | - (instancetype)byAddingY: (CGFloat)delta inCoordinateSystem: (MACoordinateSystem *)coordinateSystem; 50 | 51 | - (instancetype)withOrigin: (MAPoint *)point; 52 | - (instancetype)withSize: (MASize *)size; 53 | 54 | @end 55 | -------------------------------------------------------------------------------- /NSRectangle/MARectangle.m: -------------------------------------------------------------------------------- 1 | // 2 | // MARectangle.m 3 | // NSRectangle 4 | // 5 | // Created by Michael Ash on 3/1/12. 6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import "MARectangle.h" 10 | 11 | #import "MACoordinateSystem.h" 12 | 13 | 14 | @implementation MATwoElementCoordinate { 15 | @protected 16 | CGFloat _elements[2]; 17 | MACoordinateSystem *_coordinateSystem; 18 | } 19 | 20 | - (instancetype)initWithElements: (CGFloat[2])elements coordinateSystem: (MACoordinateSystem *)coordinateSystem 21 | { 22 | if((self = [super init])) 23 | { 24 | memcpy(_elements, elements, sizeof(_elements)); 25 | _coordinateSystem = coordinateSystem; 26 | } 27 | return self; 28 | } 29 | 30 | - (NSString *)description 31 | { 32 | return [NSString stringWithFormat: @"<%@ %p: (%f, %f) %@>", [self class], self, _elements[0], _elements[1], _coordinateSystem]; 33 | } 34 | 35 | - (CGFloat *)elements 36 | { 37 | return _elements; 38 | } 39 | 40 | - (MACoordinateSystem *)coordinateSystem 41 | { 42 | return _coordinateSystem; 43 | } 44 | 45 | @end 46 | 47 | @implementation MAPoint 48 | 49 | + (instancetype)pointWithNSPoint: (NSPoint)p coordinateSystem: (MACoordinateSystem *)coordinateSystem 50 | { 51 | return [[self alloc] initWithElements: (CGFloat *)&p coordinateSystem: coordinateSystem]; 52 | } 53 | 54 | - (NSPoint)pointValueInCoordinateSystem: (MACoordinateSystem *)coordinateSystem 55 | { 56 | NSPoint point = *(NSPoint *)_elements; 57 | return [_coordinateSystem convertPoint: point toCoordinateSystem: coordinateSystem]; 58 | } 59 | 60 | @end 61 | 62 | @implementation MASize 63 | 64 | + (instancetype)sizeWithNSSize: (NSSize)s coordinateSystem: (MACoordinateSystem *)coordinateSystem 65 | { 66 | return [[self alloc] initWithElements: (CGFloat *)&s coordinateSystem: coordinateSystem]; 67 | } 68 | 69 | - (NSSize)sizeValueInCoordinateSystem: (MACoordinateSystem *)coordinateSystem 70 | { 71 | NSSize size = *(NSSize *)_elements; 72 | return [_coordinateSystem convertSize: size toCoordinateSystem: coordinateSystem]; 73 | } 74 | 75 | @end 76 | 77 | @implementation MARectangle { 78 | NSRect _r; 79 | MACoordinateSystem *_coordinateSystem; 80 | } 81 | 82 | + (instancetype)rectangleWithRect: (NSRect)r coordinateSystem: (MACoordinateSystem *)coordinateSystem 83 | { 84 | return [[self alloc] initWithRect: r coordinateSystem: coordinateSystem]; 85 | } 86 | 87 | - (instancetype)initWithRect: (NSRect)r coordinateSystem: (MACoordinateSystem *)coordinateSystem 88 | { 89 | if((self = [super init])) 90 | { 91 | _r = r; 92 | _coordinateSystem = coordinateSystem; 93 | } 94 | return self; 95 | } 96 | 97 | - (NSString *)description 98 | { 99 | return [NSString stringWithFormat: @"<%@ %p: %@ %@>", [self class], self, NSStringFromRect(_r), _coordinateSystem]; 100 | } 101 | 102 | - (NSRect)rectValueInCoordinateSystem: (MACoordinateSystem *)coordinateSystem 103 | { 104 | return [_coordinateSystem convertRect: _r toCoordinateSystem: coordinateSystem]; 105 | } 106 | 107 | - (instancetype)byAddingSizeToOrigin: (MASize *)size 108 | { 109 | NSSize delta = [size sizeValueInCoordinateSystem: _coordinateSystem]; 110 | NSRect newR = NSOffsetRect(_r, delta.width, delta.height); 111 | return [[self class] rectangleWithRect: newR coordinateSystem: _coordinateSystem]; 112 | } 113 | 114 | - (instancetype)byAddingX: (CGFloat)delta 115 | { 116 | return [self byAddingX: delta inCoordinateSystem: _coordinateSystem]; 117 | } 118 | 119 | - (instancetype)byAddingX: (CGFloat)delta inCoordinateSystem: (MACoordinateSystem *)coordinateSystem 120 | { 121 | MASize *size = [MASize sizeWithNSSize: NSMakeSize(delta, 0) coordinateSystem: coordinateSystem]; 122 | return [self byAddingSizeToOrigin: size]; 123 | } 124 | 125 | - (instancetype)byAddingY: (CGFloat)delta 126 | { 127 | return [self byAddingY: delta inCoordinateSystem: _coordinateSystem]; 128 | } 129 | 130 | - (instancetype)byAddingY: (CGFloat)delta inCoordinateSystem: (MACoordinateSystem *)coordinateSystem 131 | { 132 | MASize *size = [MASize sizeWithNSSize: NSMakeSize(0, delta) coordinateSystem: coordinateSystem]; 133 | return [self byAddingSizeToOrigin: size]; 134 | } 135 | 136 | - (instancetype)withOrigin: (MAPoint *)point 137 | { 138 | NSPoint origin = [point pointValueInCoordinateSystem: _coordinateSystem]; 139 | NSRect newR = { origin, _r.size }; 140 | return [[self class] rectangleWithRect: newR coordinateSystem: _coordinateSystem]; 141 | } 142 | 143 | - (instancetype)withSize: (MASize *)size 144 | { 145 | NSSize s = [size sizeValueInCoordinateSystem: _coordinateSystem]; 146 | NSRect newR = { _r.origin, s }; 147 | return [[self class] rectangleWithRect: newR coordinateSystem: _coordinateSystem]; 148 | } 149 | 150 | @end 151 | -------------------------------------------------------------------------------- /NSRectangle/NSRectangle-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | com.mikeash.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSMinimumSystemVersion 26 | ${MACOSX_DEPLOYMENT_TARGET} 27 | NSHumanReadableCopyright 28 | Copyright © 2012 __MyCompanyName__. All rights reserved. 29 | NSMainNibFile 30 | MainMenu 31 | NSPrincipalClass 32 | NSApplication 33 | 34 | 35 | -------------------------------------------------------------------------------- /NSRectangle/NSRectangle-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'NSRectangle' target in the 'NSRectangle' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | -------------------------------------------------------------------------------- /NSRectangle/NSScreen+MARectangleAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSScreen+MARectangleAdditions.h 3 | // NSRectangle 4 | // 5 | // Created by Michael Ash on 3/1/12. 6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class MACoordinateSystem; 12 | 13 | 14 | @interface NSScreen (MARectangleAdditions) 15 | 16 | + (MACoordinateSystem *)ma_coordinateSystem; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /NSRectangle/NSScreen+MARectangleAdditions.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSScreen+MARectangleAdditions.m 3 | // NSRectangle 4 | // 5 | // Created by Michael Ash on 3/1/12. 6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import "NSScreen+MARectangleAdditions.h" 10 | 11 | #import "MACoordinateSystem.h" 12 | 13 | 14 | @implementation NSScreen (MARectangleAdditions) 15 | 16 | + (MACoordinateSystem *)ma_coordinateSystem 17 | { 18 | static MACoordinateSystem *coordinateSystem; 19 | static dispatch_once_t pred; 20 | dispatch_once(&pred, ^{ 21 | coordinateSystem = [[MACoordinateSystem alloc] initWithScreenCoordinateSystem]; 22 | }); 23 | return coordinateSystem; 24 | } 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /NSRectangle/NSView+MARectangleAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSView+MARectangleAdditions.h 3 | // NSRectangle 4 | // 5 | // Created by Michael Ash on 3/1/12. 6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class MACoordinateSystem; 12 | @class MARectangle; 13 | 14 | @interface NSView (MARectangleAdditions) 15 | 16 | - (MACoordinateSystem *)ma_coordinateSystem; 17 | - (MARectangle *)ma_frameRectangle; 18 | - (void)ma_setFrameRectangle: (MARectangle *)rect; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /NSRectangle/NSView+MARectangleAdditions.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSView+MARectangleAdditions.m 3 | // NSRectangle 4 | // 5 | // Created by Michael Ash on 3/1/12. 6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import "NSView+MARectangleAdditions.h" 10 | 11 | #import "MACoordinateSystem.h" 12 | #import "MARectangle.h" 13 | 14 | 15 | @implementation NSView (MARectangleAdditions) 16 | 17 | - (MACoordinateSystem *)ma_coordinateSystem 18 | { 19 | return [[MACoordinateSystem alloc] initWithView: self]; 20 | } 21 | 22 | - (MARectangle *)ma_frameRectangle 23 | { 24 | return [MARectangle rectangleWithRect: [self bounds] coordinateSystem: [self ma_coordinateSystem]]; 25 | } 26 | 27 | - (void)ma_setFrameRectangle: (MARectangle *)rect 28 | { 29 | NSRect r = [rect rectValueInCoordinateSystem: [self ma_coordinateSystem]]; 30 | r = [self convertRect: r toView: [self superview]]; 31 | [self setFrame: r]; 32 | } 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /NSRectangle/NSWindow+MARectangleAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSWindow+MARectangleAdditions.h 3 | // NSRectangle 4 | // 5 | // Created by Michael Ash on 3/1/12. 6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class MACoordinateSystem; 12 | @class MARectangle; 13 | 14 | @interface NSWindow (MARectangleAdditions) 15 | 16 | - (id)initWithContentMARectangle: (MARectangle *)contentRectangle styleMask: (NSUInteger)aStyle backing: (NSBackingStoreType)bufferingType defer: (BOOL)flag; 17 | 18 | - (MACoordinateSystem *)ma_coordinateSystem; 19 | - (MARectangle *)ma_frameRectangle; 20 | - (void)ma_setFrameRectangle: (MARectangle *)rect; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /NSRectangle/NSWindow+MARectangleAdditions.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSWindow+MARectangleAdditions.m 3 | // NSRectangle 4 | // 5 | // Created by Michael Ash on 3/1/12. 6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import "NSWindow+MARectangleAdditions.h" 10 | 11 | #import "MACoordinateSystem.h" 12 | #import "MARectangle.h" 13 | #import "NSScreen+MARectangleAdditions.h" 14 | 15 | 16 | @implementation NSWindow (MARectangleAdditions) 17 | 18 | - (id)initWithContentMARectangle: (MARectangle *)contentRectangle styleMask: (NSUInteger)aStyle backing: (NSBackingStoreType)bufferingType defer: (BOOL)flag 19 | { 20 | NSRect r = [contentRectangle rectValueInCoordinateSystem: [NSScreen ma_coordinateSystem]]; 21 | return [self initWithContentRect: r styleMask: aStyle backing: bufferingType defer: flag]; 22 | } 23 | 24 | - (MACoordinateSystem *)ma_coordinateSystem 25 | { 26 | return [[MACoordinateSystem alloc] initWithWindow: self]; 27 | } 28 | 29 | - (MARectangle *)ma_frameRectangle 30 | { 31 | return [MARectangle rectangleWithRect: [self frame] coordinateSystem: [NSScreen ma_coordinateSystem]]; 32 | } 33 | 34 | - (void)ma_setFrameRectangle: (MARectangle *)rect 35 | { 36 | NSRect r = [rect rectValueInCoordinateSystem: [NSScreen ma_coordinateSystem]]; 37 | [self setFrame: r display: YES]; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /NSRectangle/en.lproj/Credits.rtf: -------------------------------------------------------------------------------- 1 | {\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;} 2 | {\colortbl;\red255\green255\blue255;} 3 | \paperw9840\paperh8400 4 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural 5 | 6 | \f0\b\fs24 \cf0 Engineering: 7 | \b0 \ 8 | Some people\ 9 | \ 10 | 11 | \b Human Interface Design: 12 | \b0 \ 13 | Some other people\ 14 | \ 15 | 16 | \b Testing: 17 | \b0 \ 18 | Hopefully not nobody\ 19 | \ 20 | 21 | \b Documentation: 22 | \b0 \ 23 | Whoever\ 24 | \ 25 | 26 | \b With special thanks to: 27 | \b0 \ 28 | Mom\ 29 | } 30 | -------------------------------------------------------------------------------- /NSRectangle/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /NSRectangle/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // NSRectangle 4 | // 5 | // Created by Michael Ash on 3/1/12. 6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | return NSApplicationMain(argc, (const char **)argv); 14 | } 15 | -------------------------------------------------------------------------------- /NSRectangleTests/NSRectangleTests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | com.mikeash.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /NSRectangleTests/NSRectangleTests.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSRectangleTests.h 3 | // NSRectangleTests 4 | // 5 | // Created by Michael Ash on 3/1/12. 6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSRectangleTests : SenTestCase 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /NSRectangleTests/NSRectangleTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSRectangleTests.m 3 | // NSRectangleTests 4 | // 5 | // Created by Michael Ash on 3/1/12. 6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import "NSRectangleTests.h" 10 | 11 | #import "MACoordinateSystem.h" 12 | #import "MARectangle.h" 13 | 14 | 15 | @implementation NSRectangleTests 16 | 17 | - (void)testSameViewPointSize 18 | { 19 | NSPoint p = { 1, 2 }; 20 | NSSize s = { 3, 4 }; 21 | 22 | NSWindow *w = [[NSWindow alloc] initWithContentRect: NSMakeRect(0, 0, 100, 100) styleMask: 0 backing: NSBackingStoreBuffered defer: YES]; 23 | NSView *v = [[NSView alloc] initWithFrame: NSMakeRect(0, 0, 100, 100)]; 24 | [[w contentView] addSubview: v]; 25 | 26 | MAPoint *pobj = [MAPoint pointWithNSPoint: p coordinateSystem: [[MACoordinateSystem alloc] initWithView: v]]; 27 | MASize *sobj = [MASize sizeWithNSSize: s coordinateSystem: [[MACoordinateSystem alloc] initWithView: v]]; 28 | 29 | STAssertEquals(p, [pobj pointValueInCoordinateSystem: [[MACoordinateSystem alloc] initWithView: v]], @"Points are not equal"); 30 | STAssertEquals(s, [sobj sizeValueInCoordinateSystem: [[MACoordinateSystem alloc] initWithView: v]], @"Sizes are not equal"); 31 | } 32 | 33 | - (void)testDifferentViewPoint 34 | { 35 | NSPoint p = { 1, 2 }; 36 | 37 | NSWindow *w = [[NSWindow alloc] initWithContentRect: NSMakeRect(0, 0, 100, 100) styleMask: 0 backing: NSBackingStoreBuffered defer: YES]; 38 | NSView *v = [[NSView alloc] initWithFrame: NSMakeRect(0, 0, 100, 100)]; 39 | NSView *v2 = [[NSView alloc] initWithFrame: NSMakeRect(50, 50, 100, 100)]; 40 | [[w contentView] addSubview: v]; 41 | [[w contentView] addSubview: v2]; 42 | 43 | MAPoint *pobj = [MAPoint pointWithNSPoint: p coordinateSystem: [[MACoordinateSystem alloc] initWithView: v]]; 44 | 45 | STAssertEquals(NSMakePoint(-49, -48), [pobj pointValueInCoordinateSystem: [[MACoordinateSystem alloc] initWithView: v2]], @"Points are not equal"); 46 | } 47 | 48 | - (void)testDifferentViewSize 49 | { 50 | NSSize s = { 1, 2 }; 51 | 52 | NSWindow *w = [[NSWindow alloc] initWithContentRect: NSMakeRect(0, 0, 100, 100) styleMask: 0 backing: NSBackingStoreBuffered defer: YES]; 53 | NSView *v = [[NSView alloc] initWithFrame: NSMakeRect(0, 0, 100, 100)]; 54 | NSView *v2 = [[NSView alloc] initWithFrame: NSMakeRect(50, 50, 100, 100)]; 55 | [v2 scaleUnitSquareToSize: NSMakeSize(2, 2)]; 56 | [[w contentView] addSubview: v]; 57 | [[w contentView] addSubview: v2]; 58 | 59 | MASize *sobj = [MASize sizeWithNSSize: s coordinateSystem: [[MACoordinateSystem alloc] initWithView: v]]; 60 | 61 | STAssertEquals(NSMakeSize(0.5, 1), [sobj sizeValueInCoordinateSystem: [[MACoordinateSystem alloc] initWithView: v2]], @"Sizes are not equal"); 62 | } 63 | 64 | - (void)testDifferentWindowPoint 65 | { 66 | NSPoint p = { 1, 2 }; 67 | 68 | NSWindow *w = [[NSWindow alloc] initWithContentRect: NSMakeRect(0, 0, 100, 100) styleMask: 0 backing: NSBackingStoreBuffered defer: YES]; 69 | NSView *v = [[NSView alloc] initWithFrame: NSMakeRect(0, 0, 100, 100)]; 70 | [[w contentView] addSubview: v]; 71 | NSWindow *w2 = [[NSWindow alloc] initWithContentRect: NSMakeRect(50, 50, 100, 100) styleMask: 0 backing: NSBackingStoreBuffered defer: YES]; 72 | NSView *v2 = [[NSView alloc] initWithFrame: NSMakeRect(0, 0, 100, 100)]; 73 | [[w2 contentView] addSubview: v2]; 74 | 75 | MAPoint *pobj = [MAPoint pointWithNSPoint: p coordinateSystem: [[MACoordinateSystem alloc] initWithView: v]]; 76 | 77 | STAssertEquals(NSMakePoint(-49, -48), [pobj pointValueInCoordinateSystem: [[MACoordinateSystem alloc] initWithView: v2]], @"Points are not equal"); 78 | } 79 | 80 | - (void)testDifferentWindowSize 81 | { 82 | NSSize s = { 1, 2 }; 83 | 84 | NSWindow *w = [[NSWindow alloc] initWithContentRect: NSMakeRect(0, 0, 100, 100) styleMask: 0 backing: NSBackingStoreBuffered defer: YES]; 85 | NSView *v = [[NSView alloc] initWithFrame: NSMakeRect(0, 0, 100, 100)]; 86 | [[w contentView] addSubview: v]; 87 | 88 | NSWindow *w2 = [[NSWindow alloc] initWithContentRect: NSMakeRect(50, 50, 100, 100) styleMask: 0 backing: NSBackingStoreBuffered defer: YES]; 89 | NSView *v2 = [[NSView alloc] initWithFrame: NSMakeRect(0, 0, 100, 100)]; 90 | [v2 scaleUnitSquareToSize: NSMakeSize(2, 2)]; 91 | [[w2 contentView] addSubview: v2]; 92 | 93 | MASize *sobj = [MASize sizeWithNSSize: s coordinateSystem: [[MACoordinateSystem alloc] initWithView: v]]; 94 | 95 | STAssertEquals(NSMakeSize(0.5, 1), [sobj sizeValueInCoordinateSystem: [[MACoordinateSystem alloc] initWithView: v2]], @"Sizes are not equal"); 96 | } 97 | - (void)testDifferentWindowRect 98 | { 99 | NSRect r = { 1, 2, 3, 4 }; 100 | 101 | NSWindow *w = [[NSWindow alloc] initWithContentRect: NSMakeRect(0, 0, 100, 100) styleMask: 0 backing: NSBackingStoreBuffered defer: YES]; 102 | NSView *v = [[NSView alloc] initWithFrame: NSMakeRect(0, 0, 100, 100)]; 103 | [[w contentView] addSubview: v]; 104 | NSWindow *w2 = [[NSWindow alloc] initWithContentRect: NSMakeRect(50, 50, 100, 100) styleMask: 0 backing: NSBackingStoreBuffered defer: YES]; 105 | NSView *v2 = [[NSView alloc] initWithFrame: NSMakeRect(0, 0, 100, 100)]; 106 | [v2 scaleUnitSquareToSize: NSMakeSize(2, 2)]; 107 | [[w2 contentView] addSubview: v2]; 108 | 109 | MARectangle *rect = [MARectangle rectangleWithRect: r coordinateSystem: [[MACoordinateSystem alloc] initWithView: v]]; 110 | 111 | STAssertEquals(NSMakeRect(-24.5, -24, 1.5, 2), [rect rectValueInCoordinateSystem: [[MACoordinateSystem alloc] initWithView: v2]], @"Rects are not equal"); 112 | } 113 | 114 | @end 115 | -------------------------------------------------------------------------------- /NSRectangleTests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | This is a 3rd party implementation of the NSRectangle class and related classes discussed here: 2 | 3 | http://openradar.appspot.com/radar?id=1567402 4 | 5 | The text of the bug follows for those who want to read directly and not click. 6 | 7 | NSRect/CGRect (and similar structs like NSPoint and NSSize) are error-prone and can be tough to use due to the multitude of coordinate spaces we deal with. Many new Cocoa programmers don't understand the difference between bounds/frame and tend to resort to trial and error to pick the right one. In cases where frame and bounds happen to be numerically similar, an error can persist in code for a long time. 8 | 9 | My understanding is that NSRect and friends are structs mainly for efficiency reasons which were a big deal back when this stuff could be expected to run on a 25MHz 68040. This is probably less important today. 10 | 11 | I propose a new class, let's call it NSRectangle, which would encompass the functionality of NSRect but would hold not only its origin and size but also its coordinate system. An NSRectangle object could be passed around from one view to another or from one window to another without needing to do any manual conversions, as the object would hold enough information to do them on its own. Something painful and error prone like lining up a window with an NSView's on-screen location would become a simple matter of initializing the window with \[view frameRectangle\] (assuming -frameRectangle is an equivalent to -frame which returns an NSRectangle object). 12 | 13 | There are obviously a lot of compatibility concerns which would require keeping the old structs around pretty much indefinitely. However, I think these new classes could still bring a lot of benefit and supersede the structs in a lot of cases. 14 | 15 | Here are some code examples of how this class might work and be used: 16 | 17 | // position a subview in the bottom middle of this view 18 | NSRectangle *frame = [self frameRectangle]; 19 | [frame setHeight: [frame height] / 2]; 20 | [frame setOriginX: [frame width] * 3 / 4]; 21 | [frame setWidth: [frame width] / 2]; 22 | [subview setFrameRectangle: frame]; 23 | 24 | // position a window directly over this view 25 | NSRectangle *frame = [self frameRectangle]; 26 | NSWindow *window = [[NSWindow alloc] initWithFrameRectangle: frame ...]; 27 | [window orderFront: nil]; 28 | 29 | // position a window next to this view on the right 30 | NSRectangle *frame = [self frameRectangle]; 31 | [frame setOriginX: [frame maxX]]; 32 | [frame setWidth: 42]; // 42 pixels in VIEW COORDINATES, may be different in screen coordinates, but we may want to size the window relative to view coordinates anyway 33 | NSWindow *window = [[NSWindow alloc] initWithFrameRectangle: frame ...]; 34 | [window orderFront: nil]; 35 | 36 | // position a window next to this view on the right, sized in screen coords 37 | NSRectangle *frame = [self frameRectangle]; 38 | [frame setOriginX: [frame maxX]]; 39 | [frame setWidth: 42 inCoordinateSystem: [NSScreen coordinateSystem]]; 40 | NSWindow *window = [[NSWindow alloc] initWithFrameRectangle: frame ...]; 41 | [window orderFront: nil]; 42 | 43 | // create a 200x200 window with origin at 100,100 on the screen 44 | NSRectangle *rect = [NSRectangle rectangleWithRect: NSMakeRect(100, 100, 200, 200) inCoordinateSystem: [NSScreen coordinateSystem]]; 45 | NSWindow *window = [[NSWindow alloc] initWithFrameRectangle: rect ...]; 46 | 47 | // create a 200x200 window with origin at 100,100 relative to a view 48 | NSRectangle *rect = [NSRectangle rectangleWithRect: NSMakeRect(100, 100, 200, 200) inCoordinateSystem: [view coordinateSystem]]; 49 | NSWindow *window = [[NSWindow alloc] initWithFrameRectangle: rect ...]; 50 | 51 | // handling events 52 | // NSPointObj is a hypothetical class version of the NSPoint struct 53 | 54 | // see if a mouse event is within this view 55 | NSPointObj *loc = [theEvent location]; 56 | if([[self frameRectangle] containsPoint: loc]) 57 | ... 58 | 59 | // see if a mouse event is within various views 60 | NSPointObj *loc = [theEvent location]; 61 | if(([[view1 frameRectangle] containsPoint: loc]) 62 | ... 63 | else if(([[view2 frameRectangle] containsPoint: loc]) 64 | ... 65 | else if(([[view3 frameRectangle] containsPoint: loc]) 66 | ... 67 | // NOTE: view1, view2, and view3 don't need to be siblings for this to work 68 | // in fact, they don't even need to be in the same window! --------------------------------------------------------------------------------