From 02503fadb95eb8a10ac1867e5367b8691273aa00 Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Mon, 22 May 2017 13:13:40 -0700 Subject: [PATCH] Add RSCore framework. --- Evergreen.xcodeproj/project.pbxproj | 135 ++- Frameworks/RSCore/.gitignore | 60 + Frameworks/RSCore/LICENSE | 21 + Frameworks/RSCore/README.md | 8 + .../RSCore/RSCore.xcodeproj/project.pbxproj | 1043 +++++++++++++++++ .../contents.xcworkspacedata | 7 + .../RSCore/RSCore/Date+Extensions.swift | 29 + Frameworks/RSCore/RSCore/DiskSaver.swift | 73 ++ Frameworks/RSCore/RSCore/Info.plist | 28 + Frameworks/RSCore/RSCore/NSArray+RSCore.h | 48 + Frameworks/RSCore/RSCore/NSArray+RSCore.m | 103 ++ Frameworks/RSCore/RSCore/NSCalendar+RSCore.h | 16 + Frameworks/RSCore/RSCore/NSCalendar+RSCore.m | 76 ++ Frameworks/RSCore/RSCore/NSColor+RSCore.h | 18 + Frameworks/RSCore/RSCore/NSColor+RSCore.m | 24 + Frameworks/RSCore/RSCore/NSData+RSCore.h | 37 + Frameworks/RSCore/RSCore/NSData+RSCore.m | 153 +++ Frameworks/RSCore/RSCore/NSDate+RSCore.h | 24 + Frameworks/RSCore/RSCore/NSDate+RSCore.m | 49 + .../RSCore/RSCore/NSDictionary+RSCore.h | 21 + .../RSCore/RSCore/NSDictionary+RSCore.m | 59 + Frameworks/RSCore/RSCore/NSEvent+RSCore.h | 25 + Frameworks/RSCore/RSCore/NSEvent+RSCore.m | 61 + .../RSCore/RSCore/NSFileManager+RSCore.h | 24 + .../RSCore/RSCore/NSFileManager+RSCore.m | 134 +++ Frameworks/RSCore/RSCore/NSImage+RSCore.h | 23 + Frameworks/RSCore/RSCore/NSImage+RSCore.m | 31 + .../RSCore/RSCore/NSMutableArray+RSCore.h | 19 + .../RSCore/RSCore/NSMutableArray+RSCore.m | 22 + .../RSCore/NSMutableDictionary+RSCore.h | 22 + .../RSCore/NSMutableDictionary+RSCore.m | 28 + .../NSMutableDictionary-Extensions.swift | 24 + .../RSCore/RSCore/NSMutableSet+RSCore.h | 20 + .../RSCore/RSCore/NSMutableSet+RSCore.m | 22 + .../RSCore/NSNotificationCenter+RSCore.h | 20 + .../RSCore/NSNotificationCenter+RSCore.m | 31 + Frameworks/RSCore/RSCore/NSObject+RSCore.h | 35 + Frameworks/RSCore/RSCore/NSObject+RSCore.m | 114 ++ .../RSCore/NSOutlineView+Extensions.swift | 25 + .../RSCore/RSCore/NSPasteboard+RSCore.h | 23 + .../RSCore/RSCore/NSPasteboard+RSCore.m | 39 + .../RSCore/NSResponder-Extensions.swift | 30 + Frameworks/RSCore/RSCore/NSSet+RSCore.h | 23 + Frameworks/RSCore/RSCore/NSSet+RSCore.m | 48 + .../RSCore/RSCore/NSStoryboard+RSCore.h | 15 + .../RSCore/RSCore/NSStoryboard+RSCore.m | 19 + Frameworks/RSCore/RSCore/NSString+RSCore.h | 76 ++ Frameworks/RSCore/RSCore/NSString+RSCore.m | 370 ++++++ .../RSCore/NSTableView+Extensions.swift | 18 + Frameworks/RSCore/RSCore/NSTableView+RSCore.h | 19 + Frameworks/RSCore/RSCore/NSTableView+RSCore.m | 26 + Frameworks/RSCore/RSCore/NSTimer+RSCore.h | 18 + Frameworks/RSCore/RSCore/NSTimer+RSCore.m | 23 + Frameworks/RSCore/RSCore/NSView+RSCore.h | 31 + Frameworks/RSCore/RSCore/NSView+RSCore.m | 68 ++ .../RSCore/RSCore/NSWindow-Extensions.swift | 19 + .../RSCore/RSCore/PlistProviderProtocol.swift | 19 + .../RSCore/RSCore/RSBackgroundColorView.h | 19 + .../RSCore/RSCore/RSBackgroundColorView.m | 67 ++ Frameworks/RSCore/RSCore/RSBinaryCache.h | 41 + Frameworks/RSCore/RSCore/RSBinaryCache.m | 129 ++ Frameworks/RSCore/RSCore/RSBlocks.h | 46 + Frameworks/RSCore/RSCore/RSBlocks.m | 36 + Frameworks/RSCore/RSCore/RSConstants.h | 25 + Frameworks/RSCore/RSCore/RSConstants.m | 17 + Frameworks/RSCore/RSCore/RSCore.h | 68 ++ Frameworks/RSCore/RSCore/RSGeometry.h | 15 + Frameworks/RSCore/RSCore/RSGeometry.m | 36 + Frameworks/RSCore/RSCore/RSImageRenderer.h | 32 + Frameworks/RSCore/RSCore/RSImageRenderer.m | 69 ++ Frameworks/RSCore/RSCore/RSMacroProcessor.h | 19 + Frameworks/RSCore/RSCore/RSMacroProcessor.m | 120 ++ .../RSCore/RSCore/RSOpaqueContainerView.h | 21 + .../RSCore/RSCore/RSOpaqueContainerView.m | 52 + Frameworks/RSCore/RSCore/RSPlatform.h | 48 + Frameworks/RSCore/RSCore/RSPlatform.m | 62 + Frameworks/RSCore/RSCore/RSPlist.h | 17 + Frameworks/RSCore/RSCore/RSPlist.m | 40 + Frameworks/RSCore/RSCore/RSScaling.h | 16 + Frameworks/RSCore/RSCore/RSScaling.m | 61 + Frameworks/RSCore/RSCore/RSToolbarItem.swift | 64 + .../RSCore/RSTransparentContainerView.h | 17 + .../RSCore/RSTransparentContainerView.m | 50 + Frameworks/RSCore/RSCore/Set+Extensions.swift | 29 + Frameworks/RSCore/RSCoreTests/Info.plist | 24 + .../RSCore/RSCoreTests/NSString+ExtrasTests.m | 84 ++ Frameworks/RSCore/RSCoreTests/RSCoreTests.m | 40 + Frameworks/RSCore/RSCoreiOS/Info.plist | 26 + 88 files changed, 4957 insertions(+), 29 deletions(-) create mode 100755 Frameworks/RSCore/.gitignore create mode 100755 Frameworks/RSCore/LICENSE create mode 100755 Frameworks/RSCore/README.md create mode 100755 Frameworks/RSCore/RSCore.xcodeproj/project.pbxproj create mode 100755 Frameworks/RSCore/RSCore.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100755 Frameworks/RSCore/RSCore/Date+Extensions.swift create mode 100755 Frameworks/RSCore/RSCore/DiskSaver.swift create mode 100755 Frameworks/RSCore/RSCore/Info.plist create mode 100755 Frameworks/RSCore/RSCore/NSArray+RSCore.h create mode 100755 Frameworks/RSCore/RSCore/NSArray+RSCore.m create mode 100755 Frameworks/RSCore/RSCore/NSCalendar+RSCore.h create mode 100755 Frameworks/RSCore/RSCore/NSCalendar+RSCore.m create mode 100755 Frameworks/RSCore/RSCore/NSColor+RSCore.h create mode 100755 Frameworks/RSCore/RSCore/NSColor+RSCore.m create mode 100755 Frameworks/RSCore/RSCore/NSData+RSCore.h create mode 100755 Frameworks/RSCore/RSCore/NSData+RSCore.m create mode 100755 Frameworks/RSCore/RSCore/NSDate+RSCore.h create mode 100755 Frameworks/RSCore/RSCore/NSDate+RSCore.m create mode 100755 Frameworks/RSCore/RSCore/NSDictionary+RSCore.h create mode 100755 Frameworks/RSCore/RSCore/NSDictionary+RSCore.m create mode 100755 Frameworks/RSCore/RSCore/NSEvent+RSCore.h create mode 100755 Frameworks/RSCore/RSCore/NSEvent+RSCore.m create mode 100755 Frameworks/RSCore/RSCore/NSFileManager+RSCore.h create mode 100755 Frameworks/RSCore/RSCore/NSFileManager+RSCore.m create mode 100755 Frameworks/RSCore/RSCore/NSImage+RSCore.h create mode 100755 Frameworks/RSCore/RSCore/NSImage+RSCore.m create mode 100755 Frameworks/RSCore/RSCore/NSMutableArray+RSCore.h create mode 100755 Frameworks/RSCore/RSCore/NSMutableArray+RSCore.m create mode 100755 Frameworks/RSCore/RSCore/NSMutableDictionary+RSCore.h create mode 100755 Frameworks/RSCore/RSCore/NSMutableDictionary+RSCore.m create mode 100755 Frameworks/RSCore/RSCore/NSMutableDictionary-Extensions.swift create mode 100755 Frameworks/RSCore/RSCore/NSMutableSet+RSCore.h create mode 100755 Frameworks/RSCore/RSCore/NSMutableSet+RSCore.m create mode 100755 Frameworks/RSCore/RSCore/NSNotificationCenter+RSCore.h create mode 100755 Frameworks/RSCore/RSCore/NSNotificationCenter+RSCore.m create mode 100755 Frameworks/RSCore/RSCore/NSObject+RSCore.h create mode 100755 Frameworks/RSCore/RSCore/NSObject+RSCore.m create mode 100755 Frameworks/RSCore/RSCore/NSOutlineView+Extensions.swift create mode 100755 Frameworks/RSCore/RSCore/NSPasteboard+RSCore.h create mode 100755 Frameworks/RSCore/RSCore/NSPasteboard+RSCore.m create mode 100755 Frameworks/RSCore/RSCore/NSResponder-Extensions.swift create mode 100755 Frameworks/RSCore/RSCore/NSSet+RSCore.h create mode 100755 Frameworks/RSCore/RSCore/NSSet+RSCore.m create mode 100755 Frameworks/RSCore/RSCore/NSStoryboard+RSCore.h create mode 100755 Frameworks/RSCore/RSCore/NSStoryboard+RSCore.m create mode 100755 Frameworks/RSCore/RSCore/NSString+RSCore.h create mode 100755 Frameworks/RSCore/RSCore/NSString+RSCore.m create mode 100755 Frameworks/RSCore/RSCore/NSTableView+Extensions.swift create mode 100755 Frameworks/RSCore/RSCore/NSTableView+RSCore.h create mode 100755 Frameworks/RSCore/RSCore/NSTableView+RSCore.m create mode 100755 Frameworks/RSCore/RSCore/NSTimer+RSCore.h create mode 100755 Frameworks/RSCore/RSCore/NSTimer+RSCore.m create mode 100755 Frameworks/RSCore/RSCore/NSView+RSCore.h create mode 100755 Frameworks/RSCore/RSCore/NSView+RSCore.m create mode 100755 Frameworks/RSCore/RSCore/NSWindow-Extensions.swift create mode 100755 Frameworks/RSCore/RSCore/PlistProviderProtocol.swift create mode 100755 Frameworks/RSCore/RSCore/RSBackgroundColorView.h create mode 100755 Frameworks/RSCore/RSCore/RSBackgroundColorView.m create mode 100755 Frameworks/RSCore/RSCore/RSBinaryCache.h create mode 100755 Frameworks/RSCore/RSCore/RSBinaryCache.m create mode 100755 Frameworks/RSCore/RSCore/RSBlocks.h create mode 100755 Frameworks/RSCore/RSCore/RSBlocks.m create mode 100755 Frameworks/RSCore/RSCore/RSConstants.h create mode 100755 Frameworks/RSCore/RSCore/RSConstants.m create mode 100755 Frameworks/RSCore/RSCore/RSCore.h create mode 100755 Frameworks/RSCore/RSCore/RSGeometry.h create mode 100755 Frameworks/RSCore/RSCore/RSGeometry.m create mode 100755 Frameworks/RSCore/RSCore/RSImageRenderer.h create mode 100755 Frameworks/RSCore/RSCore/RSImageRenderer.m create mode 100755 Frameworks/RSCore/RSCore/RSMacroProcessor.h create mode 100755 Frameworks/RSCore/RSCore/RSMacroProcessor.m create mode 100755 Frameworks/RSCore/RSCore/RSOpaqueContainerView.h create mode 100755 Frameworks/RSCore/RSCore/RSOpaqueContainerView.m create mode 100755 Frameworks/RSCore/RSCore/RSPlatform.h create mode 100755 Frameworks/RSCore/RSCore/RSPlatform.m create mode 100755 Frameworks/RSCore/RSCore/RSPlist.h create mode 100755 Frameworks/RSCore/RSCore/RSPlist.m create mode 100755 Frameworks/RSCore/RSCore/RSScaling.h create mode 100755 Frameworks/RSCore/RSCore/RSScaling.m create mode 100755 Frameworks/RSCore/RSCore/RSToolbarItem.swift create mode 100755 Frameworks/RSCore/RSCore/RSTransparentContainerView.h create mode 100755 Frameworks/RSCore/RSCore/RSTransparentContainerView.m create mode 100755 Frameworks/RSCore/RSCore/Set+Extensions.swift create mode 100755 Frameworks/RSCore/RSCoreTests/Info.plist create mode 100755 Frameworks/RSCore/RSCoreTests/NSString+ExtrasTests.m create mode 100755 Frameworks/RSCore/RSCoreTests/RSCoreTests.m create mode 100755 Frameworks/RSCore/RSCoreiOS/Info.plist diff --git a/Evergreen.xcodeproj/project.pbxproj b/Evergreen.xcodeproj/project.pbxproj index c650866d6..51aeea024 100644 --- a/Evergreen.xcodeproj/project.pbxproj +++ b/Evergreen.xcodeproj/project.pbxproj @@ -14,8 +14,10 @@ 849C64761ED37A5D003D8FC0 /* EvergreenTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849C64751ED37A5D003D8FC0 /* EvergreenTests.swift */; }; 84B06F821ED37BDD00F0B54B /* RSXML.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84B06F7D1ED37BCA00F0B54B /* RSXML.framework */; }; 84B06F831ED37BDD00F0B54B /* RSXML.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 84B06F7D1ED37BCA00F0B54B /* RSXML.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 84B06F921ED37CB300F0B54B /* RSDatabase.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84B06F8D1ED37CA100F0B54B /* RSDatabase.framework */; }; - 84B06F931ED37CB300F0B54B /* RSDatabase.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 84B06F8D1ED37CA100F0B54B /* RSDatabase.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 84B06FAE1ED37DBD00F0B54B /* RSCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84B06FA91ED37DAD00F0B54B /* RSCore.framework */; }; + 84B06FAF1ED37DBD00F0B54B /* RSCore.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 84B06FA91ED37DAD00F0B54B /* RSCore.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 84B06FB21ED37DBD00F0B54B /* RSDatabase.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84B06F9D1ED37DA000F0B54B /* RSDatabase.framework */; }; + 84B06FB31ED37DBD00F0B54B /* RSDatabase.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 84B06F9D1ED37DA000F0B54B /* RSDatabase.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -54,30 +56,58 @@ remoteGlobalIDString = 84F22C0C1B52DDEA000060CE; remoteInfo = RSXML; }; - 84B06F8C1ED37CA100F0B54B /* PBXContainerItemProxy */ = { + 84B06F9C1ED37DA000F0B54B /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 84B06F861ED37CA000F0B54B /* RSDatabase.xcodeproj */; + containerPortal = 84B06F961ED37DA000F0B54B /* RSDatabase.xcodeproj */; proxyType = 2; remoteGlobalIDString = 84F22C551B52E0D9000060CE; remoteInfo = RSDatabase; }; - 84B06F8E1ED37CA100F0B54B /* PBXContainerItemProxy */ = { + 84B06F9E1ED37DA000F0B54B /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 84B06F861ED37CA000F0B54B /* RSDatabase.xcodeproj */; + containerPortal = 84B06F961ED37DA000F0B54B /* RSDatabase.xcodeproj */; proxyType = 2; remoteGlobalIDString = 84F22C5F1B52E0D9000060CE; remoteInfo = RSDatabaseTests; }; - 84B06F901ED37CA100F0B54B /* PBXContainerItemProxy */ = { + 84B06FA01ED37DA000F0B54B /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 84B06F861ED37CA000F0B54B /* RSDatabase.xcodeproj */; + containerPortal = 84B06F961ED37DA000F0B54B /* RSDatabase.xcodeproj */; proxyType = 2; remoteGlobalIDString = 8400ABF71E0CFBD800AA7C57; remoteInfo = RSDatabaseiOS; }; - 84B06F941ED37CB300F0B54B /* PBXContainerItemProxy */ = { + 84B06FA81ED37DAD00F0B54B /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 84B06F861ED37CA000F0B54B /* RSDatabase.xcodeproj */; + containerPortal = 84B06FA21ED37DAC00F0B54B /* RSCore.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 84CFF4F41AC3C69700CEA6C8; + remoteInfo = RSCore; + }; + 84B06FAA1ED37DAD00F0B54B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 84B06FA21ED37DAC00F0B54B /* RSCore.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 84CFF4FF1AC3C69700CEA6C8; + remoteInfo = RSCoreTests; + }; + 84B06FAC1ED37DAD00F0B54B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 84B06FA21ED37DAC00F0B54B /* RSCore.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 842DD7BC1E14993900E061EB; + remoteInfo = RSCoreiOS; + }; + 84B06FB01ED37DBD00F0B54B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 84B06FA21ED37DAC00F0B54B /* RSCore.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 84CFF4F31AC3C69700CEA6C8; + remoteInfo = RSCore; + }; + 84B06FB41ED37DBD00F0B54B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 84B06F961ED37DA000F0B54B /* RSDatabase.xcodeproj */; proxyType = 1; remoteGlobalIDString = 84F22C541B52E0D9000060CE; remoteInfo = RSDatabase; @@ -91,7 +121,8 @@ dstPath = ""; dstSubfolderSpec = 10; files = ( - 84B06F931ED37CB300F0B54B /* RSDatabase.framework in Embed Frameworks */, + 84B06FB31ED37DBD00F0B54B /* RSDatabase.framework in Embed Frameworks */, + 84B06FAF1ED37DBD00F0B54B /* RSCore.framework in Embed Frameworks */, 84B06F831ED37BDD00F0B54B /* RSXML.framework in Embed Frameworks */, ); name = "Embed Frameworks"; @@ -110,7 +141,8 @@ 849C64751ED37A5D003D8FC0 /* EvergreenTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EvergreenTests.swift; sourceTree = ""; }; 849C64771ED37A5D003D8FC0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 84B06F761ED37BCA00F0B54B /* RSXML.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RSXML.xcodeproj; path = Frameworks/RSXML/RSXML.xcodeproj; sourceTree = ""; }; - 84B06F861ED37CA000F0B54B /* RSDatabase.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RSDatabase.xcodeproj; path = Frameworks/RSDatabase/RSDatabase.xcodeproj; sourceTree = ""; }; + 84B06F961ED37DA000F0B54B /* RSDatabase.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RSDatabase.xcodeproj; path = Frameworks/RSDatabase/RSDatabase.xcodeproj; sourceTree = ""; }; + 84B06FA21ED37DAC00F0B54B /* RSCore.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RSCore.xcodeproj; path = Frameworks/RSCore/RSCore.xcodeproj; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -118,7 +150,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 84B06F921ED37CB300F0B54B /* RSDatabase.framework in Frameworks */, + 84B06FB21ED37DBD00F0B54B /* RSDatabase.framework in Frameworks */, + 84B06FAE1ED37DBD00F0B54B /* RSCore.framework in Frameworks */, 84B06F821ED37BDD00F0B54B /* RSXML.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -143,7 +176,8 @@ 849C646C1ED37A5D003D8FC0 /* Info.plist */, 849C64741ED37A5D003D8FC0 /* EvergreenTests */, 849C64611ED37A5D003D8FC0 /* Products */, - 84B06F861ED37CA000F0B54B /* RSDatabase.xcodeproj */, + 84B06FA21ED37DAC00F0B54B /* RSCore.xcodeproj */, + 84B06F961ED37DA000F0B54B /* RSDatabase.xcodeproj */, 84B06F761ED37BCA00F0B54B /* RSXML.xcodeproj */, ); sourceTree = ""; @@ -176,12 +210,22 @@ name = Products; sourceTree = ""; }; - 84B06F871ED37CA000F0B54B /* Products */ = { + 84B06F971ED37DA000F0B54B /* Products */ = { isa = PBXGroup; children = ( - 84B06F8D1ED37CA100F0B54B /* RSDatabase.framework */, - 84B06F8F1ED37CA100F0B54B /* RSDatabaseTests.xctest */, - 84B06F911ED37CA100F0B54B /* RSDatabase.framework */, + 84B06F9D1ED37DA000F0B54B /* RSDatabase.framework */, + 84B06F9F1ED37DA000F0B54B /* RSDatabaseTests.xctest */, + 84B06FA11ED37DA000F0B54B /* RSDatabase.framework */, + ); + name = Products; + sourceTree = ""; + }; + 84B06FA31ED37DAC00F0B54B /* Products */ = { + isa = PBXGroup; + children = ( + 84B06FA91ED37DAD00F0B54B /* RSCore.framework */, + 84B06FAB1ED37DAD00F0B54B /* RSCoreTests.xctest */, + 84B06FAD1ED37DAD00F0B54B /* RSCore.framework */, ); name = Products; sourceTree = ""; @@ -202,7 +246,8 @@ ); dependencies = ( 84B06F851ED37BDD00F0B54B /* PBXTargetDependency */, - 84B06F951ED37CB300F0B54B /* PBXTargetDependency */, + 84B06FB11ED37DBD00F0B54B /* PBXTargetDependency */, + 84B06FB51ED37DBD00F0B54B /* PBXTargetDependency */, ); name = Evergreen; productName = Evergreen; @@ -263,8 +308,12 @@ projectDirPath = ""; projectReferences = ( { - ProductGroup = 84B06F871ED37CA000F0B54B /* Products */; - ProjectRef = 84B06F861ED37CA000F0B54B /* RSDatabase.xcodeproj */; + ProductGroup = 84B06FA31ED37DAC00F0B54B /* Products */; + ProjectRef = 84B06FA21ED37DAC00F0B54B /* RSCore.xcodeproj */; + }, + { + ProductGroup = 84B06F971ED37DA000F0B54B /* Products */; + ProjectRef = 84B06F961ED37DA000F0B54B /* RSDatabase.xcodeproj */; }, { ProductGroup = 84B06F771ED37BCA00F0B54B /* Products */; @@ -301,25 +350,46 @@ remoteRef = 84B06F801ED37BCA00F0B54B /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 84B06F8D1ED37CA100F0B54B /* RSDatabase.framework */ = { + 84B06F9D1ED37DA000F0B54B /* RSDatabase.framework */ = { isa = PBXReferenceProxy; fileType = wrapper.framework; path = RSDatabase.framework; - remoteRef = 84B06F8C1ED37CA100F0B54B /* PBXContainerItemProxy */; + remoteRef = 84B06F9C1ED37DA000F0B54B /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 84B06F8F1ED37CA100F0B54B /* RSDatabaseTests.xctest */ = { + 84B06F9F1ED37DA000F0B54B /* RSDatabaseTests.xctest */ = { isa = PBXReferenceProxy; fileType = wrapper.cfbundle; path = RSDatabaseTests.xctest; - remoteRef = 84B06F8E1ED37CA100F0B54B /* PBXContainerItemProxy */; + remoteRef = 84B06F9E1ED37DA000F0B54B /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 84B06F911ED37CA100F0B54B /* RSDatabase.framework */ = { + 84B06FA11ED37DA000F0B54B /* RSDatabase.framework */ = { isa = PBXReferenceProxy; fileType = wrapper.framework; path = RSDatabase.framework; - remoteRef = 84B06F901ED37CA100F0B54B /* PBXContainerItemProxy */; + remoteRef = 84B06FA01ED37DA000F0B54B /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 84B06FA91ED37DAD00F0B54B /* RSCore.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = RSCore.framework; + remoteRef = 84B06FA81ED37DAD00F0B54B /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 84B06FAB1ED37DAD00F0B54B /* RSCoreTests.xctest */ = { + isa = PBXReferenceProxy; + fileType = wrapper.cfbundle; + path = RSCoreTests.xctest; + remoteRef = 84B06FAA1ED37DAD00F0B54B /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 84B06FAD1ED37DAD00F0B54B /* RSCore.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = RSCore.framework; + remoteRef = 84B06FAC1ED37DAD00F0B54B /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXReferenceProxy section */ @@ -374,10 +444,15 @@ name = RSXML; targetProxy = 84B06F841ED37BDD00F0B54B /* PBXContainerItemProxy */; }; - 84B06F951ED37CB300F0B54B /* PBXTargetDependency */ = { + 84B06FB11ED37DBD00F0B54B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = RSCore; + targetProxy = 84B06FB01ED37DBD00F0B54B /* PBXContainerItemProxy */; + }; + 84B06FB51ED37DBD00F0B54B /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = RSDatabase; - targetProxy = 84B06F941ED37CB300F0B54B /* PBXContainerItemProxy */; + targetProxy = 84B06FB41ED37DBD00F0B54B /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ @@ -487,6 +562,7 @@ 849C647B1ED37A5D003D8FC0 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; COMBINE_HIDPI_IMAGES = YES; DEVELOPMENT_TEAM = 9C84TZ7Q6Z; @@ -501,6 +577,7 @@ 849C647C1ED37A5D003D8FC0 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; COMBINE_HIDPI_IMAGES = YES; DEVELOPMENT_TEAM = 9C84TZ7Q6Z; diff --git a/Frameworks/RSCore/.gitignore b/Frameworks/RSCore/.gitignore new file mode 100755 index 000000000..86f21d8e0 --- /dev/null +++ b/Frameworks/RSCore/.gitignore @@ -0,0 +1,60 @@ +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## Build generated +build/ +DerivedData/ + +## Various settings +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata/ + +## Other +*.moved-aside +*.xcuserstate + +## Obj-C/Swift specific +*.hmap +*.ipa +*.dSYM.zip +*.dSYM + +# CocoaPods +# +# We recommend against adding the Pods directory to your .gitignore. However +# you should judge for yourself, the pros and cons are mentioned at: +# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control +# +# Pods/ + +# Carthage +# +# Add this line if you want to avoid checking in source code from Carthage dependencies. +# Carthage/Checkouts + +Carthage/Build + +# fastlane +# +# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the +# screenshots whenever they are needed. +# For more information about the recommended setup visit: +# https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md + +fastlane/report.xml +fastlane/screenshots + +#Code Injection +# +# After new code Injection tools there's a generated folder /iOSInjectionProject +# https://github.com/johnno1962/injectionforxcode + +iOSInjectionProject/ diff --git a/Frameworks/RSCore/LICENSE b/Frameworks/RSCore/LICENSE new file mode 100755 index 000000000..d9348ee4e --- /dev/null +++ b/Frameworks/RSCore/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2016 brentsimmons + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Frameworks/RSCore/README.md b/Frameworks/RSCore/README.md new file mode 100755 index 000000000..6457b4684 --- /dev/null +++ b/Frameworks/RSCore/README.md @@ -0,0 +1,8 @@ +# RSCore +Utility code for Mac and iOS apps. + +This builds a Mac framework and an iOS framework. + +There’s a whole bunch of stuff in here. There are categories on Foundation and AppKit objects plus a few miscellaneous things. + +(More notes will be coming.) \ No newline at end of file diff --git a/Frameworks/RSCore/RSCore.xcodeproj/project.pbxproj b/Frameworks/RSCore/RSCore.xcodeproj/project.pbxproj new file mode 100755 index 000000000..44457bf83 --- /dev/null +++ b/Frameworks/RSCore/RSCore.xcodeproj/project.pbxproj @@ -0,0 +1,1043 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 84134D1F1C59D5450063FD24 /* NSCalendar+RSCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 84134D1D1C59D5450063FD24 /* NSCalendar+RSCore.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 84134D201C59D5450063FD24 /* NSCalendar+RSCore.m in Sources */ = {isa = PBXBuildFile; fileRef = 84134D1E1C59D5450063FD24 /* NSCalendar+RSCore.m */; }; + 8414CBA71C95F2EA00333C12 /* Set+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8414CBA61C95F2EA00333C12 /* Set+Extensions.swift */; }; + 8414CBAB1C95F8F700333C12 /* RSGeometry.h in Headers */ = {isa = PBXBuildFile; fileRef = 8414CBA91C95F8F700333C12 /* RSGeometry.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 8414CBAC1C95F8F700333C12 /* RSGeometry.m in Sources */ = {isa = PBXBuildFile; fileRef = 8414CBAA1C95F8F700333C12 /* RSGeometry.m */; }; + 8415CB8A1BF84D24007B1E98 /* NSEvent+RSCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 8415CB881BF84D24007B1E98 /* NSEvent+RSCore.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 8415CB8B1BF84D24007B1E98 /* NSEvent+RSCore.m in Sources */ = {isa = PBXBuildFile; fileRef = 8415CB891BF84D24007B1E98 /* NSEvent+RSCore.m */; }; + 8417FE021AC67D430048E9B7 /* RSOpaqueContainerView.h in Headers */ = {isa = PBXBuildFile; fileRef = 8417FE001AC67D430048E9B7 /* RSOpaqueContainerView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 8417FE031AC67D430048E9B7 /* RSOpaqueContainerView.m in Sources */ = {isa = PBXBuildFile; fileRef = 8417FE011AC67D430048E9B7 /* RSOpaqueContainerView.m */; }; + 842635571D7FA1C800196285 /* NSTableView+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 842635561D7FA1C800196285 /* NSTableView+Extensions.swift */; }; + 842635591D7FA24800196285 /* NSOutlineView+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 842635581D7FA24800196285 /* NSOutlineView+Extensions.swift */; }; + 842DD7C41E14995000E061EB /* RSCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 84CFF4F91AC3C69700CEA6C8 /* RSCore.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 842DD7C51E14995C00E061EB /* RSBlocks.h in Headers */ = {isa = PBXBuildFile; fileRef = 84CFF5101AC3C6D800CEA6C8 /* RSBlocks.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 842DD7C61E14995C00E061EB /* RSBlocks.m in Sources */ = {isa = PBXBuildFile; fileRef = 84CFF5111AC3C6D800CEA6C8 /* RSBlocks.m */; }; + 842DD7C71E14995C00E061EB /* RSConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = 84CFF5141AC3C73000CEA6C8 /* RSConstants.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 842DD7C81E14995C00E061EB /* RSConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = 84CFF5151AC3C73000CEA6C8 /* RSConstants.m */; }; + 842DD7C91E14995C00E061EB /* RSPlatform.h in Headers */ = {isa = PBXBuildFile; fileRef = 84CFF5181AC3C77500CEA6C8 /* RSPlatform.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 842DD7CA1E14995C00E061EB /* RSPlatform.m in Sources */ = {isa = PBXBuildFile; fileRef = 84CFF5191AC3C77500CEA6C8 /* RSPlatform.m */; }; + 842DD7CB1E14995C00E061EB /* RSBinaryCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 84CFF55E1AC3D0CE00CEA6C8 /* RSBinaryCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 842DD7CC1E14995C00E061EB /* RSBinaryCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 84CFF55F1AC3D0CE00CEA6C8 /* RSBinaryCache.m */; }; + 842DD7CD1E14995C00E061EB /* RSPlist.h in Headers */ = {isa = PBXBuildFile; fileRef = 844C91591B65753E0051FC1B /* RSPlist.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 842DD7CE1E14995C00E061EB /* RSPlist.m in Sources */ = {isa = PBXBuildFile; fileRef = 844C915A1B65753E0051FC1B /* RSPlist.m */; }; + 842DD7CF1E14995C00E061EB /* RSMacroProcessor.h in Headers */ = {isa = PBXBuildFile; fileRef = 8453F7DC1BDF337800B1C8ED /* RSMacroProcessor.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 842DD7D01E14995C00E061EB /* RSMacroProcessor.m in Sources */ = {isa = PBXBuildFile; fileRef = 8453F7DD1BDF337800B1C8ED /* RSMacroProcessor.m */; }; + 842DD7D41E14995C00E061EB /* DiskSaver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849BF8B91C9130150071D1DA /* DiskSaver.swift */; }; + 842DD7D51E14995C00E061EB /* PlistProviderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84A835891D4EC7B80004C598 /* PlistProviderProtocol.swift */; }; + 842DD7D61E14996300E061EB /* NSArray+RSCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 84CFF5251AC3C9A200CEA6C8 /* NSArray+RSCore.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 842DD7D71E14996300E061EB /* NSArray+RSCore.m in Sources */ = {isa = PBXBuildFile; fileRef = 84CFF5261AC3C9A200CEA6C8 /* NSArray+RSCore.m */; }; + 842DD7D81E14996300E061EB /* NSCalendar+RSCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 84134D1D1C59D5450063FD24 /* NSCalendar+RSCore.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 842DD7D91E14996300E061EB /* NSCalendar+RSCore.m in Sources */ = {isa = PBXBuildFile; fileRef = 84134D1E1C59D5450063FD24 /* NSCalendar+RSCore.m */; }; + 842DD7DA1E14996300E061EB /* NSData+RSCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 84CFF5291AC3CA9700CEA6C8 /* NSData+RSCore.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 842DD7DB1E14996300E061EB /* NSData+RSCore.m in Sources */ = {isa = PBXBuildFile; fileRef = 84CFF52A1AC3CA9700CEA6C8 /* NSData+RSCore.m */; }; + 842DD7DC1E14996300E061EB /* NSDate+RSCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 84CFF52D1AC3CB1900CEA6C8 /* NSDate+RSCore.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 842DD7DD1E14996300E061EB /* NSDate+RSCore.m in Sources */ = {isa = PBXBuildFile; fileRef = 84CFF52E1AC3CB1900CEA6C8 /* NSDate+RSCore.m */; }; + 842DD7DE1E14996300E061EB /* NSDictionary+RSCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 84CFF5311AC3CB6800CEA6C8 /* NSDictionary+RSCore.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 842DD7DF1E14996300E061EB /* NSDictionary+RSCore.m in Sources */ = {isa = PBXBuildFile; fileRef = 84CFF5321AC3CB6800CEA6C8 /* NSDictionary+RSCore.m */; }; + 842DD7E01E14996300E061EB /* NSFileManager+RSCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 84536F641BB856D4001E1639 /* NSFileManager+RSCore.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 842DD7E11E14996300E061EB /* NSFileManager+RSCore.m in Sources */ = {isa = PBXBuildFile; fileRef = 84536F651BB856D4001E1639 /* NSFileManager+RSCore.m */; }; + 842DD7E21E14996300E061EB /* NSMutableArray+RSCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 84CFF5351AC3CBB200CEA6C8 /* NSMutableArray+RSCore.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 842DD7E31E14996300E061EB /* NSMutableArray+RSCore.m in Sources */ = {isa = PBXBuildFile; fileRef = 84CFF5361AC3CBB200CEA6C8 /* NSMutableArray+RSCore.m */; }; + 842DD7E41E14996300E061EB /* NSMutableDictionary+RSCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 84CFF5391AC3CCCA00CEA6C8 /* NSMutableDictionary+RSCore.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 842DD7E51E14996300E061EB /* NSMutableDictionary+RSCore.m in Sources */ = {isa = PBXBuildFile; fileRef = 84CFF53A1AC3CCCA00CEA6C8 /* NSMutableDictionary+RSCore.m */; }; + 842DD7E61E14996300E061EB /* NSMutableSet+RSCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 84CFF53D1AC3CD0100CEA6C8 /* NSMutableSet+RSCore.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 842DD7E71E14996300E061EB /* NSMutableSet+RSCore.m in Sources */ = {isa = PBXBuildFile; fileRef = 84CFF53E1AC3CD0100CEA6C8 /* NSMutableSet+RSCore.m */; }; + 842DD7E81E14996300E061EB /* NSNotificationCenter+RSCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 84CFF5411AC3CD3500CEA6C8 /* NSNotificationCenter+RSCore.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 842DD7E91E14996300E061EB /* NSNotificationCenter+RSCore.m in Sources */ = {isa = PBXBuildFile; fileRef = 84CFF5421AC3CD3500CEA6C8 /* NSNotificationCenter+RSCore.m */; }; + 842DD7EA1E14996300E061EB /* NSObject+RSCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 84CFF5201AC3C89D00CEA6C8 /* NSObject+RSCore.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 842DD7EB1E14996300E061EB /* NSObject+RSCore.m in Sources */ = {isa = PBXBuildFile; fileRef = 84CFF5211AC3C89D00CEA6C8 /* NSObject+RSCore.m */; }; + 842DD7EC1E14996300E061EB /* NSSet+RSCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 845DE0F11B80477100D1571B /* NSSet+RSCore.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 842DD7ED1E14996300E061EB /* NSSet+RSCore.m in Sources */ = {isa = PBXBuildFile; fileRef = 845DE0F21B80477100D1571B /* NSSet+RSCore.m */; }; + 842DD7EE1E14996300E061EB /* NSString+RSCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 84CFF5491AC3CDAC00CEA6C8 /* NSString+RSCore.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 842DD7EF1E14996300E061EB /* NSString+RSCore.m in Sources */ = {isa = PBXBuildFile; fileRef = 84CFF54A1AC3CDAC00CEA6C8 /* NSString+RSCore.m */; }; + 842DD7F01E14996300E061EB /* NSTimer+RSCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 84CFF5451AC3CD8000CEA6C8 /* NSTimer+RSCore.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 842DD7F11E14996300E061EB /* NSTimer+RSCore.m in Sources */ = {isa = PBXBuildFile; fileRef = 84CFF5461AC3CD8000CEA6C8 /* NSTimer+RSCore.m */; }; + 842DD7F21E14996B00E061EB /* Date+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84FEB4AB1D19D7F4004727E5 /* Date+Extensions.swift */; }; + 842DD7F31E14996B00E061EB /* NSMutableDictionary-Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84BB45421D6909C700B48537 /* NSMutableDictionary-Extensions.swift */; }; + 842DD7F41E14996B00E061EB /* Set+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8414CBA61C95F2EA00333C12 /* Set+Extensions.swift */; }; + 842DD7F51E14997600E061EB /* RSImageRenderer.h in Headers */ = {isa = PBXBuildFile; fileRef = 84CFF5621AC3D13C00CEA6C8 /* RSImageRenderer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 842DD7F61E14997600E061EB /* RSImageRenderer.m in Sources */ = {isa = PBXBuildFile; fileRef = 84CFF5631AC3D13C00CEA6C8 /* RSImageRenderer.m */; }; + 842DD7F71E14997600E061EB /* RSScaling.h in Headers */ = {isa = PBXBuildFile; fileRef = 84CFF5671AC3D1B000CEA6C8 /* RSScaling.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 842DD7F81E14997600E061EB /* RSScaling.m in Sources */ = {isa = PBXBuildFile; fileRef = 84CFF5681AC3D1B000CEA6C8 /* RSScaling.m */; }; + 8432B1861DACA0E90057D6DF /* NSResponder-Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8432B1851DACA0E90057D6DF /* NSResponder-Extensions.swift */; }; + 8432B1881DACA2060057D6DF /* NSWindow-Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8432B1871DACA2060057D6DF /* NSWindow-Extensions.swift */; }; + 844C915B1B65753E0051FC1B /* RSPlist.h in Headers */ = {isa = PBXBuildFile; fileRef = 844C91591B65753E0051FC1B /* RSPlist.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 844C915C1B65753E0051FC1B /* RSPlist.m in Sources */ = {isa = PBXBuildFile; fileRef = 844C915A1B65753E0051FC1B /* RSPlist.m */; }; + 844F91D51D90D86100820C48 /* RSTransparentContainerView.h in Headers */ = {isa = PBXBuildFile; fileRef = 844F91D31D90D86100820C48 /* RSTransparentContainerView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 844F91D61D90D86100820C48 /* RSTransparentContainerView.m in Sources */ = {isa = PBXBuildFile; fileRef = 844F91D41D90D86100820C48 /* RSTransparentContainerView.m */; }; + 84536F661BB856D4001E1639 /* NSFileManager+RSCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 84536F641BB856D4001E1639 /* NSFileManager+RSCore.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 84536F671BB856D4001E1639 /* NSFileManager+RSCore.m in Sources */ = {isa = PBXBuildFile; fileRef = 84536F651BB856D4001E1639 /* NSFileManager+RSCore.m */; }; + 8453F7DE1BDF337800B1C8ED /* RSMacroProcessor.h in Headers */ = {isa = PBXBuildFile; fileRef = 8453F7DC1BDF337800B1C8ED /* RSMacroProcessor.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 8453F7DF1BDF337800B1C8ED /* RSMacroProcessor.m in Sources */ = {isa = PBXBuildFile; fileRef = 8453F7DD1BDF337800B1C8ED /* RSMacroProcessor.m */; }; + 845DE0F31B80477100D1571B /* NSSet+RSCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 845DE0F11B80477100D1571B /* NSSet+RSCore.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 845DE0F41B80477100D1571B /* NSSet+RSCore.m in Sources */ = {isa = PBXBuildFile; fileRef = 845DE0F21B80477100D1571B /* NSSet+RSCore.m */; }; + 8461387F1DB3F5BE00048B83 /* RSToolbarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8461387E1DB3F5BE00048B83 /* RSToolbarItem.swift */; }; + 849A339D1AC90A0A0015BA09 /* NSTableView+RSCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 849A339B1AC90A0A0015BA09 /* NSTableView+RSCore.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 849A339E1AC90A0A0015BA09 /* NSTableView+RSCore.m in Sources */ = {isa = PBXBuildFile; fileRef = 849A339C1AC90A0A0015BA09 /* NSTableView+RSCore.m */; }; + 849B08971BF7BCE30090CEE4 /* NSPasteboard+RSCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 849B08951BF7BCE30090CEE4 /* NSPasteboard+RSCore.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 849B08981BF7BCE30090CEE4 /* NSPasteboard+RSCore.m in Sources */ = {isa = PBXBuildFile; fileRef = 849B08961BF7BCE30090CEE4 /* NSPasteboard+RSCore.m */; }; + 849BF8BA1C9130150071D1DA /* DiskSaver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849BF8B91C9130150071D1DA /* DiskSaver.swift */; }; + 84A8358A1D4EC7B80004C598 /* PlistProviderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84A835891D4EC7B80004C598 /* PlistProviderProtocol.swift */; }; + 84B890561C59CF1600D8BF23 /* NSString+ExtrasTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 84B890551C59CF1600D8BF23 /* NSString+ExtrasTests.m */; }; + 84BB45431D6909C700B48537 /* NSMutableDictionary-Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84BB45421D6909C700B48537 /* NSMutableDictionary-Extensions.swift */; }; + 84CFF4FA1AC3C69700CEA6C8 /* RSCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 84CFF4F91AC3C69700CEA6C8 /* RSCore.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 84CFF5001AC3C69700CEA6C8 /* RSCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84CFF4F41AC3C69700CEA6C8 /* RSCore.framework */; }; + 84CFF5071AC3C69700CEA6C8 /* RSCoreTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 84CFF5061AC3C69700CEA6C8 /* RSCoreTests.m */; }; + 84CFF5121AC3C6D800CEA6C8 /* RSBlocks.h in Headers */ = {isa = PBXBuildFile; fileRef = 84CFF5101AC3C6D800CEA6C8 /* RSBlocks.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 84CFF5131AC3C6D800CEA6C8 /* RSBlocks.m in Sources */ = {isa = PBXBuildFile; fileRef = 84CFF5111AC3C6D800CEA6C8 /* RSBlocks.m */; }; + 84CFF5161AC3C73000CEA6C8 /* RSConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = 84CFF5141AC3C73000CEA6C8 /* RSConstants.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 84CFF5171AC3C73000CEA6C8 /* RSConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = 84CFF5151AC3C73000CEA6C8 /* RSConstants.m */; }; + 84CFF51A1AC3C77500CEA6C8 /* RSPlatform.h in Headers */ = {isa = PBXBuildFile; fileRef = 84CFF5181AC3C77500CEA6C8 /* RSPlatform.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 84CFF51B1AC3C77500CEA6C8 /* RSPlatform.m in Sources */ = {isa = PBXBuildFile; fileRef = 84CFF5191AC3C77500CEA6C8 /* RSPlatform.m */; }; + 84CFF5221AC3C89D00CEA6C8 /* NSObject+RSCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 84CFF5201AC3C89D00CEA6C8 /* NSObject+RSCore.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 84CFF5231AC3C89D00CEA6C8 /* NSObject+RSCore.m in Sources */ = {isa = PBXBuildFile; fileRef = 84CFF5211AC3C89D00CEA6C8 /* NSObject+RSCore.m */; }; + 84CFF5271AC3C9A200CEA6C8 /* NSArray+RSCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 84CFF5251AC3C9A200CEA6C8 /* NSArray+RSCore.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 84CFF5281AC3C9A200CEA6C8 /* NSArray+RSCore.m in Sources */ = {isa = PBXBuildFile; fileRef = 84CFF5261AC3C9A200CEA6C8 /* NSArray+RSCore.m */; }; + 84CFF52B1AC3CA9700CEA6C8 /* NSData+RSCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 84CFF5291AC3CA9700CEA6C8 /* NSData+RSCore.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 84CFF52C1AC3CA9700CEA6C8 /* NSData+RSCore.m in Sources */ = {isa = PBXBuildFile; fileRef = 84CFF52A1AC3CA9700CEA6C8 /* NSData+RSCore.m */; }; + 84CFF52F1AC3CB1900CEA6C8 /* NSDate+RSCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 84CFF52D1AC3CB1900CEA6C8 /* NSDate+RSCore.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 84CFF5301AC3CB1900CEA6C8 /* NSDate+RSCore.m in Sources */ = {isa = PBXBuildFile; fileRef = 84CFF52E1AC3CB1900CEA6C8 /* NSDate+RSCore.m */; }; + 84CFF5331AC3CB6800CEA6C8 /* NSDictionary+RSCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 84CFF5311AC3CB6800CEA6C8 /* NSDictionary+RSCore.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 84CFF5341AC3CB6800CEA6C8 /* NSDictionary+RSCore.m in Sources */ = {isa = PBXBuildFile; fileRef = 84CFF5321AC3CB6800CEA6C8 /* NSDictionary+RSCore.m */; }; + 84CFF5371AC3CBB200CEA6C8 /* NSMutableArray+RSCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 84CFF5351AC3CBB200CEA6C8 /* NSMutableArray+RSCore.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 84CFF5381AC3CBB200CEA6C8 /* NSMutableArray+RSCore.m in Sources */ = {isa = PBXBuildFile; fileRef = 84CFF5361AC3CBB200CEA6C8 /* NSMutableArray+RSCore.m */; }; + 84CFF53B1AC3CCCA00CEA6C8 /* NSMutableDictionary+RSCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 84CFF5391AC3CCCA00CEA6C8 /* NSMutableDictionary+RSCore.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 84CFF53C1AC3CCCA00CEA6C8 /* NSMutableDictionary+RSCore.m in Sources */ = {isa = PBXBuildFile; fileRef = 84CFF53A1AC3CCCA00CEA6C8 /* NSMutableDictionary+RSCore.m */; }; + 84CFF53F1AC3CD0100CEA6C8 /* NSMutableSet+RSCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 84CFF53D1AC3CD0100CEA6C8 /* NSMutableSet+RSCore.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 84CFF5401AC3CD0100CEA6C8 /* NSMutableSet+RSCore.m in Sources */ = {isa = PBXBuildFile; fileRef = 84CFF53E1AC3CD0100CEA6C8 /* NSMutableSet+RSCore.m */; }; + 84CFF5431AC3CD3500CEA6C8 /* NSNotificationCenter+RSCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 84CFF5411AC3CD3500CEA6C8 /* NSNotificationCenter+RSCore.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 84CFF5441AC3CD3500CEA6C8 /* NSNotificationCenter+RSCore.m in Sources */ = {isa = PBXBuildFile; fileRef = 84CFF5421AC3CD3500CEA6C8 /* NSNotificationCenter+RSCore.m */; }; + 84CFF5471AC3CD8000CEA6C8 /* NSTimer+RSCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 84CFF5451AC3CD8000CEA6C8 /* NSTimer+RSCore.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 84CFF5481AC3CD8000CEA6C8 /* NSTimer+RSCore.m in Sources */ = {isa = PBXBuildFile; fileRef = 84CFF5461AC3CD8000CEA6C8 /* NSTimer+RSCore.m */; }; + 84CFF54B1AC3CDAC00CEA6C8 /* NSString+RSCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 84CFF5491AC3CDAC00CEA6C8 /* NSString+RSCore.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 84CFF54C1AC3CDAC00CEA6C8 /* NSString+RSCore.m in Sources */ = {isa = PBXBuildFile; fileRef = 84CFF54A1AC3CDAC00CEA6C8 /* NSString+RSCore.m */; }; + 84CFF5531AC3CF4700CEA6C8 /* NSColor+RSCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 84CFF5511AC3CF4700CEA6C8 /* NSColor+RSCore.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 84CFF5541AC3CF4700CEA6C8 /* NSColor+RSCore.m in Sources */ = {isa = PBXBuildFile; fileRef = 84CFF5521AC3CF4700CEA6C8 /* NSColor+RSCore.m */; }; + 84CFF5581AC3CF9100CEA6C8 /* NSView+RSCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 84CFF5561AC3CF9100CEA6C8 /* NSView+RSCore.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 84CFF5591AC3CF9100CEA6C8 /* NSView+RSCore.m in Sources */ = {isa = PBXBuildFile; fileRef = 84CFF5571AC3CF9100CEA6C8 /* NSView+RSCore.m */; }; + 84CFF55C1AC3D01F00CEA6C8 /* RSBackgroundColorView.h in Headers */ = {isa = PBXBuildFile; fileRef = 84CFF55A1AC3D01F00CEA6C8 /* RSBackgroundColorView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 84CFF55D1AC3D01F00CEA6C8 /* RSBackgroundColorView.m in Sources */ = {isa = PBXBuildFile; fileRef = 84CFF55B1AC3D01F00CEA6C8 /* RSBackgroundColorView.m */; }; + 84CFF5601AC3D0CE00CEA6C8 /* RSBinaryCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 84CFF55E1AC3D0CE00CEA6C8 /* RSBinaryCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 84CFF5611AC3D0CE00CEA6C8 /* RSBinaryCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 84CFF55F1AC3D0CE00CEA6C8 /* RSBinaryCache.m */; }; + 84CFF5641AC3D13C00CEA6C8 /* RSImageRenderer.h in Headers */ = {isa = PBXBuildFile; fileRef = 84CFF5621AC3D13C00CEA6C8 /* RSImageRenderer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 84CFF5651AC3D13C00CEA6C8 /* RSImageRenderer.m in Sources */ = {isa = PBXBuildFile; fileRef = 84CFF5631AC3D13C00CEA6C8 /* RSImageRenderer.m */; }; + 84CFF5691AC3D1B000CEA6C8 /* RSScaling.h in Headers */ = {isa = PBXBuildFile; fileRef = 84CFF5671AC3D1B000CEA6C8 /* RSScaling.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 84CFF56A1AC3D1B000CEA6C8 /* RSScaling.m in Sources */ = {isa = PBXBuildFile; fileRef = 84CFF5681AC3D1B000CEA6C8 /* RSScaling.m */; }; + 84CFF56D1AC3D20A00CEA6C8 /* NSImage+RSCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 84CFF56B1AC3D20A00CEA6C8 /* NSImage+RSCore.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 84CFF56E1AC3D20A00CEA6C8 /* NSImage+RSCore.m in Sources */ = {isa = PBXBuildFile; fileRef = 84CFF56C1AC3D20A00CEA6C8 /* NSImage+RSCore.m */; }; + 84FE9FC31C00453900081CE9 /* NSStoryboard+RSCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 84FE9FC11C00453900081CE9 /* NSStoryboard+RSCore.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 84FE9FC41C00453900081CE9 /* NSStoryboard+RSCore.m in Sources */ = {isa = PBXBuildFile; fileRef = 84FE9FC21C00453900081CE9 /* NSStoryboard+RSCore.m */; }; + 84FEB4AC1D19D7F4004727E5 /* Date+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84FEB4AB1D19D7F4004727E5 /* Date+Extensions.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 84CFF5011AC3C69700CEA6C8 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 84CFF4EB1AC3C69700CEA6C8 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 84CFF4F31AC3C69700CEA6C8; + remoteInfo = RSCore; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 84134D1D1C59D5450063FD24 /* NSCalendar+RSCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSCalendar+RSCore.h"; sourceTree = ""; }; + 84134D1E1C59D5450063FD24 /* NSCalendar+RSCore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSCalendar+RSCore.m"; sourceTree = ""; }; + 8414CBA61C95F2EA00333C12 /* Set+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Set+Extensions.swift"; sourceTree = ""; }; + 8414CBA91C95F8F700333C12 /* RSGeometry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RSGeometry.h; sourceTree = ""; }; + 8414CBAA1C95F8F700333C12 /* RSGeometry.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RSGeometry.m; sourceTree = ""; }; + 8415CB881BF84D24007B1E98 /* NSEvent+RSCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSEvent+RSCore.h"; sourceTree = ""; }; + 8415CB891BF84D24007B1E98 /* NSEvent+RSCore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSEvent+RSCore.m"; sourceTree = ""; }; + 8417FE001AC67D430048E9B7 /* RSOpaqueContainerView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RSOpaqueContainerView.h; sourceTree = ""; }; + 8417FE011AC67D430048E9B7 /* RSOpaqueContainerView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RSOpaqueContainerView.m; sourceTree = ""; }; + 842635561D7FA1C800196285 /* NSTableView+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSTableView+Extensions.swift"; sourceTree = ""; }; + 842635581D7FA24800196285 /* NSOutlineView+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSOutlineView+Extensions.swift"; sourceTree = ""; }; + 842DD7BC1E14993900E061EB /* RSCore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = RSCore.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 842DD7BF1E14993900E061EB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 8432B1851DACA0E90057D6DF /* NSResponder-Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSResponder-Extensions.swift"; sourceTree = ""; }; + 8432B1871DACA2060057D6DF /* NSWindow-Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSWindow-Extensions.swift"; sourceTree = ""; }; + 844C91591B65753E0051FC1B /* RSPlist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RSPlist.h; path = RSCore/RSPlist.h; sourceTree = ""; }; + 844C915A1B65753E0051FC1B /* RSPlist.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RSPlist.m; path = RSCore/RSPlist.m; sourceTree = ""; }; + 844F91D31D90D86100820C48 /* RSTransparentContainerView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RSTransparentContainerView.h; sourceTree = ""; }; + 844F91D41D90D86100820C48 /* RSTransparentContainerView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RSTransparentContainerView.m; sourceTree = ""; }; + 84536F641BB856D4001E1639 /* NSFileManager+RSCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSFileManager+RSCore.h"; sourceTree = ""; }; + 84536F651BB856D4001E1639 /* NSFileManager+RSCore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSFileManager+RSCore.m"; sourceTree = ""; }; + 8453F7DC1BDF337800B1C8ED /* RSMacroProcessor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RSMacroProcessor.h; path = RSCore/RSMacroProcessor.h; sourceTree = ""; }; + 8453F7DD1BDF337800B1C8ED /* RSMacroProcessor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RSMacroProcessor.m; path = RSCore/RSMacroProcessor.m; sourceTree = ""; }; + 845DE0F11B80477100D1571B /* NSSet+RSCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSSet+RSCore.h"; sourceTree = ""; }; + 845DE0F21B80477100D1571B /* NSSet+RSCore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSSet+RSCore.m"; sourceTree = ""; }; + 8461387E1DB3F5BE00048B83 /* RSToolbarItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RSToolbarItem.swift; sourceTree = ""; }; + 849A339B1AC90A0A0015BA09 /* NSTableView+RSCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSTableView+RSCore.h"; sourceTree = ""; }; + 849A339C1AC90A0A0015BA09 /* NSTableView+RSCore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSTableView+RSCore.m"; sourceTree = ""; }; + 849B08951BF7BCE30090CEE4 /* NSPasteboard+RSCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSPasteboard+RSCore.h"; sourceTree = ""; }; + 849B08961BF7BCE30090CEE4 /* NSPasteboard+RSCore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSPasteboard+RSCore.m"; sourceTree = ""; }; + 849BF8B91C9130150071D1DA /* DiskSaver.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DiskSaver.swift; path = RSCore/DiskSaver.swift; sourceTree = ""; }; + 84A835891D4EC7B80004C598 /* PlistProviderProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PlistProviderProtocol.swift; path = RSCore/PlistProviderProtocol.swift; sourceTree = ""; }; + 84B890551C59CF1600D8BF23 /* NSString+ExtrasTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+ExtrasTests.m"; sourceTree = ""; }; + 84BB45421D6909C700B48537 /* NSMutableDictionary-Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSMutableDictionary-Extensions.swift"; sourceTree = ""; }; + 84CFF4F41AC3C69700CEA6C8 /* RSCore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = RSCore.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 84CFF4F81AC3C69700CEA6C8 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = RSCore/Info.plist; sourceTree = ""; }; + 84CFF4F91AC3C69700CEA6C8 /* RSCore.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = RSCore.h; path = RSCore/RSCore.h; sourceTree = ""; }; + 84CFF4FF1AC3C69700CEA6C8 /* RSCoreTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RSCoreTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 84CFF5051AC3C69700CEA6C8 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 84CFF5061AC3C69700CEA6C8 /* RSCoreTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RSCoreTests.m; sourceTree = ""; }; + 84CFF5101AC3C6D800CEA6C8 /* RSBlocks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RSBlocks.h; path = RSCore/RSBlocks.h; sourceTree = ""; }; + 84CFF5111AC3C6D800CEA6C8 /* RSBlocks.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RSBlocks.m; path = RSCore/RSBlocks.m; sourceTree = ""; }; + 84CFF5141AC3C73000CEA6C8 /* RSConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RSConstants.h; path = RSCore/RSConstants.h; sourceTree = ""; }; + 84CFF5151AC3C73000CEA6C8 /* RSConstants.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RSConstants.m; path = RSCore/RSConstants.m; sourceTree = ""; }; + 84CFF5181AC3C77500CEA6C8 /* RSPlatform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RSPlatform.h; path = RSCore/RSPlatform.h; sourceTree = ""; }; + 84CFF5191AC3C77500CEA6C8 /* RSPlatform.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RSPlatform.m; path = RSCore/RSPlatform.m; sourceTree = ""; }; + 84CFF5201AC3C89D00CEA6C8 /* NSObject+RSCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+RSCore.h"; sourceTree = ""; }; + 84CFF5211AC3C89D00CEA6C8 /* NSObject+RSCore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+RSCore.m"; sourceTree = ""; }; + 84CFF5251AC3C9A200CEA6C8 /* NSArray+RSCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSArray+RSCore.h"; sourceTree = ""; }; + 84CFF5261AC3C9A200CEA6C8 /* NSArray+RSCore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSArray+RSCore.m"; sourceTree = ""; }; + 84CFF5291AC3CA9700CEA6C8 /* NSData+RSCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSData+RSCore.h"; sourceTree = ""; }; + 84CFF52A1AC3CA9700CEA6C8 /* NSData+RSCore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSData+RSCore.m"; sourceTree = ""; }; + 84CFF52D1AC3CB1900CEA6C8 /* NSDate+RSCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDate+RSCore.h"; sourceTree = ""; }; + 84CFF52E1AC3CB1900CEA6C8 /* NSDate+RSCore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSDate+RSCore.m"; sourceTree = ""; }; + 84CFF5311AC3CB6800CEA6C8 /* NSDictionary+RSCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDictionary+RSCore.h"; sourceTree = ""; }; + 84CFF5321AC3CB6800CEA6C8 /* NSDictionary+RSCore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSDictionary+RSCore.m"; sourceTree = ""; }; + 84CFF5351AC3CBB200CEA6C8 /* NSMutableArray+RSCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSMutableArray+RSCore.h"; sourceTree = ""; }; + 84CFF5361AC3CBB200CEA6C8 /* NSMutableArray+RSCore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSMutableArray+RSCore.m"; sourceTree = ""; }; + 84CFF5391AC3CCCA00CEA6C8 /* NSMutableDictionary+RSCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSMutableDictionary+RSCore.h"; sourceTree = ""; }; + 84CFF53A1AC3CCCA00CEA6C8 /* NSMutableDictionary+RSCore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSMutableDictionary+RSCore.m"; sourceTree = ""; }; + 84CFF53D1AC3CD0100CEA6C8 /* NSMutableSet+RSCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSMutableSet+RSCore.h"; sourceTree = ""; }; + 84CFF53E1AC3CD0100CEA6C8 /* NSMutableSet+RSCore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSMutableSet+RSCore.m"; sourceTree = ""; }; + 84CFF5411AC3CD3500CEA6C8 /* NSNotificationCenter+RSCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSNotificationCenter+RSCore.h"; sourceTree = ""; }; + 84CFF5421AC3CD3500CEA6C8 /* NSNotificationCenter+RSCore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSNotificationCenter+RSCore.m"; sourceTree = ""; }; + 84CFF5451AC3CD8000CEA6C8 /* NSTimer+RSCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSTimer+RSCore.h"; sourceTree = ""; }; + 84CFF5461AC3CD8000CEA6C8 /* NSTimer+RSCore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSTimer+RSCore.m"; sourceTree = ""; }; + 84CFF5491AC3CDAC00CEA6C8 /* NSString+RSCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+RSCore.h"; sourceTree = ""; }; + 84CFF54A1AC3CDAC00CEA6C8 /* NSString+RSCore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+RSCore.m"; sourceTree = ""; }; + 84CFF5511AC3CF4700CEA6C8 /* NSColor+RSCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSColor+RSCore.h"; sourceTree = ""; }; + 84CFF5521AC3CF4700CEA6C8 /* NSColor+RSCore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSColor+RSCore.m"; sourceTree = ""; }; + 84CFF5561AC3CF9100CEA6C8 /* NSView+RSCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSView+RSCore.h"; sourceTree = ""; }; + 84CFF5571AC3CF9100CEA6C8 /* NSView+RSCore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSView+RSCore.m"; sourceTree = ""; }; + 84CFF55A1AC3D01F00CEA6C8 /* RSBackgroundColorView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RSBackgroundColorView.h; sourceTree = ""; }; + 84CFF55B1AC3D01F00CEA6C8 /* RSBackgroundColorView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RSBackgroundColorView.m; sourceTree = ""; }; + 84CFF55E1AC3D0CE00CEA6C8 /* RSBinaryCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RSBinaryCache.h; path = RSCore/RSBinaryCache.h; sourceTree = ""; }; + 84CFF55F1AC3D0CE00CEA6C8 /* RSBinaryCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RSBinaryCache.m; path = RSCore/RSBinaryCache.m; sourceTree = ""; }; + 84CFF5621AC3D13C00CEA6C8 /* RSImageRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RSImageRenderer.h; sourceTree = ""; }; + 84CFF5631AC3D13C00CEA6C8 /* RSImageRenderer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RSImageRenderer.m; sourceTree = ""; }; + 84CFF5671AC3D1B000CEA6C8 /* RSScaling.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RSScaling.h; sourceTree = ""; }; + 84CFF5681AC3D1B000CEA6C8 /* RSScaling.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RSScaling.m; sourceTree = ""; }; + 84CFF56B1AC3D20A00CEA6C8 /* NSImage+RSCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSImage+RSCore.h"; sourceTree = ""; }; + 84CFF56C1AC3D20A00CEA6C8 /* NSImage+RSCore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSImage+RSCore.m"; sourceTree = ""; }; + 84FE9FC11C00453900081CE9 /* NSStoryboard+RSCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSStoryboard+RSCore.h"; sourceTree = ""; }; + 84FE9FC21C00453900081CE9 /* NSStoryboard+RSCore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSStoryboard+RSCore.m"; sourceTree = ""; }; + 84FEB4AB1D19D7F4004727E5 /* Date+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Date+Extensions.swift"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 842DD7B81E14993900E061EB /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 84CFF4F01AC3C69700CEA6C8 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 84CFF4FC1AC3C69700CEA6C8 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 84CFF5001AC3C69700CEA6C8 /* RSCore.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 842DD7BD1E14993900E061EB /* RSCoreiOS */ = { + isa = PBXGroup; + children = ( + 842DD7BF1E14993900E061EB /* Info.plist */, + ); + path = RSCoreiOS; + sourceTree = ""; + }; + 842DD7F91E1499FA00E061EB /* Views */ = { + isa = PBXGroup; + children = ( + 84CFF55A1AC3D01F00CEA6C8 /* RSBackgroundColorView.h */, + 84CFF55B1AC3D01F00CEA6C8 /* RSBackgroundColorView.m */, + 844F91D31D90D86100820C48 /* RSTransparentContainerView.h */, + 844F91D41D90D86100820C48 /* RSTransparentContainerView.m */, + 8417FE001AC67D430048E9B7 /* RSOpaqueContainerView.h */, + 8417FE011AC67D430048E9B7 /* RSOpaqueContainerView.m */, + ); + name = Views; + sourceTree = ""; + }; + 84CFF4EA1AC3C69700CEA6C8 = { + isa = PBXGroup; + children = ( + 84CFF4F91AC3C69700CEA6C8 /* RSCore.h */, + 84CFF5101AC3C6D800CEA6C8 /* RSBlocks.h */, + 84CFF5111AC3C6D800CEA6C8 /* RSBlocks.m */, + 84CFF5141AC3C73000CEA6C8 /* RSConstants.h */, + 84CFF5151AC3C73000CEA6C8 /* RSConstants.m */, + 84CFF5181AC3C77500CEA6C8 /* RSPlatform.h */, + 84CFF5191AC3C77500CEA6C8 /* RSPlatform.m */, + 84CFF55E1AC3D0CE00CEA6C8 /* RSBinaryCache.h */, + 84CFF55F1AC3D0CE00CEA6C8 /* RSBinaryCache.m */, + 844C91591B65753E0051FC1B /* RSPlist.h */, + 844C915A1B65753E0051FC1B /* RSPlist.m */, + 8453F7DC1BDF337800B1C8ED /* RSMacroProcessor.h */, + 8453F7DD1BDF337800B1C8ED /* RSMacroProcessor.m */, + 849BF8B91C9130150071D1DA /* DiskSaver.swift */, + 84A835891D4EC7B80004C598 /* PlistProviderProtocol.swift */, + 84CFF5241AC3C8A200CEA6C8 /* Foundation */, + 84CFF5551AC3CF4A00CEA6C8 /* AppKit */, + 84CFF5661AC3D13F00CEA6C8 /* Images */, + 84CFF4F81AC3C69700CEA6C8 /* Info.plist */, + 84CFF5031AC3C69700CEA6C8 /* RSCoreTests */, + 842DD7BD1E14993900E061EB /* RSCoreiOS */, + 84CFF4F51AC3C69700CEA6C8 /* Products */, + ); + sourceTree = ""; + }; + 84CFF4F51AC3C69700CEA6C8 /* Products */ = { + isa = PBXGroup; + children = ( + 84CFF4F41AC3C69700CEA6C8 /* RSCore.framework */, + 84CFF4FF1AC3C69700CEA6C8 /* RSCoreTests.xctest */, + 842DD7BC1E14993900E061EB /* RSCore.framework */, + ); + name = Products; + sourceTree = ""; + }; + 84CFF5031AC3C69700CEA6C8 /* RSCoreTests */ = { + isa = PBXGroup; + children = ( + 84CFF5061AC3C69700CEA6C8 /* RSCoreTests.m */, + 84B890551C59CF1600D8BF23 /* NSString+ExtrasTests.m */, + 84CFF5041AC3C69700CEA6C8 /* Supporting Files */, + ); + path = RSCoreTests; + sourceTree = ""; + }; + 84CFF5041AC3C69700CEA6C8 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 84CFF5051AC3C69700CEA6C8 /* Info.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 84CFF5241AC3C8A200CEA6C8 /* Foundation */ = { + isa = PBXGroup; + children = ( + 84CFF5251AC3C9A200CEA6C8 /* NSArray+RSCore.h */, + 84CFF5261AC3C9A200CEA6C8 /* NSArray+RSCore.m */, + 84134D1D1C59D5450063FD24 /* NSCalendar+RSCore.h */, + 84134D1E1C59D5450063FD24 /* NSCalendar+RSCore.m */, + 84CFF5291AC3CA9700CEA6C8 /* NSData+RSCore.h */, + 84CFF52A1AC3CA9700CEA6C8 /* NSData+RSCore.m */, + 84CFF52D1AC3CB1900CEA6C8 /* NSDate+RSCore.h */, + 84CFF52E1AC3CB1900CEA6C8 /* NSDate+RSCore.m */, + 84CFF5311AC3CB6800CEA6C8 /* NSDictionary+RSCore.h */, + 84CFF5321AC3CB6800CEA6C8 /* NSDictionary+RSCore.m */, + 84536F641BB856D4001E1639 /* NSFileManager+RSCore.h */, + 84536F651BB856D4001E1639 /* NSFileManager+RSCore.m */, + 84CFF5351AC3CBB200CEA6C8 /* NSMutableArray+RSCore.h */, + 84CFF5361AC3CBB200CEA6C8 /* NSMutableArray+RSCore.m */, + 84CFF5391AC3CCCA00CEA6C8 /* NSMutableDictionary+RSCore.h */, + 84CFF53A1AC3CCCA00CEA6C8 /* NSMutableDictionary+RSCore.m */, + 84CFF53D1AC3CD0100CEA6C8 /* NSMutableSet+RSCore.h */, + 84CFF53E1AC3CD0100CEA6C8 /* NSMutableSet+RSCore.m */, + 84CFF5411AC3CD3500CEA6C8 /* NSNotificationCenter+RSCore.h */, + 84CFF5421AC3CD3500CEA6C8 /* NSNotificationCenter+RSCore.m */, + 84CFF5201AC3C89D00CEA6C8 /* NSObject+RSCore.h */, + 84CFF5211AC3C89D00CEA6C8 /* NSObject+RSCore.m */, + 845DE0F11B80477100D1571B /* NSSet+RSCore.h */, + 845DE0F21B80477100D1571B /* NSSet+RSCore.m */, + 84CFF5491AC3CDAC00CEA6C8 /* NSString+RSCore.h */, + 84CFF54A1AC3CDAC00CEA6C8 /* NSString+RSCore.m */, + 84CFF5451AC3CD8000CEA6C8 /* NSTimer+RSCore.h */, + 84CFF5461AC3CD8000CEA6C8 /* NSTimer+RSCore.m */, + 84FEB4AB1D19D7F4004727E5 /* Date+Extensions.swift */, + 84BB45421D6909C700B48537 /* NSMutableDictionary-Extensions.swift */, + 8414CBA61C95F2EA00333C12 /* Set+Extensions.swift */, + ); + name = Foundation; + path = RSCore; + sourceTree = ""; + }; + 84CFF5551AC3CF4A00CEA6C8 /* AppKit */ = { + isa = PBXGroup; + children = ( + 84CFF5511AC3CF4700CEA6C8 /* NSColor+RSCore.h */, + 84CFF5521AC3CF4700CEA6C8 /* NSColor+RSCore.m */, + 8415CB881BF84D24007B1E98 /* NSEvent+RSCore.h */, + 8415CB891BF84D24007B1E98 /* NSEvent+RSCore.m */, + 84CFF56B1AC3D20A00CEA6C8 /* NSImage+RSCore.h */, + 84CFF56C1AC3D20A00CEA6C8 /* NSImage+RSCore.m */, + 842635581D7FA24800196285 /* NSOutlineView+Extensions.swift */, + 849B08951BF7BCE30090CEE4 /* NSPasteboard+RSCore.h */, + 849B08961BF7BCE30090CEE4 /* NSPasteboard+RSCore.m */, + 8432B1851DACA0E90057D6DF /* NSResponder-Extensions.swift */, + 84FE9FC11C00453900081CE9 /* NSStoryboard+RSCore.h */, + 84FE9FC21C00453900081CE9 /* NSStoryboard+RSCore.m */, + 842635561D7FA1C800196285 /* NSTableView+Extensions.swift */, + 849A339B1AC90A0A0015BA09 /* NSTableView+RSCore.h */, + 849A339C1AC90A0A0015BA09 /* NSTableView+RSCore.m */, + 84CFF5561AC3CF9100CEA6C8 /* NSView+RSCore.h */, + 84CFF5571AC3CF9100CEA6C8 /* NSView+RSCore.m */, + 8432B1871DACA2060057D6DF /* NSWindow-Extensions.swift */, + 8414CBA91C95F8F700333C12 /* RSGeometry.h */, + 8414CBAA1C95F8F700333C12 /* RSGeometry.m */, + 8461387E1DB3F5BE00048B83 /* RSToolbarItem.swift */, + 842DD7F91E1499FA00E061EB /* Views */, + ); + name = AppKit; + path = RSCore; + sourceTree = ""; + }; + 84CFF5661AC3D13F00CEA6C8 /* Images */ = { + isa = PBXGroup; + children = ( + 84CFF5621AC3D13C00CEA6C8 /* RSImageRenderer.h */, + 84CFF5631AC3D13C00CEA6C8 /* RSImageRenderer.m */, + 84CFF5671AC3D1B000CEA6C8 /* RSScaling.h */, + 84CFF5681AC3D1B000CEA6C8 /* RSScaling.m */, + ); + name = Images; + path = RSCore; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 842DD7B91E14993900E061EB /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 842DD7E21E14996300E061EB /* NSMutableArray+RSCore.h in Headers */, + 842DD7E81E14996300E061EB /* NSNotificationCenter+RSCore.h in Headers */, + 842DD7DA1E14996300E061EB /* NSData+RSCore.h in Headers */, + 842DD7EE1E14996300E061EB /* NSString+RSCore.h in Headers */, + 842DD7C91E14995C00E061EB /* RSPlatform.h in Headers */, + 842DD7F51E14997600E061EB /* RSImageRenderer.h in Headers */, + 842DD7EC1E14996300E061EB /* NSSet+RSCore.h in Headers */, + 842DD7C41E14995000E061EB /* RSCore.h in Headers */, + 842DD7F71E14997600E061EB /* RSScaling.h in Headers */, + 842DD7C71E14995C00E061EB /* RSConstants.h in Headers */, + 842DD7D81E14996300E061EB /* NSCalendar+RSCore.h in Headers */, + 842DD7EA1E14996300E061EB /* NSObject+RSCore.h in Headers */, + 842DD7CB1E14995C00E061EB /* RSBinaryCache.h in Headers */, + 842DD7CD1E14995C00E061EB /* RSPlist.h in Headers */, + 842DD7C51E14995C00E061EB /* RSBlocks.h in Headers */, + 842DD7E01E14996300E061EB /* NSFileManager+RSCore.h in Headers */, + 842DD7E61E14996300E061EB /* NSMutableSet+RSCore.h in Headers */, + 842DD7D61E14996300E061EB /* NSArray+RSCore.h in Headers */, + 842DD7E41E14996300E061EB /* NSMutableDictionary+RSCore.h in Headers */, + 842DD7DE1E14996300E061EB /* NSDictionary+RSCore.h in Headers */, + 842DD7CF1E14995C00E061EB /* RSMacroProcessor.h in Headers */, + 842DD7DC1E14996300E061EB /* NSDate+RSCore.h in Headers */, + 842DD7F01E14996300E061EB /* NSTimer+RSCore.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 84CFF4F11AC3C69700CEA6C8 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 84CFF5691AC3D1B000CEA6C8 /* RSScaling.h in Headers */, + 84CFF53B1AC3CCCA00CEA6C8 /* NSMutableDictionary+RSCore.h in Headers */, + 84CFF5581AC3CF9100CEA6C8 /* NSView+RSCore.h in Headers */, + 84CFF5221AC3C89D00CEA6C8 /* NSObject+RSCore.h in Headers */, + 84134D1F1C59D5450063FD24 /* NSCalendar+RSCore.h in Headers */, + 849A339D1AC90A0A0015BA09 /* NSTableView+RSCore.h in Headers */, + 84CFF52B1AC3CA9700CEA6C8 /* NSData+RSCore.h in Headers */, + 84CFF51A1AC3C77500CEA6C8 /* RSPlatform.h in Headers */, + 8417FE021AC67D430048E9B7 /* RSOpaqueContainerView.h in Headers */, + 84CFF5371AC3CBB200CEA6C8 /* NSMutableArray+RSCore.h in Headers */, + 84CFF5641AC3D13C00CEA6C8 /* RSImageRenderer.h in Headers */, + 84CFF5271AC3C9A200CEA6C8 /* NSArray+RSCore.h in Headers */, + 84CFF5531AC3CF4700CEA6C8 /* NSColor+RSCore.h in Headers */, + 84CFF4FA1AC3C69700CEA6C8 /* RSCore.h in Headers */, + 844F91D51D90D86100820C48 /* RSTransparentContainerView.h in Headers */, + 84CFF53F1AC3CD0100CEA6C8 /* NSMutableSet+RSCore.h in Headers */, + 84CFF5601AC3D0CE00CEA6C8 /* RSBinaryCache.h in Headers */, + 84CFF5121AC3C6D800CEA6C8 /* RSBlocks.h in Headers */, + 84CFF56D1AC3D20A00CEA6C8 /* NSImage+RSCore.h in Headers */, + 84CFF5471AC3CD8000CEA6C8 /* NSTimer+RSCore.h in Headers */, + 84CFF5331AC3CB6800CEA6C8 /* NSDictionary+RSCore.h in Headers */, + 84CFF54B1AC3CDAC00CEA6C8 /* NSString+RSCore.h in Headers */, + 84CFF55C1AC3D01F00CEA6C8 /* RSBackgroundColorView.h in Headers */, + 84CFF5161AC3C73000CEA6C8 /* RSConstants.h in Headers */, + 84536F661BB856D4001E1639 /* NSFileManager+RSCore.h in Headers */, + 84CFF52F1AC3CB1900CEA6C8 /* NSDate+RSCore.h in Headers */, + 8414CBAB1C95F8F700333C12 /* RSGeometry.h in Headers */, + 845DE0F31B80477100D1571B /* NSSet+RSCore.h in Headers */, + 844C915B1B65753E0051FC1B /* RSPlist.h in Headers */, + 8453F7DE1BDF337800B1C8ED /* RSMacroProcessor.h in Headers */, + 8415CB8A1BF84D24007B1E98 /* NSEvent+RSCore.h in Headers */, + 849B08971BF7BCE30090CEE4 /* NSPasteboard+RSCore.h in Headers */, + 84FE9FC31C00453900081CE9 /* NSStoryboard+RSCore.h in Headers */, + 84CFF5431AC3CD3500CEA6C8 /* NSNotificationCenter+RSCore.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 842DD7BB1E14993900E061EB /* RSCoreiOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 842DD7C11E14993900E061EB /* Build configuration list for PBXNativeTarget "RSCoreiOS" */; + buildPhases = ( + 842DD7B71E14993900E061EB /* Sources */, + 842DD7B81E14993900E061EB /* Frameworks */, + 842DD7B91E14993900E061EB /* Headers */, + 842DD7BA1E14993900E061EB /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = RSCoreiOS; + productName = RSCoreiOS; + productReference = 842DD7BC1E14993900E061EB /* RSCore.framework */; + productType = "com.apple.product-type.framework"; + }; + 84CFF4F31AC3C69700CEA6C8 /* RSCore */ = { + isa = PBXNativeTarget; + buildConfigurationList = 84CFF50A1AC3C69700CEA6C8 /* Build configuration list for PBXNativeTarget "RSCore" */; + buildPhases = ( + 84CFF4EF1AC3C69700CEA6C8 /* Sources */, + 84CFF4F01AC3C69700CEA6C8 /* Frameworks */, + 84CFF4F11AC3C69700CEA6C8 /* Headers */, + 84CFF4F21AC3C69700CEA6C8 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = RSCore; + productName = RSCore; + productReference = 84CFF4F41AC3C69700CEA6C8 /* RSCore.framework */; + productType = "com.apple.product-type.framework"; + }; + 84CFF4FE1AC3C69700CEA6C8 /* RSCoreTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 84CFF50D1AC3C69700CEA6C8 /* Build configuration list for PBXNativeTarget "RSCoreTests" */; + buildPhases = ( + 84CFF4FB1AC3C69700CEA6C8 /* Sources */, + 84CFF4FC1AC3C69700CEA6C8 /* Frameworks */, + 84CFF4FD1AC3C69700CEA6C8 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 84CFF5021AC3C69700CEA6C8 /* PBXTargetDependency */, + ); + name = RSCoreTests; + productName = RSCoreTests; + productReference = 84CFF4FF1AC3C69700CEA6C8 /* RSCoreTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 84CFF4EB1AC3C69700CEA6C8 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0720; + LastUpgradeCheck = 0620; + ORGANIZATIONNAME = "Ranchero Software, LLC"; + TargetAttributes = { + 842DD7BB1E14993900E061EB = { + CreatedOnToolsVersion = 8.2.1; + DevelopmentTeam = 9C84TZ7Q6Z; + LastSwiftMigration = 0820; + ProvisioningStyle = Automatic; + }; + 84CFF4F31AC3C69700CEA6C8 = { + CreatedOnToolsVersion = 6.2; + LastSwiftMigration = 0800; + }; + 84CFF4FE1AC3C69700CEA6C8 = { + CreatedOnToolsVersion = 6.2; + LastSwiftMigration = 0800; + }; + }; + }; + buildConfigurationList = 84CFF4EE1AC3C69700CEA6C8 /* Build configuration list for PBXProject "RSCore" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 84CFF4EA1AC3C69700CEA6C8; + productRefGroup = 84CFF4F51AC3C69700CEA6C8 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 84CFF4F31AC3C69700CEA6C8 /* RSCore */, + 84CFF4FE1AC3C69700CEA6C8 /* RSCoreTests */, + 842DD7BB1E14993900E061EB /* RSCoreiOS */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 842DD7BA1E14993900E061EB /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 84CFF4F21AC3C69700CEA6C8 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 84CFF4FD1AC3C69700CEA6C8 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 842DD7B71E14993900E061EB /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 842DD7EB1E14996300E061EB /* NSObject+RSCore.m in Sources */, + 842DD7F81E14997600E061EB /* RSScaling.m in Sources */, + 842DD7D01E14995C00E061EB /* RSMacroProcessor.m in Sources */, + 842DD7E51E14996300E061EB /* NSMutableDictionary+RSCore.m in Sources */, + 842DD7F41E14996B00E061EB /* Set+Extensions.swift in Sources */, + 842DD7D71E14996300E061EB /* NSArray+RSCore.m in Sources */, + 842DD7CC1E14995C00E061EB /* RSBinaryCache.m in Sources */, + 842DD7F31E14996B00E061EB /* NSMutableDictionary-Extensions.swift in Sources */, + 842DD7DF1E14996300E061EB /* NSDictionary+RSCore.m in Sources */, + 842DD7C81E14995C00E061EB /* RSConstants.m in Sources */, + 842DD7D41E14995C00E061EB /* DiskSaver.swift in Sources */, + 842DD7E11E14996300E061EB /* NSFileManager+RSCore.m in Sources */, + 842DD7C61E14995C00E061EB /* RSBlocks.m in Sources */, + 842DD7DD1E14996300E061EB /* NSDate+RSCore.m in Sources */, + 842DD7E91E14996300E061EB /* NSNotificationCenter+RSCore.m in Sources */, + 842DD7E71E14996300E061EB /* NSMutableSet+RSCore.m in Sources */, + 842DD7E31E14996300E061EB /* NSMutableArray+RSCore.m in Sources */, + 842DD7DB1E14996300E061EB /* NSData+RSCore.m in Sources */, + 842DD7D51E14995C00E061EB /* PlistProviderProtocol.swift in Sources */, + 842DD7CE1E14995C00E061EB /* RSPlist.m in Sources */, + 842DD7EF1E14996300E061EB /* NSString+RSCore.m in Sources */, + 842DD7F21E14996B00E061EB /* Date+Extensions.swift in Sources */, + 842DD7ED1E14996300E061EB /* NSSet+RSCore.m in Sources */, + 842DD7CA1E14995C00E061EB /* RSPlatform.m in Sources */, + 842DD7D91E14996300E061EB /* NSCalendar+RSCore.m in Sources */, + 842DD7F11E14996300E061EB /* NSTimer+RSCore.m in Sources */, + 842DD7F61E14997600E061EB /* RSImageRenderer.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 84CFF4EF1AC3C69700CEA6C8 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 8417FE031AC67D430048E9B7 /* RSOpaqueContainerView.m in Sources */, + 84CFF5481AC3CD8000CEA6C8 /* NSTimer+RSCore.m in Sources */, + 849BF8BA1C9130150071D1DA /* DiskSaver.swift in Sources */, + 84FE9FC41C00453900081CE9 /* NSStoryboard+RSCore.m in Sources */, + 84CFF5341AC3CB6800CEA6C8 /* NSDictionary+RSCore.m in Sources */, + 84CFF54C1AC3CDAC00CEA6C8 /* NSString+RSCore.m in Sources */, + 84CFF5171AC3C73000CEA6C8 /* RSConstants.m in Sources */, + 8432B1881DACA2060057D6DF /* NSWindow-Extensions.swift in Sources */, + 84CFF5541AC3CF4700CEA6C8 /* NSColor+RSCore.m in Sources */, + 84536F671BB856D4001E1639 /* NSFileManager+RSCore.m in Sources */, + 8415CB8B1BF84D24007B1E98 /* NSEvent+RSCore.m in Sources */, + 84CFF53C1AC3CCCA00CEA6C8 /* NSMutableDictionary+RSCore.m in Sources */, + 8414CBAC1C95F8F700333C12 /* RSGeometry.m in Sources */, + 84134D201C59D5450063FD24 /* NSCalendar+RSCore.m in Sources */, + 84CFF5651AC3D13C00CEA6C8 /* RSImageRenderer.m in Sources */, + 84CFF5381AC3CBB200CEA6C8 /* NSMutableArray+RSCore.m in Sources */, + 84CFF5401AC3CD0100CEA6C8 /* NSMutableSet+RSCore.m in Sources */, + 84CFF5441AC3CD3500CEA6C8 /* NSNotificationCenter+RSCore.m in Sources */, + 84CFF55D1AC3D01F00CEA6C8 /* RSBackgroundColorView.m in Sources */, + 84CFF5131AC3C6D800CEA6C8 /* RSBlocks.m in Sources */, + 8432B1861DACA0E90057D6DF /* NSResponder-Extensions.swift in Sources */, + 849B08981BF7BCE30090CEE4 /* NSPasteboard+RSCore.m in Sources */, + 842635571D7FA1C800196285 /* NSTableView+Extensions.swift in Sources */, + 84CFF5611AC3D0CE00CEA6C8 /* RSBinaryCache.m in Sources */, + 84CFF5301AC3CB1900CEA6C8 /* NSDate+RSCore.m in Sources */, + 84CFF5281AC3C9A200CEA6C8 /* NSArray+RSCore.m in Sources */, + 84CFF5591AC3CF9100CEA6C8 /* NSView+RSCore.m in Sources */, + 84CFF56A1AC3D1B000CEA6C8 /* RSScaling.m in Sources */, + 84FEB4AC1D19D7F4004727E5 /* Date+Extensions.swift in Sources */, + 8461387F1DB3F5BE00048B83 /* RSToolbarItem.swift in Sources */, + 84BB45431D6909C700B48537 /* NSMutableDictionary-Extensions.swift in Sources */, + 845DE0F41B80477100D1571B /* NSSet+RSCore.m in Sources */, + 842635591D7FA24800196285 /* NSOutlineView+Extensions.swift in Sources */, + 844C915C1B65753E0051FC1B /* RSPlist.m in Sources */, + 84CFF5231AC3C89D00CEA6C8 /* NSObject+RSCore.m in Sources */, + 8414CBA71C95F2EA00333C12 /* Set+Extensions.swift in Sources */, + 844F91D61D90D86100820C48 /* RSTransparentContainerView.m in Sources */, + 84CFF56E1AC3D20A00CEA6C8 /* NSImage+RSCore.m in Sources */, + 8453F7DF1BDF337800B1C8ED /* RSMacroProcessor.m in Sources */, + 84A8358A1D4EC7B80004C598 /* PlistProviderProtocol.swift in Sources */, + 849A339E1AC90A0A0015BA09 /* NSTableView+RSCore.m in Sources */, + 84CFF51B1AC3C77500CEA6C8 /* RSPlatform.m in Sources */, + 84CFF52C1AC3CA9700CEA6C8 /* NSData+RSCore.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 84CFF4FB1AC3C69700CEA6C8 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 84B890561C59CF1600D8BF23 /* NSString+ExtrasTests.m in Sources */, + 84CFF5071AC3C69700CEA6C8 /* RSCoreTests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 84CFF5021AC3C69700CEA6C8 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 84CFF4F31AC3C69700CEA6C8 /* RSCore */; + targetProxy = 84CFF5011AC3C69700CEA6C8 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 842DD7C21E14993900E061EB /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + DEBUG_INFORMATION_FORMAT = dwarf; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = 9C84TZ7Q6Z; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_TESTABILITY = YES; + GCC_NO_COMMON_BLOCKS = YES; + INFOPLIST_FILE = RSCoreiOS/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 10.2; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.ranchero.RSCoreiOS; + PRODUCT_NAME = RSCore; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_VERSION = 3.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 842DD7C31E14993900E061EB /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = 9C84TZ7Q6Z; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_NO_COMMON_BLOCKS = YES; + INFOPLIST_FILE = RSCoreiOS/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 10.2; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.ranchero.RSCoreiOS; + PRODUCT_NAME = RSCore; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_VERSION = 3.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 84CFF5081AC3C69700CEA6C8 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES; + CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YES; + CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_STATIC_ANALYZER_MODE = deep; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; + GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES; + GCC_TREAT_WARNINGS_AS_ERRORS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; + GCC_WARN_SHADOW = YES; + GCC_WARN_SIGN_COMPARE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNKNOWN_PRAGMAS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_LABEL = YES; + GCC_WARN_UNUSED_PARAMETER = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.10; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + RUN_CLANG_STATIC_ANALYZER = YES; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_TREAT_WARNINGS_AS_ERRORS = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 84CFF5091AC3C69700CEA6C8 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES; + CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YES; + CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_STATIC_ANALYZER_MODE = deep; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; + GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES; + GCC_TREAT_WARNINGS_AS_ERRORS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; + GCC_WARN_SHADOW = YES; + GCC_WARN_SIGN_COMPARE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNKNOWN_PRAGMAS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_LABEL = YES; + GCC_WARN_UNUSED_PARAMETER = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.10; + MTL_ENABLE_DEBUG_INFO = NO; + RUN_CLANG_STATIC_ANALYZER = YES; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_TREAT_WARNINGS_AS_ERRORS = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 84CFF50B1AC3C69700CEA6C8 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES; + CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES; + CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YES; + CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = YES; + CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_VERSION = A; + INFOPLIST_FILE = RSCore/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_VERSION = 3.0; + }; + name = Debug; + }; + 84CFF50C1AC3C69700CEA6C8 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES; + CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES; + CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YES; + CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = YES; + CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_VERSION = A; + INFOPLIST_FILE = RSCore/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_VERSION = 3.0; + }; + name = Release; + }; + 84CFF50E1AC3C69700CEA6C8 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + COMBINE_HIDPI_IMAGES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(DEVELOPER_FRAMEWORKS_DIR)", + "$(inherited)", + ); + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = RSCoreTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; + }; + name = Debug; + }; + 84CFF50F1AC3C69700CEA6C8 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + COMBINE_HIDPI_IMAGES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(DEVELOPER_FRAMEWORKS_DIR)", + "$(inherited)", + ); + INFOPLIST_FILE = RSCoreTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 842DD7C11E14993900E061EB /* Build configuration list for PBXNativeTarget "RSCoreiOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 842DD7C21E14993900E061EB /* Debug */, + 842DD7C31E14993900E061EB /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; + 84CFF4EE1AC3C69700CEA6C8 /* Build configuration list for PBXProject "RSCore" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 84CFF5081AC3C69700CEA6C8 /* Debug */, + 84CFF5091AC3C69700CEA6C8 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 84CFF50A1AC3C69700CEA6C8 /* Build configuration list for PBXNativeTarget "RSCore" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 84CFF50B1AC3C69700CEA6C8 /* Debug */, + 84CFF50C1AC3C69700CEA6C8 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 84CFF50D1AC3C69700CEA6C8 /* Build configuration list for PBXNativeTarget "RSCoreTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 84CFF50E1AC3C69700CEA6C8 /* Debug */, + 84CFF50F1AC3C69700CEA6C8 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 84CFF4EB1AC3C69700CEA6C8 /* Project object */; +} diff --git a/Frameworks/RSCore/RSCore.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Frameworks/RSCore/RSCore.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100755 index 000000000..467773e68 --- /dev/null +++ b/Frameworks/RSCore/RSCore.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Frameworks/RSCore/RSCore/Date+Extensions.swift b/Frameworks/RSCore/RSCore/Date+Extensions.swift new file mode 100755 index 000000000..12b0f77e0 --- /dev/null +++ b/Frameworks/RSCore/RSCore/Date+Extensions.swift @@ -0,0 +1,29 @@ +// +// Date+Extensions.swift +// RSCore +// +// Created by Brent Simmons on 6/21/16. +// Copyright © 2016 Ranchero Software, LLC. All rights reserved. +// + +import Foundation + +public extension Date { + + // Below are for rough use only — they don't use the calendar. + + public mutating func subtract(days: Int) { + + addTimeInterval(0.0 - timeIntervalWithDays(days)) + } + + public mutating func add(days: Int) { + + addTimeInterval(timeIntervalWithDays(days)) + } +} + +private func timeIntervalWithDays(_ days: Int) -> TimeInterval { + + return TimeInterval(days * 24 * 60 * 60) +} diff --git a/Frameworks/RSCore/RSCore/DiskSaver.swift b/Frameworks/RSCore/RSCore/DiskSaver.swift new file mode 100755 index 000000000..ffa9a81cc --- /dev/null +++ b/Frameworks/RSCore/RSCore/DiskSaver.swift @@ -0,0 +1,73 @@ +// +// DiskSaver.swift +// RSCore +// +// Created by Brent Simmons on 12/28/15. +// Copyright © 2015 Ranchero Software, LLC. All rights reserved. +// + +import Foundation + +public final class DiskSaver: NSObject { + + private let path: String + public weak var delegate: PlistProvider? + private var coalescedSaveTimer: Timer? + + public var dirty = false { + didSet { + if dirty { + coalescedSaveToDisk() + } + else { + invalidateSaveTimer() + } + } + } + + public init(path: String) { + + self.path = path + } + + deinit { + + if let timer = coalescedSaveTimer, timer.isValid { + timer.invalidate() + } + } + + private func invalidateSaveTimer() { + + if let timer = coalescedSaveTimer, timer.isValid { + timer.invalidate() + } + coalescedSaveTimer = nil + } + + private let coalescedSaveInterval = 1.0 + + private func coalescedSaveToDisk() { + + invalidateSaveTimer() + coalescedSaveTimer = Timer.scheduledTimer(timeInterval: coalescedSaveInterval, target: self, selector: #selector(saveToDisk), userInfo: nil, repeats: false) + } + + public dynamic func saveToDisk() { + + invalidateSaveTimer() + if !dirty { + return + } + if let d = delegate?.plist { + + do { + try RSPlist.write(d, filePath: path) + dirty = false + } + catch { + print("DiskSaver: error writing \(path) to disk.") + } + } + } +} diff --git a/Frameworks/RSCore/RSCore/Info.plist b/Frameworks/RSCore/RSCore/Info.plist new file mode 100755 index 000000000..b2ae8f4ae --- /dev/null +++ b/Frameworks/RSCore/RSCore/Info.plist @@ -0,0 +1,28 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + com.ranchero.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSHumanReadableCopyright + Copyright © 2015 Ranchero Software, LLC. All rights reserved. + NSPrincipalClass + + + diff --git a/Frameworks/RSCore/RSCore/NSArray+RSCore.h b/Frameworks/RSCore/RSCore/NSArray+RSCore.h new file mode 100755 index 000000000..db81e62c9 --- /dev/null +++ b/Frameworks/RSCore/RSCore/NSArray+RSCore.h @@ -0,0 +1,48 @@ +// +// NSArray+RSCore.h +// RSCore +// +// Created by Brent Simmons on 3/25/15. +// Copyright (c) 2015 Ranchero Software, LLC. All rights reserved. +// + +@import Foundation; +#import + + +BOOL RSEqualArrays(NSArray *array1, NSArray *array2); /*Yes if both nil, identical, or equal*/ + + +@interface NSArray (RSCore) + + +/*Returns nil if out of bounds instead of throwing an exception.*/ + +- (id)rs_safeObjectAtIndex:(NSUInteger)anIndex; + +/*Does valueForKey:key. When value isEqual, returns YES.*/ + +- (id)rs_firstObjectWhereValueForKey:(NSString *)key equalsValue:(id)value; + +- (id)rs_firstObjectPassingTest:(RSTestBlock)testBlock; + + +typedef id (^RSMapBlock)(id obj); + +- (NSArray *)rs_map:(RSMapBlock)mapBlock; + + +typedef BOOL (^RSFilterBlock)(id obj); + +- (NSArray *)rs_filter:(RSFilterBlock)filterBlock; + + +- (NSArray *)rs_arrayWithCopyOfEachObject; + + +/*Does [valueForKey:key] on each object and uses that as the key in the dictionary.*/ + +- (NSDictionary *)rs_dictionaryUsingKey:(id)key; + + +@end diff --git a/Frameworks/RSCore/RSCore/NSArray+RSCore.m b/Frameworks/RSCore/RSCore/NSArray+RSCore.m new file mode 100755 index 000000000..96271c77c --- /dev/null +++ b/Frameworks/RSCore/RSCore/NSArray+RSCore.m @@ -0,0 +1,103 @@ +// +// NSArray+RSCore.m +// RSCore +// +// Created by Brent Simmons on 3/25/15. +// Copyright (c) 2015 Ranchero Software, LLC. All rights reserved. +// + +#import "NSArray+RSCore.h" + + +BOOL RSEqualArrays(NSArray *array1, NSArray *array2) { + + return array1 == array2 || [array1 isEqualToArray:array2]; +} + + +@implementation NSArray (RSCore) + + +- (id)rs_safeObjectAtIndex:(NSUInteger)ix { + + if (self.count < 1 || ix >= self.count) { + return nil; + } + + return self[ix]; +} + + +- (id)rs_firstObjectWhereValueForKey:(NSString *)key equalsValue:(id)value { + + return [self rs_firstObjectPassingTest:^BOOL(id obj) { + return [[obj valueForKey:key] isEqual:value]; + }]; +} + + +- (id)rs_firstObjectPassingTest:(RSTestBlock)testBlock { + + for (id oneObject in self) { + if (testBlock(oneObject)) { + return oneObject; + } + } + return nil; +} + + +- (NSArray *)rs_map:(RSMapBlock)mapBlock { + + NSMutableArray *mappedArray = [NSMutableArray new]; + + for (id oneObject in self) { + + id objectToAdd = mapBlock(oneObject); + if (objectToAdd) { + [mappedArray addObject:objectToAdd]; + } + } + + return [mappedArray copy]; +} + + +- (NSArray *)rs_filter:(RSFilterBlock)filterBlock { + + NSMutableArray *filteredArray = [NSMutableArray new]; + + for (id oneObject in self) { + + if (filterBlock(oneObject)) { + [filteredArray addObject:oneObject]; + } + } + + return [filteredArray copy]; +} + + +- (NSArray *)rs_arrayWithCopyOfEachObject { + + return [self rs_map:^id(id obj) { + return [obj copy]; + }]; +} + + +- (NSDictionary *)rs_dictionaryUsingKey:(id)key { + + NSMutableDictionary *d = [NSMutableDictionary new]; + + for (id oneObject in self) { + + id oneUniqueID = [oneObject valueForKey:key]; + d[oneUniqueID] = oneObject; + } + + return [d copy]; +} + + +@end diff --git a/Frameworks/RSCore/RSCore/NSCalendar+RSCore.h b/Frameworks/RSCore/RSCore/NSCalendar+RSCore.h new file mode 100755 index 000000000..bad6b57dd --- /dev/null +++ b/Frameworks/RSCore/RSCore/NSCalendar+RSCore.h @@ -0,0 +1,16 @@ +// +// NSCalendar+RSCore.h +// RSCore +// +// Created by Brent Simmons on 1/27/16. +// Copyright © 2016 Ranchero Software, LLC. All rights reserved. +// + +@import Foundation; + +@interface NSCalendar (RSCore) + ++ (NSCalendar *)rs_cachedCalendar; ++ (BOOL)rs_dateIsToday:(NSDate *)d; + +@end diff --git a/Frameworks/RSCore/RSCore/NSCalendar+RSCore.m b/Frameworks/RSCore/RSCore/NSCalendar+RSCore.m new file mode 100755 index 000000000..60f17d1f3 --- /dev/null +++ b/Frameworks/RSCore/RSCore/NSCalendar+RSCore.m @@ -0,0 +1,76 @@ +// +// NSCalendar+RSCore.m +// RSCore +// +// Created by Brent Simmons on 1/27/16. +// Copyright © 2016 Ranchero Software, LLC. All rights reserved. +// + +@import Foundation; +#import "NSCalendar+RSCore.h" +#if TARGET_OS_IPHONE +@import UIKit; +#else +@import Cocoa; +#endif + +@implementation NSCalendar (RSCore) + +static NSCalendar *cachedCalendar = nil; + ++ (NSCalendar *)rs_cachedCalendar { + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + + cachedCalendar = [NSCalendar autoupdatingCurrentCalendar]; + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(rs_significantTimeChange:) name:NSSystemTimeZoneDidChangeNotification object:nil]; + +#if TARGET_OS_IPHONE + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(rs_significantTimeChange:) name:UIApplicationDidBecomeActiveNotification object:nil]; +#else + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(rs_significantTimeChange:) name:NSApplicationDidBecomeActiveNotification object:nil]; +#endif + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(rs_significantTimeChange:) name:NSCalendarDayChangedNotification object:nil]; + }); + + NSLock *lock = [self rs_cachedCalendarLock]; + [lock lock]; + NSCalendar *calendar = cachedCalendar; + [lock unlock]; + + return calendar; +} + + ++ (void)rs_significantTimeChange:(NSNotification *)note { + +#pragma unused(note) + + NSLock *lock = [self rs_cachedCalendarLock]; + [lock lock]; + cachedCalendar = [NSCalendar autoupdatingCurrentCalendar]; + [lock unlock]; +} + ++ (NSLock *)rs_cachedCalendarLock { + + static NSLock *lock = nil; + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + lock = [[NSLock alloc] init]; + }); + + return lock; +} + + ++ (BOOL)rs_dateIsToday:(NSDate *)d { + + return [[self rs_cachedCalendar] isDateInToday:d]; +} + + +@end diff --git a/Frameworks/RSCore/RSCore/NSColor+RSCore.h b/Frameworks/RSCore/RSCore/NSColor+RSCore.h new file mode 100755 index 000000000..b342e2ec4 --- /dev/null +++ b/Frameworks/RSCore/RSCore/NSColor+RSCore.h @@ -0,0 +1,18 @@ +// +// NSColor+RSCore.h +// RSCore +// +// Created by Brent Simmons on 3/25/15. +// Copyright (c) 2015 Ranchero Software, LLC. All rights reserved. +// + +@import Cocoa; + + +@interface NSColor (RSCore) + + ++ (NSColor *)rs_colorWithHexString:(NSString *)hexString; + + +@end diff --git a/Frameworks/RSCore/RSCore/NSColor+RSCore.m b/Frameworks/RSCore/RSCore/NSColor+RSCore.m new file mode 100755 index 000000000..13297b134 --- /dev/null +++ b/Frameworks/RSCore/RSCore/NSColor+RSCore.m @@ -0,0 +1,24 @@ +// +// NSColor+RSCore.m +// RSCore +// +// Created by Brent Simmons on 3/25/15. +// Copyright (c) 2015 Ranchero Software, LLC. All rights reserved. +// + +#import "NSColor+RSCore.h" +#import "NSString+RSCore.h" + + +@implementation NSColor (RSCore) + + ++ (NSColor *)rs_colorWithHexString:(NSString *)hexString { + + RSRGBAComponents components = [hexString rs_rgbaComponents]; + + return [NSColor colorWithRed:components.red green:components.green blue:components.blue alpha:components.alpha]; +} + + +@end diff --git a/Frameworks/RSCore/RSCore/NSData+RSCore.h b/Frameworks/RSCore/RSCore/NSData+RSCore.h new file mode 100755 index 000000000..d9b9e1e52 --- /dev/null +++ b/Frameworks/RSCore/RSCore/NSData+RSCore.h @@ -0,0 +1,37 @@ +// +// NSData+RSCore.h +// RSCore +// +// Created by Brent Simmons on 3/25/15. +// Copyright (c) 2015 Ranchero Software, LLC. All rights reserved. +// + +@import Foundation; + + +BOOL RSEqualBytes(const void *bytes1, const void *bytes2, size_t length); + +NSString *RSHexadecimalStringWithBytes(const unsigned char *bytes, NSUInteger numberOfBytes); + + +@interface NSData (RSCore) + +- (NSData *)rs_md5Hash; +- (NSString *)rs_md5HashString; + +- (BOOL)rs_dataIsPNG; +- (BOOL)rs_dataIsGIF; +- (BOOL)rs_dataIsJPEG; +- (BOOL)rs_dataIsImage; + +- (BOOL)rs_dataIsProbablyHTML; + +- (BOOL)rs_dataBeginsWithBytes:(const void *)bytes length:(size_t)numberOfBytes; + +- (NSString *)rs_noCopyString; //This data object must out-live returned string. May return nil. + +/*If bytes are deadbeef, then string is @"deadbeef". Returns nil for empty data.*/ + +- (NSString *)rs_hexadecimalString; + +@end diff --git a/Frameworks/RSCore/RSCore/NSData+RSCore.m b/Frameworks/RSCore/RSCore/NSData+RSCore.m new file mode 100755 index 000000000..fc96c5b1e --- /dev/null +++ b/Frameworks/RSCore/RSCore/NSData+RSCore.m @@ -0,0 +1,153 @@ +// +// NSData+RSCore.m +// RSCore +// +// Created by Brent Simmons on 3/25/15. +// Copyright (c) 2015 Ranchero Software, LLC. All rights reserved. +// + +#import +#import "NSData+RSCore.h" + + +@implementation NSData (RSCore) + + +- (NSData *)rs_md5Hash { + + unsigned char hash[CC_MD5_DIGEST_LENGTH]; + CC_MD5([self bytes], (CC_LONG)[self length], hash); + + return [NSData dataWithBytes:(const void *)hash length:CC_MD5_DIGEST_LENGTH]; +} + +- (NSString *)rs_md5HashString { + + NSData *d = [self rs_md5Hash]; + return [d rs_hexadecimalString]; +} + +BOOL RSEqualBytes(const void *bytes1, const void *bytes2, size_t length) { + + return memcmp(bytes1, bytes2, length) == 0; +} + + +- (BOOL)rs_dataBeginsWithBytes:(const void *)bytes length:(size_t)numberOfBytes { + + if ([self length] < numberOfBytes) { + return NO; + } + + return RSEqualBytes([self bytes], bytes, numberOfBytes); +} + + +- (BOOL)rs_dataIsPNG { + + /* http://www.w3.org/TR/PNG/#5PNG-file-signature : "The first eight bytes of a PNG datastream always contain the following (decimal) values: 137 80 78 71 13 10 26 10" */ + + static const Byte pngHeader[] = {137, 'P', 'N', 'G', 13, 10, 26, 10}; + return [self rs_dataBeginsWithBytes:pngHeader length:sizeof(pngHeader)]; +} + + +- (BOOL)rs_dataIsGIF { + + /* http://www.onicos.com/staff/iz/formats/gif.html */ + + static const Byte gifHeader1[] = {'G', 'I', 'F', '8', '7', 'a'}; + if ([self rs_dataBeginsWithBytes:gifHeader1 length:sizeof(gifHeader1)]) { + return YES; + } + + static const Byte gifHeader2[] = {'G', 'I', 'F', '8', '9', 'a'}; + return [self rs_dataBeginsWithBytes:gifHeader2 length:sizeof(gifHeader2)]; +} + + +- (BOOL)rs_dataIsJPEG { + + const void *bytes = [self bytes]; + + static const Byte jpegHeader1[] = {'J', 'F', 'I', 'F'}; + + if (RSEqualBytes(bytes + 6, jpegHeader1, sizeof(jpegHeader1))) { + return YES; + } + + static const Byte jpegHeader2[] = {'E', 'x', 'i', 'f'}; + return RSEqualBytes(bytes + 6, jpegHeader2, sizeof(jpegHeader2)); +} + + +- (BOOL)rs_dataIsImage { + + return [self rs_dataIsPNG] || [self rs_dataIsJPEG] || [self rs_dataIsGIF]; +} + + +- (BOOL)rs_dataIsProbablyHTML { + + NSString *s = [self rs_noCopyString]; + if (!s) { + return NO; + } + + if (![s containsString:@">"] || ![s containsString:@">"]) { + return NO; + } + + for (NSString *oneString in @[@"html", @"body"]) { + NSRange range = [s rangeOfString:oneString options:NSCaseInsensitiveSearch]; + if (range.location == NSNotFound) { + return NO; + } + } + + return YES; +} + + +- (NSString *)rs_noCopyString { + + NSDictionary *options = @{NSStringEncodingDetectionSuggestedEncodingsKey : @[@(NSUTF8StringEncoding)]}; + BOOL usedLossyConversion = NO; + NSStringEncoding encoding = [NSString stringEncodingForData:self encodingOptions:options convertedString:nil usedLossyConversion:&usedLossyConversion]; + if (encoding == 0) { + return nil; + } + + return [[NSString alloc] initWithBytesNoCopy:(void *)self.bytes length:self.length encoding:encoding freeWhenDone:NO]; +} + + +NSString *RSHexadecimalStringWithBytes(const Byte *bytes, NSUInteger numberOfBytes) { + + if (numberOfBytes < 1) { + return nil; + } + + if (numberOfBytes == 16) { + // Common case — MD5 hash, for example. + return [NSString stringWithFormat:@"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7], bytes[8], bytes[9], bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], bytes[15]]; + } + + NSMutableString *s = [[NSMutableString alloc] initWithString:@""]; + NSUInteger i = 0; + + for (i = 0; i < numberOfBytes; i++) { + [s appendString:[NSString stringWithFormat:@"%02x", bytes[i]]]; + } + + return [s copy]; +} + + +- (NSString *)rs_hexadecimalString { + + return RSHexadecimalStringWithBytes([self bytes], [self length]); +} + + +@end diff --git a/Frameworks/RSCore/RSCore/NSDate+RSCore.h b/Frameworks/RSCore/RSCore/NSDate+RSCore.h new file mode 100755 index 000000000..77ad6788b --- /dev/null +++ b/Frameworks/RSCore/RSCore/NSDate+RSCore.h @@ -0,0 +1,24 @@ +// +// NSDate+RSCore.h +// RSCore +// +// Created by Brent Simmons on 3/25/15. +// Copyright (c) 2015 Ranchero Software, LLC. All rights reserved. +// + +@import Foundation; + +@interface NSDate (RSCore) + + +- (NSString *)rs_unixTimestampStringWithNoDecimal; + +- (NSString *)rs_iso8601DateString; + + +/*Not intended for calendar-perfect use.*/ + ++ (NSDate *)rs_dateWithNumberOfDaysInThePast:(NSUInteger)numberOfDays; + + +@end diff --git a/Frameworks/RSCore/RSCore/NSDate+RSCore.m b/Frameworks/RSCore/RSCore/NSDate+RSCore.m new file mode 100755 index 000000000..fef487e1d --- /dev/null +++ b/Frameworks/RSCore/RSCore/NSDate+RSCore.m @@ -0,0 +1,49 @@ +// +// NSDate+RSCore.m +// RSCore +// +// Created by Brent Simmons on 3/25/15. +// Copyright (c) 2015 Ranchero Software, LLC. All rights reserved. +// + +#import "NSDate+RSCore.h" + +@implementation NSDate (RSCore) + + +- (NSString *)rs_unixTimestampStringWithNoDecimal { + return [NSString stringWithFormat:@"%.0f", [self timeIntervalSince1970]]; /*%.0f means no decimal*/ +} + + +- (NSString *)rs_iso8601DateString { + + /*NSDateFormatters are not thread-safe.*/ + + static NSDateFormatter *dateFormatter = nil; + static NSLock *lock = nil; + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + lock = [[NSLock alloc] init]; + dateFormatter = [NSDateFormatter new]; + NSLocale *enUSPOSIXLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]; + [dateFormatter setLocale:enUSPOSIXLocale]; + [dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ"]; + }); + + [lock lock]; + NSString *dateString = [dateFormatter stringFromDate:self]; + [lock unlock]; + + return dateString; +} + + ++ (NSDate *)rs_dateWithNumberOfDaysInThePast:(NSUInteger)numberOfDays { + + NSTimeInterval timeInterval = 60 * 60 * 24 * numberOfDays; + return [NSDate dateWithTimeIntervalSinceNow:-timeInterval]; +} + +@end diff --git a/Frameworks/RSCore/RSCore/NSDictionary+RSCore.h b/Frameworks/RSCore/RSCore/NSDictionary+RSCore.h new file mode 100755 index 000000000..0ef25c253 --- /dev/null +++ b/Frameworks/RSCore/RSCore/NSDictionary+RSCore.h @@ -0,0 +1,21 @@ +// +// NSDictionary+RSCore.h +// RSCore +// +// Created by Brent Simmons on 3/25/15. +// Copyright (c) 2015 Ranchero Software, LLC. All rights reserved. +// + +@import Foundation; + +@interface NSDictionary (RSCore) + +/*Keys that aren't strings are ignored. No coercion.*/ + +- (id)rs_objectForCaseInsensitiveKey:(NSString *)key; + +- (BOOL)rs_boolForKey:(NSString *)key; /*NO if doesn't exist.*/ + +- (int64_t)rs_int64ForKey:(NSString *)key; /*0 if doesn't exist.*/ + +@end diff --git a/Frameworks/RSCore/RSCore/NSDictionary+RSCore.m b/Frameworks/RSCore/RSCore/NSDictionary+RSCore.m new file mode 100755 index 000000000..2119ecf08 --- /dev/null +++ b/Frameworks/RSCore/RSCore/NSDictionary+RSCore.m @@ -0,0 +1,59 @@ +// +// NSDictionary+RSCore.m +// RSCore +// +// Created by Brent Simmons on 3/25/15. +// Copyright (c) 2015 Ranchero Software, LLC. All rights reserved. +// + +#import "NSDictionary+RSCore.h" + +@implementation NSDictionary (RSCore) + + +- (id)rs_objectForCaseInsensitiveKey:(NSString *)key { + + id obj = self[key]; + if (obj) { + return obj; + } + + for (NSString *oneKey in self.allKeys) { + + if ([oneKey isKindOfClass:[NSString class]] && [key caseInsensitiveCompare:oneKey] == NSOrderedSame) { + return self[oneKey]; + } + } + + return nil; +} + + +- (BOOL)rs_boolForKey:(NSString *)key { + + id obj = self[key]; + + if ([obj respondsToSelector:@selector(boolValue)]) { + return [obj boolValue]; + } + + return NO; +} + + +- (int64_t)rs_int64ForKey:(NSString *)key { + + id obj = self[key]; + if (!obj) { + return 0LL; + } + + if ([obj respondsToSelector:@selector(longLongValue)]) { + return ((NSNumber *)(obj)).longLongValue; + } + + return 0LL; +} + + +@end diff --git a/Frameworks/RSCore/RSCore/NSEvent+RSCore.h b/Frameworks/RSCore/RSCore/NSEvent+RSCore.h new file mode 100755 index 000000000..ca2d518a1 --- /dev/null +++ b/Frameworks/RSCore/RSCore/NSEvent+RSCore.h @@ -0,0 +1,25 @@ +// +// NSEvent+RSCore.h +// RSCore +// +// Created by Brent Simmons on 11/14/15. +// Copyright © 2015 Ranchero Software, LLC. All rights reserved. +// + +@import AppKit; + +NS_ASSUME_NONNULL_BEGIN + +@interface NSEvent (RSCore) + +- (void)rs_getCommandKeyDown:(BOOL *)commandKeyDown optionKeyDown:(BOOL *)optionKeyDown controlKeyDown:(BOOL *)controlKeyDown shiftKeyDown:(BOOL *)shiftKeyDown; + +- (BOOL)rs_keyIsModified; + +- (unichar)rs_unmodifiedCharacter; //The one and only key pressed, if just one. NSNotFound otherwise. + +- (nullable NSString *)rs_unmodifiedCharacterString; // The one and only key, if just one. + +@end + +NS_ASSUME_NONNULL_END diff --git a/Frameworks/RSCore/RSCore/NSEvent+RSCore.m b/Frameworks/RSCore/RSCore/NSEvent+RSCore.m new file mode 100755 index 000000000..371013282 --- /dev/null +++ b/Frameworks/RSCore/RSCore/NSEvent+RSCore.m @@ -0,0 +1,61 @@ +// +// NSEvent+RSCore.m +// RSCore +// +// Created by Brent Simmons on 11/14/15. +// Copyright © 2015 Ranchero Software, LLC. All rights reserved. +// + +#import "NSEvent+RSCore.h" +#import "NSString+RSCore.h" + + +@implementation NSEvent (RSCore) + + +- (void)rs_getCommandKeyDown:(BOOL *)commandKeyDown optionKeyDown:(BOOL *)optionKeyDown controlKeyDown:(BOOL *)controlKeyDown shiftKeyDown:(BOOL *)shiftKeyDown { + + NSEventModifierFlags flags = self.modifierFlags; + + *shiftKeyDown = ((flags & NSShiftKeyMask) != 0); + *optionKeyDown = ((flags & NSAlternateKeyMask) != 0); + *commandKeyDown = ((flags & NSCommandKeyMask) != 0); + *controlKeyDown = ((flags & NSControlKeyMask) != 0); +} + + +- (BOOL)rs_keyIsModified { + + BOOL commandKeyDown = NO; + BOOL optionKeyDown = NO; + BOOL controlKeyDown = NO; + BOOL shiftKeyDown = NO; + + [self rs_getCommandKeyDown:&commandKeyDown optionKeyDown:&optionKeyDown controlKeyDown:&controlKeyDown shiftKeyDown:&shiftKeyDown]; + + return commandKeyDown || optionKeyDown || controlKeyDown || shiftKeyDown; +} + + +- (unichar)rs_unmodifiedCharacter { + + NSString *s = self.charactersIgnoringModifiers; + if (RSStringIsEmpty(s) || s.length > 1) { + return (unichar)NSNotFound; + } + + return [s characterAtIndex:0]; +} + + +- (NSString *)rs_unmodifiedCharacterString { + + NSString *s = self.charactersIgnoringModifiers; + if (RSStringIsEmpty(s) || s.length > 1) { + return nil; + } + + return s; +} + +@end diff --git a/Frameworks/RSCore/RSCore/NSFileManager+RSCore.h b/Frameworks/RSCore/RSCore/NSFileManager+RSCore.h new file mode 100755 index 000000000..38b070348 --- /dev/null +++ b/Frameworks/RSCore/RSCore/NSFileManager+RSCore.h @@ -0,0 +1,24 @@ +// +// NSFileManager+RSCore.h +// RSCore +// +// Created by Brent Simmons on 9/27/15. +// Copyright © 2015 Ranchero Software, LLC. All rights reserved. +// + +@import Foundation; + +NS_ASSUME_NONNULL_BEGIN + +@interface NSFileManager (RSCore) + +- (BOOL)rs_copyFilesInFolder:(NSString *)source destination:(NSString *)destination error:(NSError * _Nullable * _Nullable)error; + +- (NSArray *)rs_filenamesInFolder:(NSString *)folder; +- (NSArray *)rs_filepathsInFolder:(NSString *)folder; + +- (BOOL)rs_fileIsFolder:(NSString *)f; // Returns NO if file doesn't exist. + +@end + +NS_ASSUME_NONNULL_END diff --git a/Frameworks/RSCore/RSCore/NSFileManager+RSCore.m b/Frameworks/RSCore/RSCore/NSFileManager+RSCore.m new file mode 100755 index 000000000..9db3cb606 --- /dev/null +++ b/Frameworks/RSCore/RSCore/NSFileManager+RSCore.m @@ -0,0 +1,134 @@ +// +// NSFileManager+RSCore.m +// RSCore +// +// Created by Brent Simmons on 9/27/15. +// Copyright © 2015 Ranchero Software, LLC. All rights reserved. +// + +#import "NSFileManager+RSCore.h" + + +static BOOL fileExists(NSString *f) { + + NSCParameterAssert(f); + return f && [[NSFileManager defaultManager] fileExistsAtPath:f]; +} + +static BOOL fileIsFolder(NSString *f) { + + NSCParameterAssert(f); + BOOL isFolder = NO; + if (![[NSFileManager defaultManager] fileExistsAtPath:f isDirectory:&isFolder]) { + return NO; + } + return isFolder; +} + +static BOOL deleteFile(NSString *f, NSError **error) { + + NSCParameterAssert(f); + NSCAssert(fileExists, f); + + if (!f || !fileExists(f)) { + return NO; + } + + return [[NSFileManager defaultManager] removeItemAtPath:f error:error]; +} + +static BOOL copyFile(NSString *source, NSString *dest, BOOL overwriteIfNecessary, NSError **error) { + + NSCParameterAssert(source); + NSCParameterAssert(dest); + NSCAssert(fileExists(source), nil); + + if (!dest || !source || !fileExists(source)) { + return NO; + } + + if (fileExists(dest)) { + if (overwriteIfNecessary) { + deleteFile(dest, error); + } + else { + return NO; + } + } + + return [[NSFileManager defaultManager] copyItemAtPath:source toPath:dest error:error]; +} + +@implementation NSFileManager (RSCore) + + +- (BOOL)rs_copyFilesInFolder:(NSString *)source destination:(NSString *)destination error:(NSError **)error { + + NSAssert(fileIsFolder(source), nil); + NSAssert(fileIsFolder(destination), nil); + + if (!fileIsFolder(source) || !fileIsFolder(destination)) { + return NO; + } + + NSArray *filenames = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:source error:error]; + if (!filenames) { + return NO; + } + + for (NSString *oneFilename in filenames) { + + if ([oneFilename hasPrefix:@"."]) { + continue; + } + + NSString *sourceFile = [source stringByAppendingPathComponent:oneFilename]; + NSString *destFile = [destination stringByAppendingPathComponent:oneFilename]; + + if (!copyFile(sourceFile, destFile, YES, error)) { + return NO; + } + } + + return YES; +} + + +- (NSArray *)rs_filenamesInFolder:(NSString *)folder { + + NSParameterAssert(folder); + NSAssert(fileIsFolder(folder), nil); + + if (!folder || !fileIsFolder(folder)) { + return @[]; + } + + return [[NSFileManager defaultManager] contentsOfDirectoryAtPath:folder error:nil]; +} + + +- (NSArray *)rs_filepathsInFolder:(NSString *)folder { + + NSArray *filenames = [self rs_filenamesInFolder:folder]; + if (!filenames) { + return @[]; + } + + NSMutableArray *filepaths = [NSMutableArray new]; + for (NSString *oneFilename in filenames) { + + NSString *onePath = [oneFilename stringByAppendingPathComponent:oneFilename]; + [filepaths addObject:onePath]; + } + + return filepaths; +} + + +- (BOOL)rs_fileIsFolder:(NSString *)f { + + return fileIsFolder(f); +} + +@end + diff --git a/Frameworks/RSCore/RSCore/NSImage+RSCore.h b/Frameworks/RSCore/RSCore/NSImage+RSCore.h new file mode 100755 index 000000000..ce4d7d2e1 --- /dev/null +++ b/Frameworks/RSCore/RSCore/NSImage+RSCore.h @@ -0,0 +1,23 @@ +// +// NSImage+RSCore.h +// RSCore +// +// Created by Brent Simmons on 3/25/15. +// Copyright (c) 2015 Ranchero Software, LLC. All rights reserved. +// + +@import Cocoa; +#import "RSBlocks.h" + + +@interface NSImage (RSCore) + + +/*Calls -initWithData in background queue. data and imageResultBlock must be non-nil.*/ + ++ (void)rs_imageWithData:(NSData *)data imageResultBlock:(RSImageResultBlock)imageResultBlock; + ++ (instancetype)imageWithContentsOfFile:(NSString *)f; + + +@end diff --git a/Frameworks/RSCore/RSCore/NSImage+RSCore.m b/Frameworks/RSCore/RSCore/NSImage+RSCore.m new file mode 100755 index 000000000..4ce495c98 --- /dev/null +++ b/Frameworks/RSCore/RSCore/NSImage+RSCore.m @@ -0,0 +1,31 @@ +// +// NSImage+RSCore.m +// RSCore +// +// Created by Brent Simmons on 3/25/15. +// Copyright (c) 2015 Ranchero Software, LLC. All rights reserved. +// + +#import "NSImage+RSCore.h" + + +@implementation NSImage (RSCore) + + ++ (void)rs_imageWithData:(NSData *)data imageResultBlock:(RSImageResultBlock)imageResultBlock { + + NSParameterAssert(data != nil); + + NSImage *image = [[NSImage alloc] initWithData:data]; + + RSCallBlockWithParameter(imageResultBlock, image); +} + + ++ (instancetype)imageWithContentsOfFile:(NSString *)f { + + return [[self alloc] initWithContentsOfFile:f]; +} + + +@end diff --git a/Frameworks/RSCore/RSCore/NSMutableArray+RSCore.h b/Frameworks/RSCore/RSCore/NSMutableArray+RSCore.h new file mode 100755 index 000000000..f84302249 --- /dev/null +++ b/Frameworks/RSCore/RSCore/NSMutableArray+RSCore.h @@ -0,0 +1,19 @@ +// +// NSMutableArray+RSCore.h +// RSCore +// +// Created by Brent Simmons on 3/25/15. +// Copyright (c) 2015 Ranchero Software, LLC. All rights reserved. +// + +@import Foundation; + +@interface NSMutableArray (RSCore) + + +/*Does nothing if obj == nil. No exception thrown.*/ + +- (void)rs_safeAddObject:(id)obj; + + +@end diff --git a/Frameworks/RSCore/RSCore/NSMutableArray+RSCore.m b/Frameworks/RSCore/RSCore/NSMutableArray+RSCore.m new file mode 100755 index 000000000..7000d4456 --- /dev/null +++ b/Frameworks/RSCore/RSCore/NSMutableArray+RSCore.m @@ -0,0 +1,22 @@ +// +// NSMutableArray+RSCore.m +// RSCore +// +// Created by Brent Simmons on 3/25/15. +// Copyright (c) 2015 Ranchero Software, LLC. All rights reserved. +// + +#import "NSMutableArray+RSCore.h" + + +@implementation NSMutableArray (RSCore) + + +- (void)rs_safeAddObject:(id)obj { + if (obj != nil) { + [self addObject:obj]; + } +} + + +@end diff --git a/Frameworks/RSCore/RSCore/NSMutableDictionary+RSCore.h b/Frameworks/RSCore/RSCore/NSMutableDictionary+RSCore.h new file mode 100755 index 000000000..5a5b6d37e --- /dev/null +++ b/Frameworks/RSCore/RSCore/NSMutableDictionary+RSCore.h @@ -0,0 +1,22 @@ +// +// NSMutableDictionary+RSCore.h +// RSCore +// +// Created by Brent Simmons on 3/25/15. +// Copyright (c) 2015 Ranchero Software, LLC. All rights reserved. +// + +@import Foundation; + + +@interface NSMutableDictionary (RSCore) + + +/*If obj or key are nil, does nothing. No exception thrown.*/ + +- (void)rs_safeSetObject:(id)obj forKey:(id)key; + +- (void)rs_removeObjectsForKeys:(NSArray *)keys; + + +@end diff --git a/Frameworks/RSCore/RSCore/NSMutableDictionary+RSCore.m b/Frameworks/RSCore/RSCore/NSMutableDictionary+RSCore.m new file mode 100755 index 000000000..481da2b0b --- /dev/null +++ b/Frameworks/RSCore/RSCore/NSMutableDictionary+RSCore.m @@ -0,0 +1,28 @@ +// +// NSMutableDictionary+RSCore.m +// RSCore +// +// Created by Brent Simmons on 3/25/15. +// Copyright (c) 2015 Ranchero Software, LLC. All rights reserved. +// + +#import "NSMutableDictionary+RSCore.h" + + +@implementation NSMutableDictionary (RSCore) + + +- (void)rs_safeSetObject:(id)obj forKey:(id)key { + if (obj != nil & key != nil) { + [self setObject:obj forKey:key]; + } +} + + +- (void)rs_removeObjectsForKeys:(NSArray *)keys { + + for (id oneKey in keys) { + [self removeObjectForKey:oneKey]; + } +} +@end diff --git a/Frameworks/RSCore/RSCore/NSMutableDictionary-Extensions.swift b/Frameworks/RSCore/RSCore/NSMutableDictionary-Extensions.swift new file mode 100755 index 000000000..397573d85 --- /dev/null +++ b/Frameworks/RSCore/RSCore/NSMutableDictionary-Extensions.swift @@ -0,0 +1,24 @@ +// +// NSMutableDictionary-Extensions.swift +// RSCore +// +// Created by Brent Simmons on 8/20/16. +// Copyright © 2016 Ranchero Software. All rights reserved. +// + +import Foundation + +public extension NSMutableDictionary { + + public func setOptionalStringValue(_ stringValue: String?, _ key: String) { + + if let s = stringValue { + setObjectWithStringKey(s as NSString, key) + } + } + + public func setObjectWithStringKey(_ obj: Any, _ key: String) { + + setObject(obj, forKey: key as NSString) + } +} diff --git a/Frameworks/RSCore/RSCore/NSMutableSet+RSCore.h b/Frameworks/RSCore/RSCore/NSMutableSet+RSCore.h new file mode 100755 index 000000000..a248ed5f0 --- /dev/null +++ b/Frameworks/RSCore/RSCore/NSMutableSet+RSCore.h @@ -0,0 +1,20 @@ +// +// NSMutableSet+RSCore.h +// RSCore +// +// Created by Brent Simmons on 3/25/15. +// Copyright (c) 2015 Ranchero Software, LLC. All rights reserved. +// + +@import Foundation; + + +@interface NSMutableSet (RSCore) + + +/*Does nothing if obj == nil. No exception thrown.*/ + +- (void)rs_safeAddObject:(id)obj; + + +@end diff --git a/Frameworks/RSCore/RSCore/NSMutableSet+RSCore.m b/Frameworks/RSCore/RSCore/NSMutableSet+RSCore.m new file mode 100755 index 000000000..328824a51 --- /dev/null +++ b/Frameworks/RSCore/RSCore/NSMutableSet+RSCore.m @@ -0,0 +1,22 @@ +// +// NSMutableSet+RSCore.m +// RSCore +// +// Created by Brent Simmons on 3/25/15. +// Copyright (c) 2015 Ranchero Software, LLC. All rights reserved. +// + +#import "NSMutableSet+RSCore.h" + + +@implementation NSMutableSet (RSCore) + + +- (void)rs_safeAddObject:(id)obj { + if (obj != nil) { + [self addObject:obj]; + } +} + + +@end diff --git a/Frameworks/RSCore/RSCore/NSNotificationCenter+RSCore.h b/Frameworks/RSCore/RSCore/NSNotificationCenter+RSCore.h new file mode 100755 index 000000000..d7115d66a --- /dev/null +++ b/Frameworks/RSCore/RSCore/NSNotificationCenter+RSCore.h @@ -0,0 +1,20 @@ +// +// NSNotificationCenter+RSCore.h +// RSCore +// +// Created by Brent Simmons on 3/25/15. +// Copyright (c) 2015 Ranchero Software, LLC. All rights reserved. +// + +@import Foundation; + + +@interface NSNotificationCenter (RSCore) + + +/*Posts immediately if already on the main thread.*/ + +- (void)rs_postNotificationNameOnMainThread:(NSString *)notificationName object:(id)obj userInfo:(NSDictionary *)userInfo; + + +@end diff --git a/Frameworks/RSCore/RSCore/NSNotificationCenter+RSCore.m b/Frameworks/RSCore/RSCore/NSNotificationCenter+RSCore.m new file mode 100755 index 000000000..f57482554 --- /dev/null +++ b/Frameworks/RSCore/RSCore/NSNotificationCenter+RSCore.m @@ -0,0 +1,31 @@ +// +// NSNotificationCenter+RSCore.m +// RSCore +// +// Created by Brent Simmons on 3/25/15. +// Copyright (c) 2015 Ranchero Software, LLC. All rights reserved. +// + +#import "NSNotificationCenter+RSCore.h" + + +@implementation NSNotificationCenter (RSCore) + + +- (void)rs_postNotificationNameOnMainThread:(NSString *)notificationName object:(id)obj userInfo:(NSDictionary *)userInfo { + + if (![NSThread isMainThread]) { + + dispatch_async(dispatch_get_main_queue(), ^{ + + [self postNotificationName:notificationName object:obj userInfo:userInfo]; + }); + } + + else { + [self postNotificationName:notificationName object:obj userInfo:userInfo]; + } +} + + +@end diff --git a/Frameworks/RSCore/RSCore/NSObject+RSCore.h b/Frameworks/RSCore/RSCore/NSObject+RSCore.h new file mode 100755 index 000000000..5b9ed4829 --- /dev/null +++ b/Frameworks/RSCore/RSCore/NSObject+RSCore.h @@ -0,0 +1,35 @@ +// +// NSObject+RSCore.h +// RSCore +// +// Created by Brent Simmons on 3/25/15. +// Copyright (c) 2015 Ranchero Software, LLC. All rights reserved. +// + +@import Foundation; + + +BOOL RSIsNil(id __nullable obj); // YES if nil or NSNull. + +BOOL RSIsEmpty(id __nullable obj); /*YES if nil or NSNull -- or length or count < 1*/ + +BOOL RSEqualValues(id __nullable obj1, id __nullable obj2); // YES if both are nil or NSNull or isEqual: returns YES. + +NS_ASSUME_NONNULL_BEGIN + +@interface NSObject (RSCore) + +/*Cancels any previous and does a new -performSelector:withObject:afterDelay:. Experimental.*/ + +- (void)rs_performSelectorCoalesced:(SEL)selector withObject:(id _Nullable)obj afterDelay:(NSTimeInterval)delay; + + +- (void)rs_takeValuesFromObject:(id)object propertyNames:(NSArray *)propertyNames; + +- (NSDictionary *)rs_mergeValuesWithObjectReturningChanges:(id)object propertyNames:(NSArray *)propertyNames; + +- (NSDictionary *)rs_dictionaryOfNonNilValues:(NSArray *)propertyNames; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Frameworks/RSCore/RSCore/NSObject+RSCore.m b/Frameworks/RSCore/RSCore/NSObject+RSCore.m new file mode 100755 index 000000000..13156448c --- /dev/null +++ b/Frameworks/RSCore/RSCore/NSObject+RSCore.m @@ -0,0 +1,114 @@ +// +// NSObject+RSCore.m +// RSCore +// +// Created by Brent Simmons on 3/25/15. +// Copyright (c) 2015 Ranchero Software, LLC. All rights reserved. +// + +#import "NSObject+RSCore.h" + + +BOOL RSIsNil(id obj) { + + return obj == nil || obj == [NSNull null]; +} + +BOOL RSIsEmpty(id obj) { + + if (RSIsNil(obj)) { + return YES; + } + + if ([obj respondsToSelector:@selector(count)]) { + return [obj count] < 1; + } + + if ([obj respondsToSelector:@selector(length)]) { + return [obj length] < 1; + } + + return NO; /*Shouldn't get here very often.*/ +} + + +BOOL RSEqualValues(id obj1, id obj2) { + + BOOL obj1IsNil = RSIsNil(obj1); + BOOL obj2IsNil = RSIsNil(obj2); + + if (obj1IsNil && obj2IsNil) { + return YES; + } + if (obj1IsNil != obj2IsNil) { + return NO; + } + + return [obj1 isEqual:obj2]; +} + + +@implementation NSObject (RSCore) + +- (void)rs_performSelectorCoalesced:(SEL)selector withObject:(id)obj afterDelay:(NSTimeInterval)delay { + + [NSObject cancelPreviousPerformRequestsWithTarget:self selector:selector object:obj]; + [self performSelector:selector withObject:obj afterDelay:delay]; +} + + +- (void)rs_takeValuesFromObject:(id)object propertyNames:(NSArray *)propertyNames { + + for (NSString *onePropertyName in propertyNames) { + + id oneValue = [object valueForKey:onePropertyName]; + if (oneValue == (id)[NSNull null]) { + [self setValue:nil forKey:onePropertyName]; + } + else { + [self setValue:oneValue forKey:onePropertyName]; + } + } +} + + +- (NSDictionary *)rs_mergeValuesWithObjectReturningChanges:(id)object propertyNames:(NSArray *)propertyNames { + + NSMutableDictionary *changes = [NSMutableDictionary new]; + + for (NSString *onePropertyName in propertyNames) { + + id oneLocalValue = [self valueForKey:onePropertyName]; + id oneRemoteValue = [object valueForKey:onePropertyName]; + + if (RSEqualValues(oneLocalValue, oneRemoteValue)) { + continue; + } + + [self setValue:oneRemoteValue forKey:onePropertyName]; + changes[onePropertyName] = oneRemoteValue; + } + + return [changes copy]; +} + + +- (NSDictionary *)rs_dictionaryOfNonNilValues:(NSArray *)propertyNames { + + NSMutableDictionary *d = [NSMutableDictionary new]; + + for (NSString *onePropertyName in propertyNames) { + + id oneValue = [self valueForKey:onePropertyName]; + if (RSIsNil(oneValue)) { + continue; + } + + d[onePropertyName] = oneValue; + } + + return [d copy]; +} + +@end + diff --git a/Frameworks/RSCore/RSCore/NSOutlineView+Extensions.swift b/Frameworks/RSCore/RSCore/NSOutlineView+Extensions.swift new file mode 100755 index 000000000..de2e6e041 --- /dev/null +++ b/Frameworks/RSCore/RSCore/NSOutlineView+Extensions.swift @@ -0,0 +1,25 @@ +// +// NSOutlineView+Extensions.swift +// RSCore +// +// Created by Brent Simmons on 9/6/16. +// Copyright © 2016 Ranchero Software, LLC. All rights reserved. +// + +import Cocoa + +public extension NSOutlineView { + + var selectedItems: [AnyObject] { + get { + + if selectionIsEmpty { + return [AnyObject]() + } + + return selectedRowIndexes.flatMap { (oneIndex) -> AnyObject? in + return item(atRow: oneIndex) as AnyObject + } + } + } +} diff --git a/Frameworks/RSCore/RSCore/NSPasteboard+RSCore.h b/Frameworks/RSCore/RSCore/NSPasteboard+RSCore.h new file mode 100755 index 000000000..3d73838dc --- /dev/null +++ b/Frameworks/RSCore/RSCore/NSPasteboard+RSCore.h @@ -0,0 +1,23 @@ +// +// NSPasteboard+RSCore.h +// RSCore +// +// Created by Brent Simmons on 11/14/15. +// Copyright © 2015 Ranchero Software, LLC. All rights reserved. +// + +@import AppKit; + +NS_ASSUME_NONNULL_BEGIN + +@interface NSPasteboard (RSCore) + +/*Pulls something that looks like a URL from the pasteboard. May return nil. + The string won’t be normalized — for instance, it could return "apple.com". + And the string may not really be a URL.*/ + ++ (nullable NSString *)rs_urlStringFromPasteboard:(NSPasteboard *)pasteboard; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Frameworks/RSCore/RSCore/NSPasteboard+RSCore.m b/Frameworks/RSCore/RSCore/NSPasteboard+RSCore.m new file mode 100755 index 000000000..ccc71f591 --- /dev/null +++ b/Frameworks/RSCore/RSCore/NSPasteboard+RSCore.m @@ -0,0 +1,39 @@ +// +// NSPasteboard+RSCore.m +// RSCore +// +// Created by Brent Simmons on 11/14/15. +// Copyright © 2015 Ranchero Software, LLC. All rights reserved. +// + +#import "NSPasteboard+RSCore.h" +#import "NSString+RSCore.h" + + +@implementation NSPasteboard (RSCore) + ++ (nullable NSString *)rs_urlStringFromPasteboard:(NSPasteboard *)pasteboard { + + return [pasteboard rs_urlString]; +} + +- (nullable NSString *)rs_urlString { + + NSString *type = [self availableTypeFromArray:@[NSStringPboardType]]; + if (!type) { + return nil; + } + + NSString *s = [self stringForType:type]; + if (RSStringIsEmpty(s)) { + return nil; + } + + if ([s rs_stringMayBeURL]) { + return s; + } + + return nil; +} + +@end diff --git a/Frameworks/RSCore/RSCore/NSResponder-Extensions.swift b/Frameworks/RSCore/RSCore/NSResponder-Extensions.swift new file mode 100755 index 000000000..5a8516c00 --- /dev/null +++ b/Frameworks/RSCore/RSCore/NSResponder-Extensions.swift @@ -0,0 +1,30 @@ +// +// NSResponder-Extensions.swift +// RSCore +// +// Created by Brent Simmons on 10/10/16. +// Copyright © 2016 Ranchero Software, LLC. All rights reserved. +// + +import Cocoa + +public extension NSResponder { + + public func hasAncestor(_ ancestor: NSResponder) -> Bool { + + var nomad: NSResponder = self + while(true) { + if nomad === ancestor { + return true + } + if let _ = nomad.nextResponder { + nomad = nomad.nextResponder! + } + else { + break + } + } + + return false + } +} diff --git a/Frameworks/RSCore/RSCore/NSSet+RSCore.h b/Frameworks/RSCore/RSCore/NSSet+RSCore.h new file mode 100755 index 000000000..0b2dd0491 --- /dev/null +++ b/Frameworks/RSCore/RSCore/NSSet+RSCore.h @@ -0,0 +1,23 @@ +// +// NSSet+RSCore.h +// RSCore +// +// Created by Brent Simmons on 8/15/15. +// Copyright © 2015 Ranchero Software, LLC. All rights reserved. +// + +@import Foundation; +#import +#import + + +@interface NSSet (RSCore) + +- (id)rs_anyObjectPassingTest:(RSTestBlock)testBlock; + +- (NSSet *)rs_filter:(RSFilterBlock)filterBlock; + +- (NSSet *)rs_objectsConformingToProtocol:(Protocol *)p; + + +@end diff --git a/Frameworks/RSCore/RSCore/NSSet+RSCore.m b/Frameworks/RSCore/RSCore/NSSet+RSCore.m new file mode 100755 index 000000000..677471cdf --- /dev/null +++ b/Frameworks/RSCore/RSCore/NSSet+RSCore.m @@ -0,0 +1,48 @@ +// +// NSSet+RSCore.m +// RSCore +// +// Created by Brent Simmons on 8/15/15. +// Copyright © 2015 Ranchero Software, LLC. All rights reserved. +// + +#import "NSSet+RSCore.h" + +@implementation NSSet (RSCore) + +- (id)rs_anyObjectPassingTest:(RSTestBlock)testBlock { + + for (id oneObject in self) { + + if (testBlock(oneObject)) { + return oneObject; + } + } + + return nil; +} + + +- (NSSet *)rs_filter:(RSFilterBlock)filterBlock { + + NSMutableSet *filteredSet = [NSMutableSet new]; + + for (id oneObject in self) { + + if (filterBlock(oneObject)) { + [filteredSet addObject:oneObject]; + } + } + + return [filteredSet copy]; +} + + +- (NSSet *)rs_objectsConformingToProtocol:(Protocol *)p { + + return [self rs_filter:^BOOL(id obj) { + return [obj conformsToProtocol:p]; + }]; +} + +@end diff --git a/Frameworks/RSCore/RSCore/NSStoryboard+RSCore.h b/Frameworks/RSCore/RSCore/NSStoryboard+RSCore.h new file mode 100755 index 000000000..9bce9166c --- /dev/null +++ b/Frameworks/RSCore/RSCore/NSStoryboard+RSCore.h @@ -0,0 +1,15 @@ +// +// NSStoryboard+RSCore.h +// RSCore +// +// Created by Brent Simmons on 11/20/15. +// Copyright © 2015 Ranchero Software, LLC. All rights reserved. +// + +@import Cocoa; + +@interface NSStoryboard (RSCore) + ++ (id)rs_initialControllerWithStoryboardName:(NSString *)storyboardName; + +@end diff --git a/Frameworks/RSCore/RSCore/NSStoryboard+RSCore.m b/Frameworks/RSCore/RSCore/NSStoryboard+RSCore.m new file mode 100755 index 000000000..0325f1bfd --- /dev/null +++ b/Frameworks/RSCore/RSCore/NSStoryboard+RSCore.m @@ -0,0 +1,19 @@ +// +// NSStoryboard+RSCore.m +// RSCore +// +// Created by Brent Simmons on 11/20/15. +// Copyright © 2015 Ranchero Software, LLC. All rights reserved. +// + +#import "NSStoryboard+RSCore.h" + +@implementation NSStoryboard (RSCore) + ++ (id)rs_initialControllerWithStoryboardName:(NSString *)storyboardName { + + NSStoryboard *storyboard = [self storyboardWithName:storyboardName bundle:nil]; + return [storyboard instantiateInitialController]; +} + +@end diff --git a/Frameworks/RSCore/RSCore/NSString+RSCore.h b/Frameworks/RSCore/RSCore/NSString+RSCore.h new file mode 100755 index 000000000..90b031b01 --- /dev/null +++ b/Frameworks/RSCore/RSCore/NSString+RSCore.h @@ -0,0 +1,76 @@ +// +// NSString+RSCore.h +// RSCore +// +// Created by Brent Simmons on 3/25/15. +// Copyright (c) 2015 Ranchero Software, LLC. All rights reserved. +// + +@import Foundation; +@import CoreGraphics; + + +BOOL RSStringIsEmpty(NSString * _Nullable s); /*Yes if null, NSNull, or length < 1*/ + +BOOL RSEqualStrings(NSString * _Nullable s1, NSString * _Nullable s2); /*Equal if both are nil*/ + +NS_ASSUME_NONNULL_BEGIN + +NSString *RSStringReplaceAll(NSString *stringToSearch, NSString *searchFor, NSString *replaceWith); /*Literal search*/ + +@interface NSString (RSCore) + + +/*The hashed data is a UTF-8 encoded version of the string.*/ + +- (NSData *)rs_md5Hash; +- (NSString *)rs_md5HashString; + + +/*Trims whitespace from leading and trailing ends. Collapses internal whitespace to single @" " character. + Whitespace is space, tag, cr, and lf characters.*/ + +- (NSString *)rs_stringWithCollapsedWhitespace; + +- (NSString *)rs_stringByTrimmingWhitespace; + +- (BOOL)rs_stringMayBeURL; + +- (NSString *)rs_normalizedURLString; //Change feed: to http:, etc. + +/*0.0f to 1.0f for each.*/ + +typedef struct { + CGFloat red; + CGFloat green; + CGFloat blue; + CGFloat alpha; +} RSRGBAComponents; + +/*red, green, blue components default to 1.0 if not specified. + alpha defaults to 1.0 if not specified.*/ + +- (RSRGBAComponents)rs_rgbaComponents; + + +/*If string doesn't have the prefix or suffix, it returns self. If prefix or suffix is nil or empty, returns self. If self and prefix or suffix are equal, returns @"".*/ + +- (NSString *)rs_stringByStrippingPrefix:(NSString *)prefix caseSensitive:(BOOL)caseSensitive; +- (NSString *)rs_stringByStrippingSuffix:(NSString *)suffix caseSensitive:(BOOL)caseSensitive; + +- (NSString *)rs_stringByStrippingHTML:(NSUInteger)maxCharacters; + +/*Filename from path, file URL string, or external URL string.*/ + +- (NSString *)rs_filename; + +- (BOOL)rs_caseInsensitiveContains:(NSString *)s; + +- (NSString *)rs_stringByEscapingSpecialXMLCharacters; + ++ (NSString *)rs_stringWithNumberOfTabs:(NSInteger)numberOfTabs; +- (NSString *)rs_stringByPrependingNumberOfTabs:(NSInteger)numberOfTabs; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Frameworks/RSCore/RSCore/NSString+RSCore.m b/Frameworks/RSCore/RSCore/NSString+RSCore.m new file mode 100755 index 000000000..ae56b75fc --- /dev/null +++ b/Frameworks/RSCore/RSCore/NSString+RSCore.m @@ -0,0 +1,370 @@ +// +// NSString+RSCore.m +// RSCore +// +// Created by Brent Simmons on 3/25/15. +// Copyright (c) 2015 Ranchero Software, LLC. All rights reserved. +// + +#import "NSString+RSCore.h" +#import "NSData+RSCore.h" + + +BOOL RSStringIsEmpty(NSString *s) { + + if (s == nil || (id)s == [NSNull null]) { + return YES; + } + + return s.length < 1; +} + + +BOOL RSEqualStrings(NSString *s1, NSString *s2) { + + return (s1 == nil && s2 == nil) || [s1 isEqualToString:s2]; +} + + +NSString *RSStringReplaceAll(NSString *stringToSearch, NSString *searchFor, NSString *replaceWith) { + + if (RSStringIsEmpty(stringToSearch)) { + return stringToSearch; + } + if (searchFor == nil || replaceWith == nil) { + return stringToSearch; + } + + NSMutableString *s = [stringToSearch mutableCopy]; + [s replaceOccurrencesOfString:searchFor withString:replaceWith options:NSLiteralSearch range:NSMakeRange(0, [s length])]; + + return s; +} + + +@implementation NSString (RSCore) + + +- (NSData *)rs_md5Hash { + + NSData *data = [self dataUsingEncoding:NSUTF8StringEncoding]; + return [data rs_md5Hash]; +} + + +- (NSString *)rs_md5HashString { + + NSData *d = [self rs_md5Hash]; + return [d rs_hexadecimalString]; +} + + +- (NSString *)rs_stringWithCollapsedWhitespace { + + NSMutableString *dest = [self mutableCopy]; + + CFStringTrimWhitespace((__bridge CFMutableStringRef)dest); + + [dest replaceOccurrencesOfString:@"\t" withString:@" " options:NSLiteralSearch range:NSMakeRange(0, [dest length])]; + [dest replaceOccurrencesOfString:@"\r" withString:@" " options:NSLiteralSearch range:NSMakeRange(0, [dest length])]; + [dest replaceOccurrencesOfString:@"\n" withString:@" " options:NSLiteralSearch range:NSMakeRange(0, [dest length])]; + + while ([dest rangeOfString:@" " options:NSLiteralSearch].location != NSNotFound) { + [dest replaceOccurrencesOfString:@" " withString:@" " options:NSLiteralSearch range:NSMakeRange(0, [dest length])]; + } + + return dest; +} + + +- (NSString *)rs_stringByTrimmingWhitespace { + + return [self stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; +} + + +- (BOOL)rs_stringContainsAnyCharacterFromSet:(NSCharacterSet *)characterSet { + + NSRange range = [self rangeOfCharacterFromSet:characterSet]; + return range.length > 0; +} + +- (BOOL)rs_stringMayBeURL { + + NSString *s = [self rs_stringByTrimmingWhitespace]; + if (RSStringIsEmpty(s)) { + return NO; + } + + if (![s containsString:@"."]) { + return NO; + } + + if ([s rs_stringContainsAnyCharacterFromSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]) { + return NO; + } + if ([s rs_stringContainsAnyCharacterFromSet:[NSCharacterSet controlCharacterSet]]) { + return NO; + } + if ([s rs_stringContainsAnyCharacterFromSet:[NSCharacterSet illegalCharacterSet]]) { + return NO; + } + + return YES; +} + + +- (NSString *)rs_stringByReplacingPrefix:(NSString *)prefix withHTTPPrefix:(NSString *)httpPrefix { + + if ([self.lowercaseString hasPrefix:prefix]) { + + NSString *s = [self rs_stringByStrippingPrefix:prefix caseSensitive:NO]; + if (![s hasPrefix:@"//"]) { + s = [NSString stringWithFormat:@"//%@", s]; + } + s = [NSString stringWithFormat:@"%@%@", httpPrefix, s]; + + return s; + } + return self; +} + +- (NSString *)rs_normalizedURLString { + + NSString *s = [self rs_stringByTrimmingWhitespace]; + + static NSString *feedPrefix = @"feed:"; + static NSString *feedsPrefix = @"feeds:"; + static NSString *httpPrefix = @"http:"; + static NSString *httpsPrefix = @"https:"; + + s = [s rs_stringByReplacingPrefix:feedPrefix withHTTPPrefix:httpPrefix]; + s = [s rs_stringByReplacingPrefix:feedsPrefix withHTTPPrefix:httpsPrefix]; + + if (![s hasPrefix:@"http"]) { + s = [NSString stringWithFormat:@"http://%@", s]; + } + + return s; +} + + +- (RSRGBAComponents)rs_rgbaComponents { + + RSRGBAComponents components = {0.0f, 0.0f, 0.0f, 1.0f}; + + NSMutableString *s = [self mutableCopy]; + [s replaceOccurrencesOfString:@"#" withString:@"" options:NSLiteralSearch range:NSMakeRange(0, [s length])]; + CFStringTrimWhitespace((__bridge CFMutableStringRef)s); + + unsigned int red = 0, green = 0, blue = 0, alpha = 0; + + if ([s length] >= 2) { + if ([[NSScanner scannerWithString:[s substringWithRange:NSMakeRange(0, 2)]] scanHexInt:&red]) { + components.red = (CGFloat)red / 255.0f; + } + } + + if ([s length] >= 4) { + if ([[NSScanner scannerWithString:[s substringWithRange:NSMakeRange(2, 2)]] scanHexInt:&green]) { + components.green = (CGFloat)green / 255.0f; + } + } + + if ([s length] >= 6) { + if ([[NSScanner scannerWithString:[s substringWithRange:NSMakeRange(4, 2)]] scanHexInt:&blue]) { + components.blue = (CGFloat)blue / 255.0f; + } + } + + if ([s length] >= 8) { + if ([[NSScanner scannerWithString:[s substringWithRange:NSMakeRange(6, 2)]] scanHexInt:&alpha]) { + components.alpha = (CGFloat)alpha / 255.0f; + } + } + + return components; +} + + +- (NSString *)rs_stringByStrippingPrefix:(NSString *)prefix caseSensitive:(BOOL)caseSensitive { + + if (RSStringIsEmpty(prefix)) { + return self; + } + + if (!caseSensitive) { + if (![self.lowercaseString hasPrefix:prefix.lowercaseString]) + return self; + } + else if (![self hasPrefix:prefix]) { + return self; + } + + if ([self isEqualToString:prefix]) { + return @""; + } + if (!caseSensitive && [self caseInsensitiveCompare:prefix] == NSOrderedSame) { + return @""; + } + + return [self substringFromIndex:[prefix length]]; +} + + +- (NSString *)rs_stringByStrippingSuffix:(NSString *)suffix caseSensitive:(BOOL)caseSensitive { + + if (RSStringIsEmpty(suffix)) { + return self; + } + if (!caseSensitive) { + if (![self.lowercaseString hasSuffix:suffix.lowercaseString]) { + return self; + } + } + else if (![self hasSuffix:suffix]) { + return self; + } + + if ([self isEqualToString:suffix]) { + return @""; + } + if (!caseSensitive && [self caseInsensitiveCompare:suffix] == NSOrderedSame) { + return @""; + } + + return [self substringToIndex:self.length - suffix.length]; +} + +- (NSString *)rs_stringByStrippingHTML:(NSUInteger)maxCharacters { + + if (![self containsString:@"<"]) { + + if (maxCharacters > 0 && [self length] > maxCharacters) { + return [self substringToIndex:maxCharacters]; + } + + return self; + } + + NSMutableString *preflightedCopy = [self mutableCopy]; + [preflightedCopy replaceOccurrencesOfString:@"
" withString:@" " options:NSCaseInsensitiveSearch range:NSMakeRange(0, preflightedCopy.length)]; + [preflightedCopy replaceOccurrencesOfString:@"
" withString:@" " options:NSCaseInsensitiveSearch range:NSMakeRange(0, preflightedCopy.length)]; + [preflightedCopy replaceOccurrencesOfString:@"

" withString:@" " options:NSCaseInsensitiveSearch range:NSMakeRange(0, preflightedCopy.length)]; + [preflightedCopy replaceOccurrencesOfString:@"

" withString:@" " options:NSCaseInsensitiveSearch range:NSMakeRange(0, preflightedCopy.length)]; + [preflightedCopy replaceOccurrencesOfString:@"
" withString:@" " options:NSCaseInsensitiveSearch range:NSMakeRange(0, preflightedCopy.length)]; + [preflightedCopy replaceOccurrencesOfString:@"
" withString:@" " options:NSCaseInsensitiveSearch range:NSMakeRange(0, preflightedCopy.length)]; + + CFMutableStringRef s = CFStringCreateMutable(kCFAllocatorDefault, (CFIndex)preflightedCopy.length); + NSUInteger i = 0; + NSUInteger level = 0; + BOOL lastCharacterWasSpace = NO; + unichar ch; + const unichar chspace = ' '; + NSUInteger charactersAdded = 0; + + for (i = 0; i < preflightedCopy.length; i++) { + + ch = [preflightedCopy characterAtIndex:i]; + + if (ch == '<') { + level++; + } + else if (ch == '>') { + level--; + } + else if (level == 0) { + + if (ch == ' ' || ch == '\r' || ch == '\t' || ch == '\n') { + if (lastCharacterWasSpace) { + continue; + } + else { + lastCharacterWasSpace = YES; + } + ch = chspace; + } + else { + lastCharacterWasSpace = NO; + } + + CFStringAppendCharacters(s, &ch, 1); + if (maxCharacters > 0) { + charactersAdded++; + if (charactersAdded >= maxCharacters) { + break; + } + } + } + } + + return (__bridge_transfer NSString *)s; +} + + +- (NSString *)rs_filename { + + NSArray *components = [self componentsSeparatedByString:@"/"]; + NSString *filename = components.lastObject; + if (RSStringIsEmpty(filename)) { + if (components.count > 1) { + filename = components[components.count - 2]; + } + } + + return filename; +} + + +- (BOOL)rs_caseInsensitiveContains:(NSString *)s { + + NSRange range = [self rangeOfString:s options:NSCaseInsensitiveSearch]; + return range.location != NSNotFound; +} + + +- (NSString *)rs_stringByEscapingSpecialXMLCharacters { + + NSMutableString *s = [self mutableCopy]; + + [s replaceOccurrencesOfString:@"\"" withString:@""" options:NSLiteralSearch range:NSMakeRange(0, self.length)]; + [s replaceOccurrencesOfString:@"<" withString:@"<" options:NSLiteralSearch range:NSMakeRange(0, s.length)]; + [s replaceOccurrencesOfString:@">" withString:@">" options:NSLiteralSearch range:NSMakeRange(0, s.length)]; + [s replaceOccurrencesOfString:@"&" withString:@"&" options:NSLiteralSearch range:NSMakeRange(0, s.length)]; + + return s; +} + + ++ (NSString *)rs_stringWithNumberOfTabs:(NSInteger)numberOfTabs { + + static dispatch_once_t onceToken; + static NSMutableDictionary *cache = nil; + + dispatch_once(&onceToken, ^{ + cache = [NSMutableDictionary new]; + }); + + NSString *cachedString = cache[@(numberOfTabs)]; + if (cachedString) { + return cachedString; + } + + NSMutableString *s = [@"" mutableCopy]; + for (NSInteger i = 0; i < numberOfTabs; i++) { + [s appendString:@"\t"]; + } + + cache[@(numberOfTabs)] = s; + return s; +} + +- (NSString *)rs_stringByPrependingNumberOfTabs:(NSInteger)numberOfTabs { + + NSString *tabs = [NSString rs_stringWithNumberOfTabs:numberOfTabs]; + return [tabs stringByAppendingString:self]; +} + + +@end + diff --git a/Frameworks/RSCore/RSCore/NSTableView+Extensions.swift b/Frameworks/RSCore/RSCore/NSTableView+Extensions.swift new file mode 100755 index 000000000..a32325699 --- /dev/null +++ b/Frameworks/RSCore/RSCore/NSTableView+Extensions.swift @@ -0,0 +1,18 @@ +// +// NSTableView+Extensions.swift +// RSCore +// +// Created by Brent Simmons on 9/6/16. +// Copyright © 2016 Ranchero Software, LLC. All rights reserved. +// + +import Cocoa + +public extension NSTableView { + + var selectionIsEmpty: Bool { + get { + return selectedRowIndexes.startIndex == selectedRowIndexes.endIndex + } + } +} diff --git a/Frameworks/RSCore/RSCore/NSTableView+RSCore.h b/Frameworks/RSCore/RSCore/NSTableView+RSCore.h new file mode 100755 index 000000000..81c9af1c6 --- /dev/null +++ b/Frameworks/RSCore/RSCore/NSTableView+RSCore.h @@ -0,0 +1,19 @@ +// +// NSTableView+RSCore.h +// RSCore +// +// Created by Brent Simmons on 3/29/15. +// Copyright (c) 2015 Ranchero Software, LLC. All rights reserved. +// + +@import Cocoa; + + +@interface NSTableView (RSCore) + + +- (void)rs_selectRow:(NSInteger)row; +- (void)rs_selectRowAndScrollToVisible:(NSInteger)row; + + +@end diff --git a/Frameworks/RSCore/RSCore/NSTableView+RSCore.m b/Frameworks/RSCore/RSCore/NSTableView+RSCore.m new file mode 100755 index 000000000..ac9bf63bc --- /dev/null +++ b/Frameworks/RSCore/RSCore/NSTableView+RSCore.m @@ -0,0 +1,26 @@ +// +// NSTableView+RSCore.m +// RSCore +// +// Created by Brent Simmons on 3/29/15. +// Copyright (c) 2015 Ranchero Software, LLC. All rights reserved. +// + +#import "NSTableView+RSCore.h" + +@implementation NSTableView (RSCore) + + +- (void)rs_selectRow:(NSInteger)row { + + [self selectRowIndexes:[NSIndexSet indexSetWithIndex:(NSUInteger)row] byExtendingSelection:NO]; +} + + +- (void)rs_selectRowAndScrollToVisible:(NSInteger)row { + + [self rs_selectRow:row]; + [self scrollRowToVisible:row]; +} + +@end diff --git a/Frameworks/RSCore/RSCore/NSTimer+RSCore.h b/Frameworks/RSCore/RSCore/NSTimer+RSCore.h new file mode 100755 index 000000000..90da91434 --- /dev/null +++ b/Frameworks/RSCore/RSCore/NSTimer+RSCore.h @@ -0,0 +1,18 @@ +// +// NSTimer+RSCore.h +// RSCore +// +// Created by Brent Simmons on 3/25/15. +// Copyright (c) 2015 Ranchero Software, LLC. All rights reserved. +// + +@import Foundation; + + +@interface NSTimer (RSCore) + + +- (void)rs_invalidateIfValid; + + +@end diff --git a/Frameworks/RSCore/RSCore/NSTimer+RSCore.m b/Frameworks/RSCore/RSCore/NSTimer+RSCore.m new file mode 100755 index 000000000..b3270de1b --- /dev/null +++ b/Frameworks/RSCore/RSCore/NSTimer+RSCore.m @@ -0,0 +1,23 @@ +// +// NSTimer+RSCore.m +// RSCore +// +// Created by Brent Simmons on 3/25/15. +// Copyright (c) 2015 Ranchero Software, LLC. All rights reserved. +// + +#import "NSTimer+RSCore.h" + + +@implementation NSTimer (RSCore) + + +- (void)rs_invalidateIfValid { + + if ([self isValid]) { + [self invalidate]; + } +} + + +@end diff --git a/Frameworks/RSCore/RSCore/NSView+RSCore.h b/Frameworks/RSCore/RSCore/NSView+RSCore.h new file mode 100755 index 000000000..953aedd77 --- /dev/null +++ b/Frameworks/RSCore/RSCore/NSView+RSCore.h @@ -0,0 +1,31 @@ +// +// NSView+RSCore.h +// RSCore +// +// Created by Brent Simmons on 3/25/15. +// Copyright (c) 2015 Ranchero Software, LLC. All rights reserved. +// + +@import Cocoa; + + +@interface NSView (RSCore) + + +/*Keeps subview at same size as receiver.*/ + +- (void)rs_addFullSizeConstraintsForSubview:(NSView *)view; + +- (void)rs_setFrameIfNotEqual:(NSRect)r; + +@property (nonatomic, readonly) BOOL rs_isOrIsDescendedFromFirstResponder; +@property (nonatomic, readonly) BOOL rs_shouldDrawAsActive; + +- (NSRect)rs_rectCenteredVertically:(NSRect)originalRect; + +- (NSRect)rs_rectCenteredHorizontally:(NSRect)originalRect; + +- (NSRect)rs_rectCentered:(NSRect)originalRect; + + +@end diff --git a/Frameworks/RSCore/RSCore/NSView+RSCore.m b/Frameworks/RSCore/RSCore/NSView+RSCore.m new file mode 100755 index 000000000..255502909 --- /dev/null +++ b/Frameworks/RSCore/RSCore/NSView+RSCore.m @@ -0,0 +1,68 @@ +// +// NSView+RSCore.m +// RSCore +// +// Created by Brent Simmons on 3/25/15. +// Copyright (c) 2015 Ranchero Software, LLC. All rights reserved. +// + +#import "NSView+RSCore.h" +#import "RSGeometry.h" + + +@implementation NSView (RSCore) + + +- (void)rs_addFullSizeConstraintsForSubview:(NSView *)view { + + NSDictionary *d = NSDictionaryOfVariableBindings(view); + + NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"|-0-[view]-0-|" options:0 metrics:nil views:d]; + [self addConstraints:constraints]; + constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[view]-0-|" options:0 metrics:nil views:d]; + [self addConstraints:constraints]; +} + + +- (void)rs_setFrameIfNotEqual:(NSRect)r { + + if (!NSEqualRects(self.frame, r)) { + self.frame = r; + } +} + + +- (BOOL)rs_isOrIsDescendedFromFirstResponder { + + NSView *firstResponder = (NSView *)(self.window.firstResponder); + if (![firstResponder isKindOfClass:[NSView class]]) { + return NO; + } + + return [self isDescendantOf:firstResponder]; +} + + +- (BOOL)rs_shouldDrawAsActive { + + return self.window.isMainWindow && self.rs_isOrIsDescendedFromFirstResponder; +} + + +- (NSRect)rs_rectCenteredVertically:(NSRect)originalRect { + + return RSRectCenteredVerticallyInRect(originalRect, self.bounds); +} + +- (NSRect)rs_rectCenteredHorizontally:(NSRect)originalRect { + + return RSRectCenteredHorizontallyInRect(originalRect, self.bounds); +} + +- (NSRect)rs_rectCentered:(NSRect)originalRect { + + return RSRectCenteredInRect(originalRect, self.bounds); +} + + +@end diff --git a/Frameworks/RSCore/RSCore/NSWindow-Extensions.swift b/Frameworks/RSCore/RSCore/NSWindow-Extensions.swift new file mode 100755 index 000000000..08a7d21e2 --- /dev/null +++ b/Frameworks/RSCore/RSCore/NSWindow-Extensions.swift @@ -0,0 +1,19 @@ +// +// NSWindow-Extensions.swift +// RSCore +// +// Created by Brent Simmons on 10/10/16. +// Copyright © 2016 Ranchero Software, LLC. All rights reserved. +// + +import Cocoa + +public extension NSWindow { + + public func makeFirstResponderUnlessDescendantIsFirstResponder(_ responder: NSResponder) { + + if !firstResponder.hasAncestor(responder) { + makeFirstResponder(responder) + } + } +} diff --git a/Frameworks/RSCore/RSCore/PlistProviderProtocol.swift b/Frameworks/RSCore/RSCore/PlistProviderProtocol.swift new file mode 100755 index 000000000..040ffca61 --- /dev/null +++ b/Frameworks/RSCore/RSCore/PlistProviderProtocol.swift @@ -0,0 +1,19 @@ +// +// PlistProviderProtocol.swift +// RSCore +// +// Created by Brent Simmons on 7/31/16. +// Copyright © 2016 Ranchero Software, LLC. All rights reserved. +// + +import Foundation + +// For objects that can be serialized as an array or dictionary. +// Mainly used for objects that can be stored on disk. +// Unlike NSCoder it provides human-readable archives. +// Does not do any checking on the contents, but they must be plist objects. + +public protocol PlistProvider: class { + + var plist: AnyObject? {get} +} diff --git a/Frameworks/RSCore/RSCore/RSBackgroundColorView.h b/Frameworks/RSCore/RSCore/RSBackgroundColorView.h new file mode 100755 index 000000000..bd1a4cc74 --- /dev/null +++ b/Frameworks/RSCore/RSCore/RSBackgroundColorView.h @@ -0,0 +1,19 @@ +// +// RSBackgroundColorView.h +// RSCore +// +// Created by Brent Simmons on 3/25/15. +// Copyright (c) 2015 Ranchero Software, LLC. All rights reserved. +// + +@import Cocoa; + + +IB_DESIGNABLE +@interface RSBackgroundColorView : NSView + + +@property (nonatomic) IBInspectable NSColor *backgroundColor; + + +@end diff --git a/Frameworks/RSCore/RSCore/RSBackgroundColorView.m b/Frameworks/RSCore/RSCore/RSBackgroundColorView.m new file mode 100755 index 000000000..4fa235b91 --- /dev/null +++ b/Frameworks/RSCore/RSCore/RSBackgroundColorView.m @@ -0,0 +1,67 @@ +// +// RSBackgroundColorView.m +// RSCore +// +// Created by Brent Simmons on 3/25/15. +// Copyright (c) 2015 Ranchero Software, LLC. All rights reserved. +// + +#import "RSBackgroundColorView.h" + + +@implementation RSBackgroundColorView + +- (BOOL)isOpaque { + + return YES; +} + + +//- (BOOL)preservesContentDuringLiveResize { +// +// return YES; +//} +// +// +//- (BOOL)wantsDefaultClipping { +// +// return NO; +//} +// +// +//- (void)setFrameSize:(NSSize)newSize { +// +// if (NSEqualSizes(newSize, self.frame.size)) { +// return; +// } +// [super setFrameSize:newSize]; +// +// if (self.inLiveResize) { +// NSRect rects[4]; +// NSInteger count = 0; +// [self getRectsExposedDuringLiveResize:rects count:&count]; +// while (count-- > 0) { +// [self setNeedsDisplayInRect:rects[count]]; +// } +// } else { +// self.needsDisplay = YES; +// } +//} + +- (void)drawRect:(NSRect)r { + +// const NSRect *rects; +// NSInteger count = 0; +// +// [self getRectsBeingDrawn:&rects count:&count]; +// if (count < 1) { +// return; +// } + + [self.backgroundColor setFill]; + NSRectFill(r); +// NSRectFillList(rects, count); +} + + +@end diff --git a/Frameworks/RSCore/RSCore/RSBinaryCache.h b/Frameworks/RSCore/RSCore/RSBinaryCache.h new file mode 100755 index 000000000..9d2e539a9 --- /dev/null +++ b/Frameworks/RSCore/RSCore/RSBinaryCache.h @@ -0,0 +1,41 @@ +// +// RSBinaryCache.h +// RSCore +// +// Created by Brent Simmons on 3/25/15. +// Copyright (c) 2015 Ranchero Software, LLC. All rights reserved. +// + +@import Foundation; + +/*The folder this manages must already exist. + Doesn't do any locking or queueing -- caller is responsible.*/ + + +@interface RSBinaryCache : NSObject + + +- (instancetype)initWithFolder:(NSString *)folder; + +- (NSString *)filePathForKey:(NSString *)key; + +- (BOOL)setBinaryData:(NSData *)data key:(NSString *)key error:(NSError **)error; + +- (NSData *)binaryDataForKey:(NSString *)key error:(NSError **)error; + +- (BOOL)removeBinaryDataForKey:(NSString *)key error:(NSError **)error; + +- (BOOL)binaryForKeyExists:(NSString *)key; + +- (UInt64)lengthOfBinaryDataForKey:(NSString *)key error:(NSError **)error; + +- (NSArray *)allKeys:(NSError **)error; + + +extern NSString *RSBinaryKey; +extern NSString *RSBinaryLength; + +- (NSArray *)allObjects:(NSError **)error; /*NSDictionary objects with RSBinaryKey and RSBinaryLength. Key is filename.*/ + + +@end diff --git a/Frameworks/RSCore/RSCore/RSBinaryCache.m b/Frameworks/RSCore/RSCore/RSBinaryCache.m new file mode 100755 index 000000000..6de4b3c71 --- /dev/null +++ b/Frameworks/RSCore/RSCore/RSBinaryCache.m @@ -0,0 +1,129 @@ +// +// RSBinaryCache.m +// RSCore +// +// Created by Brent Simmons on 3/25/15. +// Copyright (c) 2015 Ranchero Software, LLC. All rights reserved. +// + +#import "RSBinaryCache.h" + + +@interface RSBinaryCache () + +@property (nonatomic) NSString *folder; + +@end + + +@implementation RSBinaryCache + + +#pragma mark - Init + +- (instancetype)initWithFolder:(NSString *)folder { + + self = [super init]; + if (!self) { + return nil; + } + + _folder = folder; + + return self; +} + + +#pragma mark - API + +- (NSString *)filePathForKey:(NSString *)key { + + return [self.folder stringByAppendingPathComponent:key]; +} + + +- (BOOL)setBinaryData:(NSData *)data key:(NSString *)key error:(NSError **)error { + + NSString *f = [self filePathForKey:key]; + return [data writeToFile:f options:NSDataWritingAtomic error:error]; +} + + +- (NSData *)binaryDataForKey:(NSString *)key error:(NSError **)error { + + NSString *f = [self filePathForKey:key]; + return [NSData dataWithContentsOfFile:f options:0 error:error]; +} + + +- (BOOL)removeBinaryDataForKey:(NSString *)key error:(NSError **)error { + + NSString *f = [self filePathForKey:key]; + return [[NSFileManager defaultManager] removeItemAtPath:f error:error]; +} + + +- (BOOL)binaryForKeyExists:(NSString *)key { + + NSString *f = [self filePathForKey:key]; + BOOL isDirectory = NO; + return [[NSFileManager defaultManager] fileExistsAtPath:f isDirectory:&isDirectory]; +} + + +- (UInt64)lengthOfBinaryDataForKey:(NSString *)key error:(NSError **)error { + + NSString *f = [self filePathForKey:key]; + NSDictionary *fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:f error:error]; + return [fileAttributes fileSize]; +} + + +- (NSArray *)allKeys:(NSError **)error { + + NSMutableArray *keys = [NSMutableArray new]; + + NSArray *filenames = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:self.folder error:error]; + for (NSString *oneFilename in filenames) { + + if ([oneFilename hasPrefix:@"."]) { + continue; + } + [keys addObject:oneFilename]; + } + + return [keys copy]; +} + + +NSString *RSBinaryKey = @"key"; +NSString *RSBinaryLength = @"length"; + +- (NSArray *)allObjects:(NSError **)error { + + NSMutableArray *objects = [NSMutableArray new]; + + NSArray *filenames = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:self.folder error:error]; + if (!filenames && error) { + return nil; + } + + for (NSString *oneFilename in filenames) { + + if ([oneFilename hasPrefix:@"."]) { + continue; + } + + NSMutableDictionary *oneObject = [NSMutableDictionary new]; + oneObject[RSBinaryKey] = oneFilename; + + UInt64 length = [self lengthOfBinaryDataForKey:oneFilename error:nil]; + oneObject[RSBinaryLength] = @(length); + + [objects addObject:[oneObject copy]]; + } + + return [objects copy]; +} + +@end diff --git a/Frameworks/RSCore/RSCore/RSBlocks.h b/Frameworks/RSCore/RSCore/RSBlocks.h new file mode 100755 index 000000000..5db45f693 --- /dev/null +++ b/Frameworks/RSCore/RSCore/RSBlocks.h @@ -0,0 +1,46 @@ +// +// RSBlocks.h +// RSCore +// +// Created by Brent Simmons on 3/25/15. +// Copyright (c) 2015 Ranchero Software LLC. All rights reserved. +// + +@import Foundation; +#import + +#if TARGET_OS_IPHONE +@import UIKit; +#endif + +typedef void (^RSVoidBlock)(void); + +typedef RSVoidBlock RSVoidCompletionBlock; + +typedef BOOL (^RSBoolBlock)(void); + +typedef void (^RSFetchResultsBlock)(NSArray *fetchedObjects); + +typedef void (^RSDataResultBlock)(NSData *d); + +typedef void (^RSObjectResultBlock)(id obj); + +typedef void (^RSSetResultBlock)(NSSet *set); + +typedef void (^RSBoolResultBlock)(BOOL flag); + +typedef BOOL (^RSTestBlock)(id obj); + +/*Images*/ + +typedef void (^RSImageResultBlock)(RS_IMAGE *image); + +typedef RS_IMAGE *(^RSImageRenderBlock)(RS_IMAGE *imageToRender); + + +/*Calls on main thread. Ignores if nil.*/ + +void RSCallCompletionBlock(RSVoidCompletionBlock completion); + +void RSCallBlockWithParameter(RSObjectResultBlock block, id obj); + diff --git a/Frameworks/RSCore/RSCore/RSBlocks.m b/Frameworks/RSCore/RSCore/RSBlocks.m new file mode 100755 index 000000000..9dd492b8e --- /dev/null +++ b/Frameworks/RSCore/RSCore/RSBlocks.m @@ -0,0 +1,36 @@ +// +// RSBlocks.m +// RSCore +// +// Created by Brent Simmons on 3/25/15. +// Copyright (c) 2015 Ranchero Software LLC. All rights reserved. +// + +#import "RSBlocks.h" + +void RSCallCompletionBlock(RSVoidCompletionBlock completion) { + + if (!completion) { + return; + } + + dispatch_async(dispatch_get_main_queue(), ^{ + @autoreleasepool { + completion(); + } + }); +} + +void RSCallBlockWithParameter(RSObjectResultBlock block, id obj) { + + if (!block) { + return; + } + + dispatch_async(dispatch_get_main_queue(), ^{ + @autoreleasepool { + block(obj); + } + }); +} + diff --git a/Frameworks/RSCore/RSCore/RSConstants.h b/Frameworks/RSCore/RSCore/RSConstants.h new file mode 100755 index 000000000..ad7fb7e40 --- /dev/null +++ b/Frameworks/RSCore/RSCore/RSConstants.h @@ -0,0 +1,25 @@ +// +// RSConstants.h +// RSCore +// +// Created by Brent Simmons on 3/25/15. +// Copyright (c) 2015 Ranchero Software, LLC. All rights reserved. +// + +@import Foundation; + +typedef NS_ENUM(NSUInteger, RSPosition) { + RSPositionFirst, + RSPositionMiddle, + RSPositionLast, + RSPositionOnly +}; + + +extern NSString *RSUniqueIDKey; //@"uniqueID" +extern NSString *RSImageKey; //@"image" +extern NSString *RSChildrenKey; //@"children" +extern NSString *RSNameKey; //@"name" +extern NSString *RSTypeKey; //@"type" +extern NSString *RSFolderKey; //@"folder" +extern NSString *RSURLKey; //@"url" diff --git a/Frameworks/RSCore/RSCore/RSConstants.m b/Frameworks/RSCore/RSCore/RSConstants.m new file mode 100755 index 000000000..6e3ded2f0 --- /dev/null +++ b/Frameworks/RSCore/RSCore/RSConstants.m @@ -0,0 +1,17 @@ +// +// RSConstants.m +// RSCore +// +// Created by Brent Simmons on 3/25/15. +// Copyright (c) 2015 Ranchero Software, LLC. All rights reserved. +// + +#import "RSConstants.h" + +NSString *RSUniqueIDKey = @"uniqueID"; +NSString *RSImageKey = @"image"; +NSString *RSChildrenKey = @"children"; +NSString *RSNameKey = @"name"; +NSString *RSTypeKey = @"type"; +NSString *RSFolderKey = @"folder"; +NSString *RSURLKey = @"url"; diff --git a/Frameworks/RSCore/RSCore/RSCore.h b/Frameworks/RSCore/RSCore/RSCore.h new file mode 100755 index 000000000..36e5666db --- /dev/null +++ b/Frameworks/RSCore/RSCore/RSCore.h @@ -0,0 +1,68 @@ +// +// RSCore.h +// RSCore +// +// Created by Brent Simmons on 3/25/15. +// Copyright (c) 2015 Ranchero Software, LLC. All rights reserved. +// + +@import Foundation; + +#import +#import +#import +#import + + +/*Foundation*/ + +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import + +#import + + +#if !TARGET_OS_IPHONE + +/*AppKit*/ + +#import +#import +#import +#import +#import +#import + +#import +#import +#import + +#import + +#import + +#endif + + +/*Images*/ + +#import +#import + + +/*Text*/ + +#import + diff --git a/Frameworks/RSCore/RSCore/RSGeometry.h b/Frameworks/RSCore/RSCore/RSGeometry.h new file mode 100755 index 000000000..318336a90 --- /dev/null +++ b/Frameworks/RSCore/RSCore/RSGeometry.h @@ -0,0 +1,15 @@ +// +// RSGeometry.h +// RSCore +// +// Created by Brent Simmons on 3/13/16. +// Copyright © 2016 Ranchero Software, LLC. All rights reserved. +// + +@import Foundation; + +NSRect RSRectCenteredVerticallyInRect(NSRect originalRect, NSRect containerRect); + +NSRect RSRectCenteredHorizontallyInRect(NSRect originalRect, NSRect containerRect); + +NSRect RSRectCenteredInRect(NSRect originalRect, NSRect containerRect); diff --git a/Frameworks/RSCore/RSCore/RSGeometry.m b/Frameworks/RSCore/RSCore/RSGeometry.m new file mode 100755 index 000000000..642011e9c --- /dev/null +++ b/Frameworks/RSCore/RSCore/RSGeometry.m @@ -0,0 +1,36 @@ +// +// RSGeometry.m +// RSCore +// +// Created by Brent Simmons on 3/13/16. +// Copyright © 2016 Ranchero Software, LLC. All rights reserved. +// + +#import "RSGeometry.h" + + +NSRect RSRectCenteredVerticallyInRect(NSRect originalRect, NSRect containerRect) { + + NSRect r = originalRect; + r.origin.y = NSMidY(containerRect) - (NSHeight(r) / 2.0); + r = NSIntegralRect(r); + r.size = originalRect.size; + return r; +} + + +NSRect RSRectCenteredHorizontallyInRect(NSRect originalRect, NSRect containerRect) { + + NSRect r = originalRect; + r.origin.x = NSMidX(containerRect) - (NSWidth(r) / 2.0); + r = NSIntegralRect(r); + r.size = originalRect.size; + return r; +} + + +NSRect RSRectCenteredInRect(NSRect originalRect, NSRect containerRect) { + + NSRect r = RSRectCenteredVerticallyInRect(originalRect, containerRect); + return RSRectCenteredHorizontallyInRect(r, containerRect); +} diff --git a/Frameworks/RSCore/RSCore/RSImageRenderer.h b/Frameworks/RSCore/RSCore/RSImageRenderer.h new file mode 100755 index 000000000..e599b1059 --- /dev/null +++ b/Frameworks/RSCore/RSCore/RSImageRenderer.h @@ -0,0 +1,32 @@ +// +// RSImageRenderer.h +// RSCore +// +// Created by Brent Simmons on 3/25/15. +// Copyright (c) 2015 Ranchero Software, LLC. All rights reserved. +// + +@import Foundation; +#import "RSBlocks.h" + + +/*Used to render an image based on another image. (Thumbnails, for instance.) + Thread-safe. Renders in a background queue. + + imageRenderBlock is responsible for dealing with graphics context; it returns the rendered image. + + imageResultBlock may be called on any thread. + + None of the parameters may be nil. + */ + + +@interface RSImageRenderer : NSObject + + +- (instancetype)initWithRenderer:(RSImageRenderBlock)imageRenderBlock; + +- (void)renderImage:(RS_IMAGE *)originalImage imageResultBlock:(RSImageResultBlock)imageResultBlock; + + +@end diff --git a/Frameworks/RSCore/RSCore/RSImageRenderer.m b/Frameworks/RSCore/RSCore/RSImageRenderer.m new file mode 100755 index 000000000..63530c8e3 --- /dev/null +++ b/Frameworks/RSCore/RSCore/RSImageRenderer.m @@ -0,0 +1,69 @@ +// +// RSImageRenderer.m +// RSCore +// +// Created by Brent Simmons on 3/25/15. +// Copyright (c) 2015 Ranchero Software, LLC. All rights reserved. +// + +#import "RSImageRenderer.h" + +static void RSImageRender(RS_IMAGE *originalImage, RSImageRenderBlock renderer, RSImageResultBlock imageCallback) { + + assert(originalImage != nil); + assert(renderer != nil); + assert(imageCallback != nil); + + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{ + + @autoreleasepool { + + RS_IMAGE *renderedImage = renderer(originalImage); + imageCallback(renderedImage); + } + }); +} + + + +@interface RSImageRenderer () + +@property (nonatomic, copy) RSImageRenderBlock imageRenderBlock; + +@end + + + +@implementation RSImageRenderer + + +#pragma mark - Init + +- (instancetype)initWithRenderer:(RSImageRenderBlock)imageRenderBlock { + + NSParameterAssert(imageRenderBlock != nil); + + self = [super init]; + if (self == nil) { + return nil; + } + + _imageRenderBlock = imageRenderBlock; + + return self; +} + + +#pragma mark - API + +- (void)renderImage:(RS_IMAGE *)originalImage imageResultBlock:(RSImageResultBlock)imageResultBlock { + + NSParameterAssert(originalImage != nil); + NSParameterAssert(imageResultBlock != nil); + + RSImageRender(originalImage, self.imageRenderBlock, imageResultBlock); +} + + +@end + diff --git a/Frameworks/RSCore/RSCore/RSMacroProcessor.h b/Frameworks/RSCore/RSCore/RSMacroProcessor.h new file mode 100755 index 000000000..9df3bdf21 --- /dev/null +++ b/Frameworks/RSCore/RSCore/RSMacroProcessor.h @@ -0,0 +1,19 @@ +// +// RSMacroProcessor.h +// RSCore +// +// Created by Brent Simmons on 10/26/15. +// Copyright © 2015 Ranchero Software, LLC. All rights reserved. +// + +@import Foundation; + +NS_ASSUME_NONNULL_BEGIN + +@interface RSMacroProcessor : NSObject + ++ (NSString *)renderedTextWithTemplate:(NSString *)templateString substitutions:(NSDictionary *)substitutions macroStart:(NSString *)macroStart macroEnd:(NSString *)macroEnd; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Frameworks/RSCore/RSCore/RSMacroProcessor.m b/Frameworks/RSCore/RSCore/RSMacroProcessor.m new file mode 100755 index 000000000..508361d76 --- /dev/null +++ b/Frameworks/RSCore/RSCore/RSMacroProcessor.m @@ -0,0 +1,120 @@ +// +// RSMacroProcessor.m +// RSCore +// +// Created by Brent Simmons on 10/26/15. +// Copyright © 2015 Ranchero Software, LLC. All rights reserved. +// + +#import "RSMacroProcessor.h" + + +@interface RSMacroProcessor () + +@property (nonatomic, readonly) NSString *template; +@property (nonatomic, readonly) NSDictionary *substitutions; +@property (nonatomic, readonly) NSString *macroStart; +@property (nonatomic, readonly) NSString *macroEnd; +@property (nonatomic, readonly) NSUInteger numberOfMacroStartCharacters; +@property (nonatomic, readonly) NSUInteger numberOfMacroEndCharacters; +@property (nonatomic) NSString *renderedText; + +@end + + +@implementation RSMacroProcessor + +#pragma mark - Class Methods + ++ (NSString *)renderedTextWithTemplate:(NSString *)templateString substitutions:(NSDictionary *)substitutions macroStart:(NSString *)macroStart macroEnd:(NSString *)macroEnd { + + RSMacroProcessor *macroProcessor = [[self alloc] initWithTemplate:templateString substitutions:substitutions macroStart:macroStart macroEnd:macroEnd]; + return macroProcessor.renderedText; +} + + +#pragma mark - Init + +- (instancetype)initWithTemplate:(NSString *)templateString substitutions:(NSDictionary *)substitutions macroStart:(NSString *)macroStart macroEnd:(NSString *)macroEnd { + + self = [super init]; + if (!self) { + return nil; + } + + _template = templateString; + _substitutions = substitutions; + _macroStart = macroStart; + _macroEnd = macroEnd; + _numberOfMacroStartCharacters = _macroStart.length; + _numberOfMacroEndCharacters = _macroEnd.length; + + return self; +} + +#pragma mark - Accessors + +- (NSString *)renderedText { + + if (!_renderedText) { + _renderedText = [self processMacros]; + } + + return _renderedText; +} + + +#pragma mark - Private + +- (NSUInteger)indexOfString:(NSString *)s beforeIndex:(NSUInteger)ix inString:(NSString *)stringToSearch { + + if (ix < s.length) { + return NSNotFound; + } + + NSRange range = [stringToSearch rangeOfString:s options:NSBackwardsSearch range:NSMakeRange(0, ix)]; + if (range.length < s.length) { + return NSNotFound; + } + + return range.location; +} + + +- (NSString *)processMacros { + + NSMutableString *s = [self.template mutableCopy]; + + NSUInteger lastIndexOfMacroStart = s.length; + + while (true) { + + NSUInteger ixMacroEnd = [self indexOfString:self.macroEnd beforeIndex:lastIndexOfMacroStart inString:s]; + if (ixMacroEnd == NSNotFound) { + break; + } + + NSUInteger ixMacroStart = [self indexOfString:self.macroStart beforeIndex:ixMacroEnd inString:s]; + if (ixMacroStart == NSNotFound) { + break; + } + + NSRange range = NSMakeRange(ixMacroStart, (ixMacroEnd - ixMacroStart) + self.numberOfMacroEndCharacters); + + NSRange keyRange = range; + keyRange.location += self.numberOfMacroStartCharacters; + keyRange.length -= (self.numberOfMacroStartCharacters + self.numberOfMacroEndCharacters); + NSString *key = [s substringWithRange:keyRange]; + + NSString *substition = [self.substitutions objectForKey:key]; + if (substition) { + [s replaceCharactersInRange:range withString:substition]; + } + + lastIndexOfMacroStart = ixMacroStart; + } + + return [s copy]; +} + +@end diff --git a/Frameworks/RSCore/RSCore/RSOpaqueContainerView.h b/Frameworks/RSCore/RSCore/RSOpaqueContainerView.h new file mode 100755 index 000000000..eaaf51972 --- /dev/null +++ b/Frameworks/RSCore/RSCore/RSOpaqueContainerView.h @@ -0,0 +1,21 @@ +// +// RSOpaqueContainerView.h +// RSCore +// +// Created by Brent Simmons on 3/27/15. +// Copyright (c) 2015 Ranchero Software, LLC. All rights reserved. +// + +@import Cocoa; +#import + + +/*This view has one subview, which it resizes to fit the bounds of this view.*/ + +@interface RSOpaqueContainerView : RSBackgroundColorView + + +@property (nonatomic) NSView *containedView; /*Removes old.*/ + + +@end diff --git a/Frameworks/RSCore/RSCore/RSOpaqueContainerView.m b/Frameworks/RSCore/RSCore/RSOpaqueContainerView.m new file mode 100755 index 000000000..1cfd3e586 --- /dev/null +++ b/Frameworks/RSCore/RSCore/RSOpaqueContainerView.m @@ -0,0 +1,52 @@ +// +// RSOpaqueContainerView.m +// RSCore +// +// Created by Brent Simmons on 3/27/15. +// Copyright (c) 2015 Ranchero Software, LLC. All rights reserved. +// + +#import "RSOpaqueContainerView.h" +#import "NSView+RSCore.h" + + +@implementation RSOpaqueContainerView + + ++ (BOOL)requiresConstraintBasedLayout { + + return NO; +} + + +- (NSView *)containedView { + + return self.subviews.firstObject; +} + + +- (void)setContainedView:(NSView *)containedView { + + [self.subviews makeObjectsPerformSelector:@selector(removeFromSuperviewWithoutNeedingDisplay)]; + [self addSubview:containedView]; + self.needsLayout = YES; + self.needsDisplay = YES; +} + + +- (void)layout { + + [self resizeSubviewsWithOldSize:NSZeroSize]; +} + + +- (void)resizeSubviewsWithOldSize:(NSSize)oldSize { + +#pragma unused(oldSize) + + NSView *subview = self.subviews.firstObject; + [subview rs_setFrameIfNotEqual:self.bounds]; +} + + +@end diff --git a/Frameworks/RSCore/RSCore/RSPlatform.h b/Frameworks/RSCore/RSCore/RSPlatform.h new file mode 100755 index 000000000..b12c5c226 --- /dev/null +++ b/Frameworks/RSCore/RSCore/RSPlatform.h @@ -0,0 +1,48 @@ +// +// RSPlatform.h +// RSCore +// +// Created by Brent Simmons on 3/25/15. +// Copyright (c) 2015 Ranchero Software, LLC. All rights reserved. +// + +@import Foundation; + +/*Mac: ~/Application Support/AppName/ + + If nil, gets appName from Info.plist -- @"CFBundleExecutable" key. + It creates the folder and intermediate folders if necessary. + + If something goes wrong it returns nil. The error is NSLogged. + Panic, at that point, is strongly indicated.*/ + +NS_ASSUME_NONNULL_BEGIN + +NSString * _Nullable RSDataFolder(NSString * _Nullable appName); + +/*Path to file in folder specified by RSDataFolder. + appName may be nil -- it's passed to RSDataFolder.*/ + +NSString * _Nullable RSDataFile(NSString * _Nullable appName, NSString *fileName); + +/* app support/appName/folderName/ */ + +NSString * _Nullable RSDataSubfolder(NSString * _Nullable appName, NSString *folderName); + +/* app support/appName/folderName/filename */ + +NSString * _Nullable RSDataSubfolderFile(NSString * _Nullable appName, NSString *folderName, NSString *filename); + +NS_ASSUME_NONNULL_END + + +#if TARGET_OS_IPHONE + +#define RS_IMAGE UIImage + +#else + +#define RS_IMAGE NSImage + +#endif + diff --git a/Frameworks/RSCore/RSCore/RSPlatform.m b/Frameworks/RSCore/RSCore/RSPlatform.m new file mode 100755 index 000000000..365f7ada4 --- /dev/null +++ b/Frameworks/RSCore/RSCore/RSPlatform.m @@ -0,0 +1,62 @@ +// +// RSPlatform.m +// RSCore +// +// Created by Brent Simmons on 3/25/15. +// Copyright (c) 2015 Ranchero Software, LLC. All rights reserved. +// + +#import "RSPlatform.h" + +NSString *RSDataFolder(NSString *appName) { + + NSString *dataFolder = [NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES) objectAtIndex:0]; + if (appName == nil) { + appName = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleExecutable"]; + } + dataFolder = [dataFolder stringByAppendingPathComponent:appName]; + + NSError *error = nil; + + if (![[NSFileManager defaultManager] createDirectoryAtPath:dataFolder withIntermediateDirectories:YES attributes:nil error:&error]) { + NSLog(@"RSDataFolder error: %@", error); + return nil; + } + + return dataFolder; +} + + +NSString *RSDataFile(NSString *appName, NSString *fileName) { + + NSCParameterAssert(fileName != nil); + + NSString *dataFolder = RSDataFolder(appName); + return [dataFolder stringByAppendingPathComponent:fileName]; +} + + +NSString *RSDataSubfolder(NSString *appName, NSString *folderName) { + + NSCParameterAssert(folderName != nil); + + NSString *dataFolder = RSDataFile(appName, folderName); + NSError *error = nil; + + if (![[NSFileManager defaultManager] createDirectoryAtPath:dataFolder withIntermediateDirectories:YES attributes:nil error:&error]) { + NSLog(@"RSDataFolder error: %@", error); + return nil; + } + + return dataFolder; +} + + +NSString *RSDataSubfolderFile(NSString *appName, NSString *folderName, NSString *filename) { + + NSCParameterAssert(folderName != nil); + NSCParameterAssert(filename != nil); + + NSString *dataFolder = RSDataSubfolder(appName, folderName); + return [dataFolder stringByAppendingPathComponent:filename]; +} diff --git a/Frameworks/RSCore/RSCore/RSPlist.h b/Frameworks/RSCore/RSCore/RSPlist.h new file mode 100755 index 000000000..42159208b --- /dev/null +++ b/Frameworks/RSCore/RSCore/RSPlist.h @@ -0,0 +1,17 @@ +// +// RSPlist.h +// RSCore +// +// Created by Brent Simmons on 7/26/15. +// Copyright © 2015 Ranchero Software, LLC. All rights reserved. +// + +@import Foundation; + +@interface RSPlist : NSObject + +// Writes using NSPropertyListBinaryFormat_v1_0. + ++ (BOOL)writePlist:(id)obj filePath:(NSString *)filePath error:(NSError **)error; + +@end diff --git a/Frameworks/RSCore/RSCore/RSPlist.m b/Frameworks/RSCore/RSCore/RSPlist.m new file mode 100755 index 000000000..485b47129 --- /dev/null +++ b/Frameworks/RSCore/RSCore/RSPlist.m @@ -0,0 +1,40 @@ +// +// RSPlist.m +// RSCore +// +// Created by Brent Simmons on 7/26/15. +// Copyright © 2015 Ranchero Software, LLC. All rights reserved. +// + +#import "RSPlist.h" + +@implementation RSPlist + ++ (BOOL)writePlist:(id)obj filePath:(NSString *)filePath error:(NSError **)error { + + NSData *propertyListData = [NSPropertyListSerialization dataWithPropertyList:obj format:NSPropertyListBinaryFormat_v1_0 options:0 error:error]; + + static NSLock *lock = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + lock = [[NSLock alloc] init]; + }); + + [lock lock]; + BOOL success = [propertyListData writeToFile:filePath options:NSDataWritingAtomic error:error]; + [lock unlock]; + + if (!success) { + if (*error) { + NSLog(@"Error writing property list: %@", *error); + } + else { + NSLog(@"Unknown error writing property list."); + } + } + + return success; +} + + +@end diff --git a/Frameworks/RSCore/RSCore/RSScaling.h b/Frameworks/RSCore/RSCore/RSScaling.h new file mode 100755 index 000000000..6eda06ccc --- /dev/null +++ b/Frameworks/RSCore/RSCore/RSScaling.h @@ -0,0 +1,16 @@ +// +// RSScaling.h +// RSCore +// +// Created by Brent Simmons on 3/25/15. +// Copyright (c) 2015 Ranchero Software, LLC. All rights reserved. +// + +@import Foundation; +@import CoreGraphics; + + +CGSize RSScaledSizeForImageFittingSize(CGSize imageSize, CGSize constrainingSize); /*does a ceil on size.*/ + +CGFloat RSZoomScaleToFitSize(CGSize imageSize, CGSize constrainingSize); /*Aspect fit*/ +CGFloat RSZoomScaleToFillSize(CGSize imageSize, CGSize constrainingSize); /*Aspect fill*/ diff --git a/Frameworks/RSCore/RSCore/RSScaling.m b/Frameworks/RSCore/RSCore/RSScaling.m new file mode 100755 index 000000000..f465a3679 --- /dev/null +++ b/Frameworks/RSCore/RSCore/RSScaling.m @@ -0,0 +1,61 @@ +// +// RSScaling.m +// RSCore +// +// Created by Brent Simmons on 3/25/15. +// Copyright (c) 2015 Ranchero Software, LLC. All rights reserved. +// + +#import "RSScaling.h" + + +static CGFloat RSScaleFactorToFillSize(CGSize imageSize, CGSize constrainingSize) { + + if (CGSizeEqualToSize(imageSize, constrainingSize)) + return 1.0f; + + CGFloat scaleFactorHeight = imageSize.height / constrainingSize.height; + CGFloat scaleFactorWidth = imageSize.width / constrainingSize.width; + CGFloat scaleFactor = MIN(scaleFactorHeight, scaleFactorWidth); + + return scaleFactor; +} + + +static CGFloat RSScaleFactorToFitSize(CGSize imageSize, CGSize constrainingSize) { + + if (CGSizeEqualToSize(imageSize, constrainingSize)) + return 1.0f; + + CGFloat scaleFactorHeight = imageSize.height / constrainingSize.height; + CGFloat scaleFactorWidth = imageSize.width / constrainingSize.width; + CGFloat scaleFactor = MAX(scaleFactorHeight, scaleFactorWidth); + + return scaleFactor; +} + + +CGFloat RSZoomScaleToFillSize(CGSize imageSize, CGSize constrainingSize) { + + CGFloat scaleFactor = RSScaleFactorToFillSize(imageSize, constrainingSize); + return 1.0f / scaleFactor; +} + + +CGFloat RSZoomScaleToFitSize(CGSize imageSize, CGSize constrainingSize) { + + CGFloat scaleFactor = RSScaleFactorToFitSize(imageSize, constrainingSize); + return 1.0f / scaleFactor; +} + + +CGSize RSScaledSizeForImageFittingSize(CGSize imageSize, CGSize constrainingSize) { + + CGFloat scaleFactor = RSScaleFactorToFitSize(imageSize, constrainingSize); + CGSize scaledSize = CGSizeZero; + + scaledSize.height = ceil(imageSize.height / scaleFactor); + scaledSize.width = ceil(imageSize.width / scaleFactor); + + return scaledSize; +} diff --git a/Frameworks/RSCore/RSCore/RSToolbarItem.swift b/Frameworks/RSCore/RSCore/RSToolbarItem.swift new file mode 100755 index 000000000..a8d4d0637 --- /dev/null +++ b/Frameworks/RSCore/RSCore/RSToolbarItem.swift @@ -0,0 +1,64 @@ +// +// RSToolbarItem.swift +// RSCore +// +// Created by Brent Simmons on 10/16/16. +// Copyright © 2016 Ranchero Software, LLC. All rights reserved. +// + +import Cocoa + +public class RSToolbarItem: NSToolbarItem { + + override public func validate() { + + guard let view = view, let _ = view.window else { + isEnabled = false + return + } + isEnabled = isValidAsUserInterfaceItem() + } +} + +private extension RSToolbarItem { + + func isValidAsUserInterfaceItem() -> Bool { + + // Use NSValidatedUserInterfaceItem protocol rather than calling validateToolbarItem:. + + if let target = target as? NSResponder { + return validateWithResponder(target) ?? false + } + + var responder = view?.window?.firstResponder + if responder == nil { + return false + } + + while(true) { + if let validated = validateWithResponder(responder!) { + return validated + } + responder = responder?.nextResponder + if responder == nil { + break + } + } + + if let appDelegate = NSApplication.shared().delegate { + if let validated = validateWithResponder(appDelegate) { + return validated + } + } + + return false + } + + func validateWithResponder(_ responder: NSObjectProtocol) -> Bool? { + + guard responder.responds(to: action), let target = responder as? NSUserInterfaceValidations else { + return nil + } + return target.validateUserInterfaceItem(self) + } +} diff --git a/Frameworks/RSCore/RSCore/RSTransparentContainerView.h b/Frameworks/RSCore/RSCore/RSTransparentContainerView.h new file mode 100755 index 000000000..98e5f0ff8 --- /dev/null +++ b/Frameworks/RSCore/RSCore/RSTransparentContainerView.h @@ -0,0 +1,17 @@ +// +// RSTransparentContainerView.h +// RSCore +// +// Created by Brent Simmons on 9/19/16. +// Copyright © 2016 Ranchero Software, LLC. All rights reserved. +// + +@import Cocoa; + +/*This view has one subview, which it resizes to fit the bounds of this view.*/ + +@interface RSTransparentContainerView : NSView + +@property (nonatomic) NSView *containedView; /*Removes old.*/ + +@end diff --git a/Frameworks/RSCore/RSCore/RSTransparentContainerView.m b/Frameworks/RSCore/RSCore/RSTransparentContainerView.m new file mode 100755 index 000000000..d3e6ecb0e --- /dev/null +++ b/Frameworks/RSCore/RSCore/RSTransparentContainerView.m @@ -0,0 +1,50 @@ +// +// RSTransparentContainerView.m +// RSCore +// +// Created by Brent Simmons on 9/19/16. +// Copyright © 2016 Ranchero Software, LLC. All rights reserved. +// + +#import "RSTransparentContainerView.h" +#import "NSView+RSCore.h" + + +@implementation RSTransparentContainerView + ++ (BOOL)requiresConstraintBasedLayout { + + return NO; +} + + +- (NSView *)containedView { + + return self.subviews.firstObject; +} + + +- (void)setContainedView:(NSView *)containedView { + + [self.subviews makeObjectsPerformSelector:@selector(removeFromSuperviewWithoutNeedingDisplay)]; + [self addSubview:containedView]; + self.needsLayout = YES; + self.needsDisplay = YES; +} + + +- (void)layout { + + [self resizeSubviewsWithOldSize:NSZeroSize]; +} + + +- (void)resizeSubviewsWithOldSize:(NSSize)oldSize { + +#pragma unused(oldSize) + + NSView *subview = self.subviews.firstObject; + [subview rs_setFrameIfNotEqual:self.bounds]; +} + +@end diff --git a/Frameworks/RSCore/RSCore/Set+Extensions.swift b/Frameworks/RSCore/RSCore/Set+Extensions.swift new file mode 100755 index 000000000..d97e01d54 --- /dev/null +++ b/Frameworks/RSCore/RSCore/Set+Extensions.swift @@ -0,0 +1,29 @@ +// +// Set+Extensions.swift +// RSCore +// +// Created by Brent Simmons on 3/13/16. +// Copyright © 2016 Ranchero Software, LLC. All rights reserved. +// + +import Foundation + +public extension Set { + + public func anyObjectPassingTest( _ test: (Element) -> Bool) -> Element? { + + guard let index = self.index(where: test) else { + return nil + } + + return self[index] + } + + func anyObject() -> Element? { + + if self.isEmpty { + return nil + } + return self[startIndex] + } +} diff --git a/Frameworks/RSCore/RSCoreTests/Info.plist b/Frameworks/RSCore/RSCoreTests/Info.plist new file mode 100755 index 000000000..70ccb93f7 --- /dev/null +++ b/Frameworks/RSCore/RSCoreTests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + com.ranchero.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/Frameworks/RSCore/RSCoreTests/NSString+ExtrasTests.m b/Frameworks/RSCore/RSCoreTests/NSString+ExtrasTests.m new file mode 100755 index 000000000..11fcc88e1 --- /dev/null +++ b/Frameworks/RSCore/RSCoreTests/NSString+ExtrasTests.m @@ -0,0 +1,84 @@ +// +// NSString+ExtrasTests.m +// RSCore +// +// Created by Brent Simmons on 1/27/16. +// Copyright © 2016 Ranchero Software, LLC. All rights reserved. +// + +#import +@import RSCore; + +@interface NSString_ExtrasTests : XCTestCase + +@end + +@implementation NSString_ExtrasTests + +- (void)testTrimmingWhitespace { + + NSString *s = @"\tfoo\n\n\t\r\t"; + NSString *result = [s rs_stringByTrimmingWhitespace]; + XCTAssertEqualObjects(result, @"foo"); + + s = @"\t\n\n\t\r\t"; + result = [s rs_stringByTrimmingWhitespace]; + XCTAssertEqualObjects(result, @""); + + s = @"\t"; + result = [s rs_stringByTrimmingWhitespace]; + XCTAssertEqualObjects(result, @""); + + s = @""; + result = [s rs_stringByTrimmingWhitespace]; + XCTAssertEqualObjects(result, @""); + + s = @"\nfoo\n"; + result = [s rs_stringByTrimmingWhitespace]; + XCTAssertEqualObjects(result, @"foo"); + + s = @"\nfoo"; + result = [s rs_stringByTrimmingWhitespace]; + XCTAssertEqualObjects(result, @"foo"); + + s = @"foo\n"; + result = [s rs_stringByTrimmingWhitespace]; + XCTAssertEqualObjects(result, @"foo"); + + s = @"fo\n\n\n\n\n\no\n"; + result = [s rs_stringByTrimmingWhitespace]; + XCTAssertEqualObjects(result, @"fo\n\n\n\n\n\no"); +} + +- (void)testMD5HashStringPerformance { + + NSString *s1 = @"These are the times that try men’s souls."; + NSString *s2 = @"These are the times that men’s souls."; + NSString *s3 = @"These ar th time that try men’s souls."; + NSString *s4 = @"These are the times that try men’s."; + NSString *s5 = @"These are the that try men’s souls."; + NSString *s6 = @"These are times that try men’s souls."; + NSString *s7 = @"are the times that try men’s souls."; + NSString *s8 = @"These the times that try men’s souls."; + NSString *s9 = @"These are the times tht try men’s souls."; + NSString *s10 = @"These are the times that try men's souls."; + + [self measureBlock:^{ + + for (NSInteger i = 0; i < 1000; i++) { + (void)[s1 rs_md5HashString]; + (void)[s2 rs_md5HashString]; + (void)[s3 rs_md5HashString]; + (void)[s4 rs_md5HashString]; + (void)[s5 rs_md5HashString]; + (void)[s6 rs_md5HashString]; + (void)[s7 rs_md5HashString]; + (void)[s8 rs_md5HashString]; + (void)[s9 rs_md5HashString]; + (void)[s10 rs_md5HashString]; + } + }]; +} + + +@end diff --git a/Frameworks/RSCore/RSCoreTests/RSCoreTests.m b/Frameworks/RSCore/RSCoreTests/RSCoreTests.m new file mode 100755 index 000000000..4d2e193e1 --- /dev/null +++ b/Frameworks/RSCore/RSCoreTests/RSCoreTests.m @@ -0,0 +1,40 @@ +// +// RSCoreTests.m +// RSCoreTests +// +// Created by Brent Simmons on 3/25/15. +// Copyright (c) 2015 Ranchero Software, LLC. All rights reserved. +// + +#import +#import + +@interface RSCoreTests : XCTestCase + +@end + +@implementation RSCoreTests + +- (void)setUp { + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)testExample { + // This is an example of a functional test case. + XCTAssert(YES, @"Pass"); +} + +- (void)testPerformanceExample { + // This is an example of a performance test case. + [self measureBlock:^{ + // Put the code you want to measure the time of here. + }]; +} + +@end diff --git a/Frameworks/RSCore/RSCoreiOS/Info.plist b/Frameworks/RSCore/RSCoreiOS/Info.plist new file mode 100755 index 000000000..b4e5aebb0 --- /dev/null +++ b/Frameworks/RSCore/RSCoreiOS/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + RSCore + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSPrincipalClass + + +