From fd8c742050b3475d8a3f21417bcc6864843c0fc4 Mon Sep 17 00:00:00 2001 From: "Paulo F. Andrade" Date: Mon, 15 Dec 2014 12:25:55 +0000 Subject: [PATCH 1/2] Added support for editing tweaks on OS X. - When targeting OS X, use FBTweakOSX build target --- FBTweak.xcodeproj/project.pbxproj | 190 ++++- FBTweak/FBTweakEditorViewController.h | 13 + FBTweak/FBTweakEditorViewController.m | 104 +++ FBTweak/_FBTweakCategoriesViewController.h | 34 + FBTweak/_FBTweakCategoriesViewController.m | 123 +++ FBTweak/_FBTweakListViewController.h | 16 + FBTweak/_FBTweakListViewController.m | 270 +++++++ FBTweakExample.xcodeproj/project.pbxproj | 152 ++++ FBTweakOSXExample/AppDelegate.h | 16 + FBTweakOSXExample/AppDelegate.m | 79 ++ FBTweakOSXExample/Base.lproj/MainMenu.xib | 708 ++++++++++++++++++ .../AppIcon.appiconset/Contents.json | 58 ++ FBTweakOSXExample/Info.plist | 34 + FBTweakOSXExample/main.m | 13 + README.md | 2 +- 15 files changed, 1799 insertions(+), 13 deletions(-) create mode 100644 FBTweak/FBTweakEditorViewController.h create mode 100644 FBTweak/FBTweakEditorViewController.m create mode 100644 FBTweak/_FBTweakCategoriesViewController.h create mode 100644 FBTweak/_FBTweakCategoriesViewController.m create mode 100644 FBTweak/_FBTweakListViewController.h create mode 100644 FBTweak/_FBTweakListViewController.m create mode 100644 FBTweakOSXExample/AppDelegate.h create mode 100644 FBTweakOSXExample/AppDelegate.m create mode 100644 FBTweakOSXExample/Base.lproj/MainMenu.xib create mode 100644 FBTweakOSXExample/Images.xcassets/AppIcon.appiconset/Contents.json create mode 100644 FBTweakOSXExample/Info.plist create mode 100644 FBTweakOSXExample/main.m diff --git a/FBTweak.xcodeproj/project.pbxproj b/FBTweak.xcodeproj/project.pbxproj index 64d146cf..426ecd9d 100644 --- a/FBTweak.xcodeproj/project.pbxproj +++ b/FBTweak.xcodeproj/project.pbxproj @@ -17,9 +17,7 @@ 18EFE48C189EBA4900DA6A5D /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 18EFE48A189EBA4900DA6A5D /* InfoPlist.strings */; }; 18EFE4A7189EBA9E00DA6A5D /* FBTweakViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18EFE4A5189EBA9E00DA6A5D /* FBTweakViewController.m */; }; 18EFE4AB189EBAAD00DA6A5D /* FBTweakInline.m in Sources */ = {isa = PBXBuildFile; fileRef = 18EFE4A9189EBAAD00DA6A5D /* FBTweakInline.m */; }; - 18EFE4AF189EBABA00DA6A5D /* FBTweakShakeWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 18EFE4AD189EBABA00DA6A5D /* FBTweakShakeWindow.m */; }; 18EFE4B2189EBAC200DA6A5D /* FBTweakInline.h in Headers */ = {isa = PBXBuildFile; fileRef = 18EFE4A8189EBAAD00DA6A5D /* FBTweakInline.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18EFE4B3189EBAC200DA6A5D /* FBTweakShakeWindow.h in Headers */ = {isa = PBXBuildFile; fileRef = 18EFE4AC189EBABA00DA6A5D /* FBTweakShakeWindow.h */; settings = {ATTRIBUTES = (Public, ); }; }; 18EFE4B4189EBAC200DA6A5D /* FBTweakViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 18EFE4A4189EBA9E00DA6A5D /* FBTweakViewController.h */; settings = {ATTRIBUTES = (Public, ); }; }; 18EFE4B7189EBC3100DA6A5D /* FBTweak.h in Headers */ = {isa = PBXBuildFile; fileRef = 18EFE4B5189EBC3100DA6A5D /* FBTweak.h */; settings = {ATTRIBUTES = (Public, ); }; }; 18EFE4B8189EBC3100DA6A5D /* FBTweak.m in Sources */ = {isa = PBXBuildFile; fileRef = 18EFE4B6189EBC3100DA6A5D /* FBTweak.m */; }; @@ -39,6 +37,29 @@ 18EFE528189F19B300DA6A5D /* FBTweakCategory.m in Sources */ = {isa = PBXBuildFile; fileRef = 18EFE526189F19B300DA6A5D /* FBTweakCategory.m */; }; 18EFE52D189F250700DA6A5D /* FBTweakInlineTestsMRR.m in Sources */ = {isa = PBXBuildFile; fileRef = 18EFE52C189F250700DA6A5D /* FBTweakInlineTestsMRR.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; 18EFE536189F38D500DA6A5D /* FBTweakEnabled.h in Headers */ = {isa = PBXBuildFile; fileRef = 18EFE535189F38D500DA6A5D /* FBTweakEnabled.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 2731A25E1A3CCB73003BFA2D /* FBTweakShakeWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 18EFE4AD189EBABA00DA6A5D /* FBTweakShakeWindow.m */; }; + 2731A25F1A3CCB77003BFA2D /* FBTweakShakeWindow.h in Headers */ = {isa = PBXBuildFile; fileRef = 18EFE4AC189EBABA00DA6A5D /* FBTweakShakeWindow.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 2731A28C1A3CCF07003BFA2D /* FBTweakInline.m in Sources */ = {isa = PBXBuildFile; fileRef = 18EFE4A9189EBAAD00DA6A5D /* FBTweakInline.m */; }; + 2731A28D1A3CCF0A003BFA2D /* _FBTweakBindObserver.m in Sources */ = {isa = PBXBuildFile; fileRef = 184A94EF18D26871005F2774 /* _FBTweakBindObserver.m */; }; + 2731A28E1A3CCF0F003BFA2D /* FBTweak.m in Sources */ = {isa = PBXBuildFile; fileRef = 18EFE4B6189EBC3100DA6A5D /* FBTweak.m */; }; + 2731A28F1A3CCF0F003BFA2D /* FBTweakCollection.m in Sources */ = {isa = PBXBuildFile; fileRef = 18EFE4BB189EBC4B00DA6A5D /* FBTweakCollection.m */; }; + 2731A2901A3CCF0F003BFA2D /* FBTweakCategory.m in Sources */ = {isa = PBXBuildFile; fileRef = 18EFE526189F19B300DA6A5D /* FBTweakCategory.m */; }; + 2731A2911A3CCF0F003BFA2D /* FBTweakStore.m in Sources */ = {isa = PBXBuildFile; fileRef = 18EFE4C0189EBEAD00DA6A5D /* FBTweakStore.m */; }; + 2731A2921A3CCF13003BFA2D /* FBTweakEditorViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2731A2641A3CCC86003BFA2D /* FBTweakEditorViewController.m */; }; + 2731A2931A3CCF16003BFA2D /* _FBTweakCategoriesViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2731A2681A3CCD22003BFA2D /* _FBTweakCategoriesViewController.m */; }; + 2731A2971A3CCFA4003BFA2D /* FBTweakEnabled.h in Headers */ = {isa = PBXBuildFile; fileRef = 18EFE535189F38D500DA6A5D /* FBTweakEnabled.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 2731A2981A3CCFAA003BFA2D /* FBTweakInline.h in Headers */ = {isa = PBXBuildFile; fileRef = 18EFE4A8189EBAAD00DA6A5D /* FBTweakInline.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 2731A2991A3CCFAF003BFA2D /* FBTweakInlineInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 18EFE4CF189EC70300DA6A5D /* FBTweakInlineInternal.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 2731A29A1A3CCFB8003BFA2D /* _FBTweakBindObserver.h in Headers */ = {isa = PBXBuildFile; fileRef = 184A94EE18D26871005F2774 /* _FBTweakBindObserver.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 2731A29B1A3CCFC0003BFA2D /* FBTweak.h in Headers */ = {isa = PBXBuildFile; fileRef = 18EFE4B5189EBC3100DA6A5D /* FBTweak.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 2731A29C1A3CCFC6003BFA2D /* FBTweakCollection.h in Headers */ = {isa = PBXBuildFile; fileRef = 18EFE4BA189EBC4B00DA6A5D /* FBTweakCollection.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 2731A29D1A3CCFCD003BFA2D /* FBTweakCategory.h in Headers */ = {isa = PBXBuildFile; fileRef = 18EFE525189F19B300DA6A5D /* FBTweakCategory.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 2731A29E1A3CCFD3003BFA2D /* FBTweakStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 18EFE4BF189EBEAD00DA6A5D /* FBTweakStore.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 2731A29F1A3CCFDC003BFA2D /* FBTweakEditorViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 2731A2631A3CCC86003BFA2D /* FBTweakEditorViewController.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 2731A2A01A3CCFE2003BFA2D /* _FBTweakCategoriesViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 2731A2671A3CCD22003BFA2D /* _FBTweakCategoriesViewController.h */; }; + 2731A2A11A3CD07F003BFA2D /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2731A26C1A3CCE08003BFA2D /* Cocoa.framework */; }; + 2731A2A51A3DA243003BFA2D /* _FBTweakListViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 2731A2A21A3DA243003BFA2D /* _FBTweakListViewController.h */; }; + 2731A2A61A3DA243003BFA2D /* _FBTweakListViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2731A2A31A3DA243003BFA2D /* _FBTweakListViewController.m */; }; 29E9F17B18E35C9C001EAF7D /* MessageUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 29E9F17A18E35C9C001EAF7D /* MessageUI.framework */; }; /* End PBXBuildFile section */ @@ -87,6 +108,15 @@ 18EFE526189F19B300DA6A5D /* FBTweakCategory.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBTweakCategory.m; sourceTree = ""; }; 18EFE52C189F250700DA6A5D /* FBTweakInlineTestsMRR.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBTweakInlineTestsMRR.m; sourceTree = ""; }; 18EFE535189F38D500DA6A5D /* FBTweakEnabled.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBTweakEnabled.h; sourceTree = ""; }; + 2731A2631A3CCC86003BFA2D /* FBTweakEditorViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBTweakEditorViewController.h; sourceTree = ""; }; + 2731A2641A3CCC86003BFA2D /* FBTweakEditorViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBTweakEditorViewController.m; sourceTree = ""; }; + 2731A2671A3CCD22003BFA2D /* _FBTweakCategoriesViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _FBTweakCategoriesViewController.h; sourceTree = ""; }; + 2731A2681A3CCD22003BFA2D /* _FBTweakCategoriesViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = _FBTweakCategoriesViewController.m; sourceTree = ""; }; + 2731A26C1A3CCE08003BFA2D /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; + 2731A26E1A3CCE4C003BFA2D /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; + 2731A2751A3CCEE6003BFA2D /* libFBTweakOSX.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libFBTweakOSX.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 2731A2A21A3DA243003BFA2D /* _FBTweakListViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _FBTweakListViewController.h; sourceTree = ""; }; + 2731A2A31A3DA243003BFA2D /* _FBTweakListViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = _FBTweakListViewController.m; sourceTree = ""; }; 29E9F17A18E35C9C001EAF7D /* MessageUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MessageUI.framework; path = System/Library/Frameworks/MessageUI.framework; sourceTree = SDKROOT; }; /* End PBXFileReference section */ @@ -111,6 +141,14 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 2731A2721A3CCEE6003BFA2D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 2731A2A11A3CD07F003BFA2D /* Cocoa.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ @@ -129,6 +167,7 @@ children = ( 18EFE46E189EBA4900DA6A5D /* libFBTweak.a */, 18EFE47E189EBA4900DA6A5D /* FBTweakTests.xctest */, + 2731A2751A3CCEE6003BFA2D /* libFBTweakOSX.a */, ); name = Products; sourceTree = ""; @@ -136,6 +175,8 @@ 18EFE470189EBA4900DA6A5D /* Frameworks */ = { isa = PBXGroup; children = ( + 2731A26E1A3CCE4C003BFA2D /* AppKit.framework */, + 2731A26C1A3CCE08003BFA2D /* Cocoa.framework */, 29E9F17A18E35C9C001EAF7D /* MessageUI.framework */, 18EFE471189EBA4900DA6A5D /* Foundation.framework */, 18EFE47F189EBA4900DA6A5D /* XCTest.framework */, @@ -199,6 +240,27 @@ sourceTree = ""; }; 18EFE4BE189EBD0800DA6A5D /* UI */ = { + isa = PBXGroup; + children = ( + 2731A25D1A3CCB0D003BFA2D /* OSX */, + 2731A23A1A3CCA62003BFA2D /* iOS */, + ); + name = UI; + sourceTree = ""; + }; + 18EFE532189F286000DA6A5D /* Inline */ = { + isa = PBXGroup; + children = ( + 18EFE4A8189EBAAD00DA6A5D /* FBTweakInline.h */, + 18EFE4CF189EC70300DA6A5D /* FBTweakInlineInternal.h */, + 18EFE4A9189EBAAD00DA6A5D /* FBTweakInline.m */, + 184A94EE18D26871005F2774 /* _FBTweakBindObserver.h */, + 184A94EF18D26871005F2774 /* _FBTweakBindObserver.m */, + ); + name = Inline; + sourceTree = ""; + }; + 2731A23A1A3CCA62003BFA2D /* iOS */ = { isa = PBXGroup; children = ( 18EFE4AC189EBABA00DA6A5D /* FBTweakShakeWindow.h */, @@ -212,19 +274,20 @@ 18EFE4DB189EF75800DA6A5D /* _FBTweakTableViewCell.h */, 18EFE4DC189EF75800DA6A5D /* _FBTweakTableViewCell.m */, ); - name = UI; + name = iOS; sourceTree = ""; }; - 18EFE532189F286000DA6A5D /* Inline */ = { + 2731A25D1A3CCB0D003BFA2D /* OSX */ = { isa = PBXGroup; children = ( - 18EFE4A8189EBAAD00DA6A5D /* FBTweakInline.h */, - 18EFE4CF189EC70300DA6A5D /* FBTweakInlineInternal.h */, - 18EFE4A9189EBAAD00DA6A5D /* FBTweakInline.m */, - 184A94EE18D26871005F2774 /* _FBTweakBindObserver.h */, - 184A94EF18D26871005F2774 /* _FBTweakBindObserver.m */, + 2731A2631A3CCC86003BFA2D /* FBTweakEditorViewController.h */, + 2731A2641A3CCC86003BFA2D /* FBTweakEditorViewController.m */, + 2731A2671A3CCD22003BFA2D /* _FBTweakCategoriesViewController.h */, + 2731A2681A3CCD22003BFA2D /* _FBTweakCategoriesViewController.m */, + 2731A2A21A3DA243003BFA2D /* _FBTweakListViewController.h */, + 2731A2A31A3DA243003BFA2D /* _FBTweakListViewController.m */, ); - name = Inline; + name = OSX; sourceTree = ""; }; /* End PBXGroup section */ @@ -240,16 +303,34 @@ 18EFE4B4189EBAC200DA6A5D /* FBTweakViewController.h in Headers */, 18EFE4C1189EBEAD00DA6A5D /* FBTweakStore.h in Headers */, 18EFE4B2189EBAC200DA6A5D /* FBTweakInline.h in Headers */, - 18EFE4B3189EBAC200DA6A5D /* FBTweakShakeWindow.h in Headers */, 18EFE536189F38D500DA6A5D /* FBTweakEnabled.h in Headers */, 18EFE4D0189EC70300DA6A5D /* FBTweakInlineInternal.h in Headers */, 18EFE527189F19B300DA6A5D /* FBTweakCategory.h in Headers */, + 2731A25F1A3CCB77003BFA2D /* FBTweakShakeWindow.h in Headers */, 18EFE4BC189EBC4B00DA6A5D /* FBTweakCollection.h in Headers */, 18EFE4DD189EF75800DA6A5D /* _FBTweakTableViewCell.h in Headers */, 184A94F018D26871005F2774 /* _FBTweakBindObserver.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; + 2731A2731A3CCEE6003BFA2D /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 2731A29D1A3CCFCD003BFA2D /* FBTweakCategory.h in Headers */, + 2731A29A1A3CCFB8003BFA2D /* _FBTweakBindObserver.h in Headers */, + 2731A2991A3CCFAF003BFA2D /* FBTweakInlineInternal.h in Headers */, + 2731A2A51A3DA243003BFA2D /* _FBTweakListViewController.h in Headers */, + 2731A29C1A3CCFC6003BFA2D /* FBTweakCollection.h in Headers */, + 2731A2981A3CCFAA003BFA2D /* FBTweakInline.h in Headers */, + 2731A2971A3CCFA4003BFA2D /* FBTweakEnabled.h in Headers */, + 2731A29E1A3CCFD3003BFA2D /* FBTweakStore.h in Headers */, + 2731A29B1A3CCFC0003BFA2D /* FBTweak.h in Headers */, + 2731A2A01A3CCFE2003BFA2D /* _FBTweakCategoriesViewController.h in Headers */, + 2731A29F1A3CCFDC003BFA2D /* FBTweakEditorViewController.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ @@ -288,6 +369,23 @@ productReference = 18EFE47E189EBA4900DA6A5D /* FBTweakTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; + 2731A2741A3CCEE6003BFA2D /* FBTweakOSX */ = { + isa = PBXNativeTarget; + buildConfigurationList = 2731A2861A3CCEE6003BFA2D /* Build configuration list for PBXNativeTarget "FBTweakOSX" */; + buildPhases = ( + 2731A2711A3CCEE6003BFA2D /* Sources */, + 2731A2721A3CCEE6003BFA2D /* Frameworks */, + 2731A2731A3CCEE6003BFA2D /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = FBTweakOSX; + productName = FBTweakOSX; + productReference = 2731A2751A3CCEE6003BFA2D /* libFBTweakOSX.a */; + productType = "com.apple.product-type.library.static"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ @@ -296,6 +394,11 @@ attributes = { LastUpgradeCheck = 0510; ORGANIZATIONNAME = Facebook; + TargetAttributes = { + 2731A2741A3CCEE6003BFA2D = { + CreatedOnToolsVersion = 6.1.1; + }; + }; }; buildConfigurationList = 18EFE469189EBA4900DA6A5D /* Build configuration list for PBXProject "FBTweak" */; compatibilityVersion = "Xcode 3.2"; @@ -311,6 +414,7 @@ targets = ( 18EFE46D189EBA4900DA6A5D /* FBTweak */, 18EFE47D189EBA4900DA6A5D /* FBTweakTests */, + 2731A2741A3CCEE6003BFA2D /* FBTweakOSX */, ); }; /* End PBXProject section */ @@ -339,7 +443,7 @@ 18EFE4DE189EF75800DA6A5D /* _FBTweakTableViewCell.m in Sources */, 18EFE528189F19B300DA6A5D /* FBTweakCategory.m in Sources */, 18EFE4D6189EEBC500DA6A5D /* _FBTweakCategoryViewController.m in Sources */, - 18EFE4AF189EBABA00DA6A5D /* FBTweakShakeWindow.m in Sources */, + 2731A25E1A3CCB73003BFA2D /* FBTweakShakeWindow.m in Sources */, 18EFE4DA189EEED800DA6A5D /* _FBTweakCollectionViewController.m in Sources */, 184A94F118D26871005F2774 /* _FBTweakBindObserver.m in Sources */, ); @@ -354,6 +458,22 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 2731A2711A3CCEE6003BFA2D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 2731A2901A3CCF0F003BFA2D /* FBTweakCategory.m in Sources */, + 2731A28E1A3CCF0F003BFA2D /* FBTweak.m in Sources */, + 2731A28F1A3CCF0F003BFA2D /* FBTweakCollection.m in Sources */, + 2731A2931A3CCF16003BFA2D /* _FBTweakCategoriesViewController.m in Sources */, + 2731A2A61A3DA243003BFA2D /* _FBTweakListViewController.m in Sources */, + 2731A28D1A3CCF0A003BFA2D /* _FBTweakBindObserver.m in Sources */, + 2731A28C1A3CCF07003BFA2D /* FBTweakInline.m in Sources */, + 2731A2921A3CCF13003BFA2D /* FBTweakEditorViewController.m in Sources */, + 2731A2911A3CCF0F003BFA2D /* FBTweakStore.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ @@ -465,6 +585,7 @@ 18EFE493189EBA4900DA6A5D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + CODE_SIGN_IDENTITY = "iPhone Developer"; DSTROOT = /tmp/FBTweak.dst; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "FBTweak/FBTweak-Prefix.pch"; @@ -497,6 +618,7 @@ 18EFE496189EBA4900DA6A5D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + CODE_SIGN_IDENTITY = "iPhone Developer"; FRAMEWORK_SEARCH_PATHS = ( "$(SDKROOT)/Developer/Library/Frameworks", "$(inherited)", @@ -510,6 +632,41 @@ }; name = Release; }; + 2731A2871A3CCEE6003BFA2D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_WARN_UNREACHABLE_CODE = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + EXECUTABLE_PREFIX = lib; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + MACOSX_DEPLOYMENT_TARGET = 10.10; + MTL_ENABLE_DEBUG_INFO = YES; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Debug; + }; + 2731A2881A3CCEE6003BFA2D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_WARN_UNREACHABLE_CODE = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + EXECUTABLE_PREFIX = lib; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + MACOSX_DEPLOYMENT_TARGET = 10.10; + MTL_ENABLE_DEBUG_INFO = NO; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -540,6 +697,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + 2731A2861A3CCEE6003BFA2D /* Build configuration list for PBXNativeTarget "FBTweakOSX" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 2731A2871A3CCEE6003BFA2D /* Debug */, + 2731A2881A3CCEE6003BFA2D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; /* End XCConfigurationList section */ }; rootObject = 18EFE466189EBA4900DA6A5D /* Project object */; diff --git a/FBTweak/FBTweakEditorViewController.h b/FBTweak/FBTweakEditorViewController.h new file mode 100644 index 00000000..97b0a729 --- /dev/null +++ b/FBTweak/FBTweakEditorViewController.h @@ -0,0 +1,13 @@ +// +// FBTweaksEditorViewController.h +// FBTweak +// +// Created by Paulo Andrade on 13/12/14. +// Copyright (c) 2014 Facebook. All rights reserved. +// + +#import + +@interface FBTweakEditorViewController : NSViewController + +@end diff --git a/FBTweak/FBTweakEditorViewController.m b/FBTweak/FBTweakEditorViewController.m new file mode 100644 index 00000000..e71dcaed --- /dev/null +++ b/FBTweak/FBTweakEditorViewController.m @@ -0,0 +1,104 @@ +// +// FBTweaksEditorViewController.m +// FBTweak +// +// Created by Paulo Andrade on 13/12/14. +// Copyright (c) 2014 Facebook. All rights reserved. +// + +#import "FBTweakEditorViewController.h" +#import "_FBTweakCategoriesViewController.h" +#import "_FBTweakListViewController.h" + +@interface FBTweakEditorViewController () <_FBTweakCategoriesViewControllerDelegate> + +@property (nonatomic, strong) NSSplitViewController *splitViewController; + +@property (nonatomic, strong) NSSplitViewItem *categoriesSplitViewItem; +@property (nonatomic, strong) _FBTweakCategoriesViewController *categoriesViewController; + +@property (nonatomic, strong) NSSplitViewItem *listSplitViewItem; +@property (nonatomic, strong) _FBTweakListViewController *listViewController; + + + +@end + +@implementation FBTweakEditorViewController + +- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil +{ + self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; + if (self) { + self.title = @"Tweaks"; + } + return self; +} + +- (void)loadView +{ + NSView *view = [[NSView alloc] initWithFrame:CGRectMake(0, 0, 640, 480)]; + + _FBTweakCategoriesViewController *categories = [[_FBTweakCategoriesViewController alloc] initWithStore:[FBTweakStore sharedInstance]]; + categories.delegate = self; + _FBTweakListViewController *list = [[_FBTweakListViewController alloc] init]; + + NSSplitViewController *splitViewController = [[NSSplitViewController alloc] init]; + + // Categories + NSSplitViewItem *splitItem = [NSSplitViewItem splitViewItemWithViewController:categories]; + NSView *splitItemView = [categories view]; + splitItemView.translatesAutoresizingMaskIntoConstraints = NO; + NSLayoutConstraint *width = [NSLayoutConstraint constraintWithItem:splitItemView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:150]; + width.priority = NSLayoutPriorityDefaultLow; + width.active = YES; + splitItem.holdingPriority = NSLayoutPriorityDefaultLow+1; + splitItem.collapsed = NO; + splitItem.canCollapse = NO; + [splitViewController addSplitViewItem:splitItem]; + self.categoriesSplitViewItem = splitItem; + + // Collections + splitItem = [NSSplitViewItem splitViewItemWithViewController:list]; + splitItemView = [list view]; + splitItemView.translatesAutoresizingMaskIntoConstraints = NO; + width = [NSLayoutConstraint constraintWithItem:splitItemView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:330]; + width.priority = NSLayoutPriorityDefaultLow; + width.active = YES; + splitItem.holdingPriority = NSLayoutPriorityDefaultLow; + splitItem.collapsed = NO; + splitItem.canCollapse = NO; + + [splitViewController addSplitViewItem:splitItem]; + self.listSplitViewItem = splitItem; + + NSView *splitView = [splitViewController view]; + splitView.frame = view.bounds; + splitView.autoresizingMask = NSViewWidthSizable|NSViewHeightSizable; + [view addSubview:splitView]; + + self.categoriesViewController = categories; + self.listViewController = list; + self.splitViewController = splitViewController; + + [self addChildViewController:self.splitViewController]; + + self.view = view; +} + +- (void)viewWillAppear +{ + [super viewWillAppear]; + self.listViewController.tweakCategory = [self.categoriesViewController selectedCategory]; +} + +#pragma mark - Delegates + +#pragma mark _FBTweakCategoriesViewControllerDelegate + +- (void)categoriesViewController:(_FBTweakCategoriesViewController *)controller didChangeSelection:(FBTweakCategory *)category +{ + self.listViewController.tweakCategory = category; +} + +@end diff --git a/FBTweak/_FBTweakCategoriesViewController.h b/FBTweak/_FBTweakCategoriesViewController.h new file mode 100644 index 00000000..ddfc22a7 --- /dev/null +++ b/FBTweak/_FBTweakCategoriesViewController.h @@ -0,0 +1,34 @@ +// +// _FBTweakCategoriesViewController.h +// FBTweak +// +// Created by Paulo Andrade on 13/12/14. +// Copyright (c) 2014 Facebook. All rights reserved. +// + +#import +#import "FBTweakStore.h" +#import "FBTweakCategory.h" + +@protocol _FBTweakCategoriesViewControllerDelegate; + + + +@interface _FBTweakCategoriesViewController : NSViewController + +- (instancetype)initWithStore:(FBTweakStore *)store; + +@property (nonatomic, weak) id<_FBTweakCategoriesViewControllerDelegate> delegate; + +- (FBTweakCategory *)selectedCategory; + +@end + + + + +@protocol _FBTweakCategoriesViewControllerDelegate + +- (void)categoriesViewController:(_FBTweakCategoriesViewController *)controller didChangeSelection:(FBTweakCategory *)category; + +@end diff --git a/FBTweak/_FBTweakCategoriesViewController.m b/FBTweak/_FBTweakCategoriesViewController.m new file mode 100644 index 00000000..f47b0170 --- /dev/null +++ b/FBTweak/_FBTweakCategoriesViewController.m @@ -0,0 +1,123 @@ +// +// _FBTweakCategoriesViewController.m +// FBTweak +// +// Created by Paulo Andrade on 13/12/14. +// Copyright (c) 2014 Facebook. All rights reserved. +// + +#import "_FBTweakCategoriesViewController.h" +#import "FBTweakStore.h" +#import "FBTweakCategory.h" + +@interface _FBTweakCategoriesViewController () + + +@property (nonatomic, weak) NSOutlineView *outlineView; + +@end + +@implementation _FBTweakCategoriesViewController { + NSArray *_sortedCategories; +} + +- (instancetype)initWithStore:(FBTweakStore *)store +{ + self = [super initWithNibName:@"" bundle:nil]; + if (self) { + _sortedCategories = [store.tweakCategories sortedArrayUsingComparator:^(FBTweakCategory *a, FBTweakCategory *b) { + return [a.name localizedStandardCompare:b.name]; + }]; + } + return self; +} + +- (void)loadView +{ + NSView *view = [[NSView alloc] initWithFrame:CGRectMake(0, 0, 300, 500)]; + + NSScrollView *scrollView = [[NSScrollView alloc] initWithFrame:view.bounds]; + scrollView.autoresizingMask = NSViewWidthSizable|NSViewHeightSizable; + + NSOutlineView *outlineView = [[NSOutlineView alloc] initWithFrame:scrollView.bounds]; + outlineView.autoresizingMask = NSViewWidthSizable|NSViewHeightSizable; + outlineView.translatesAutoresizingMaskIntoConstraints = NO; + outlineView.dataSource = self; + outlineView.delegate = self; + outlineView.allowsEmptySelection = NO; + outlineView.allowsMultipleSelection = NO; + outlineView.selectionHighlightStyle = NSTableViewSelectionHighlightStyleSourceList; + + NSTableColumn *column = [[NSTableColumn alloc] initWithIdentifier:@"Categories"]; + column.title = @"Categories"; + column.width = CGRectGetWidth(view.frame); + column.editable = NO; + [outlineView addTableColumn:column]; + + scrollView.documentView = outlineView; + scrollView.autoresizesSubviews = YES; + + [view addSubview:scrollView]; + + [view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[outlineView]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(outlineView)]]; + [view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[outlineView]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(outlineView)]]; + + self.outlineView = outlineView; + + self.view = view; +} + + +- (FBTweakCategory *)selectedCategory +{ + return _sortedCategories[[self.outlineView selectedRow]]; +} + +- (void)viewDidAppear +{ + [super viewDidAppear]; + [self.outlineView reloadData]; +} + +#pragma mark - NSOutlineView + +#pragma mark datasource + +- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item +{ + return (item == nil) ? [_sortedCategories count] : 0; +} + +- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item +{ + return _sortedCategories[index]; +} + +- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item +{ + return NO; +} + + +#pragma mark delegate + +- (NSView *)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(FBTweakCategory *)category +{ + NSTableCellView *cellView = [[NSTableCellView alloc] initWithFrame:CGRectMake(0, 0, 100, 50)]; + NSTextField *textField = [[NSTextField alloc] initWithFrame:cellView.bounds]; + textField.autoresizingMask = NSViewWidthSizable|NSViewHeightSizable; + textField.stringValue = category.name; + textField.bordered = NO; + textField.drawsBackground = NO; + textField.focusRingType = NSFocusRingTypeNone; + [cellView addSubview:textField]; + cellView.textField = textField; + return cellView; +} + +- (void)outlineViewSelectionDidChange:(NSNotification *)notification +{ + [self.delegate categoriesViewController:self didChangeSelection:[self selectedCategory]]; +} + +@end diff --git a/FBTweak/_FBTweakListViewController.h b/FBTweak/_FBTweakListViewController.h new file mode 100644 index 00000000..45829e53 --- /dev/null +++ b/FBTweak/_FBTweakListViewController.h @@ -0,0 +1,16 @@ +// +// _FBTweakListViewController.h +// FBTweak +// +// Created by Paulo Andrade on 14/12/14. +// Copyright (c) 2014 Facebook. All rights reserved. +// + +#import +#import "FBTweakCategory.h" + +@interface _FBTweakListViewController : NSViewController + +@property (nonatomic, strong) FBTweakCategory *tweakCategory; + +@end diff --git a/FBTweak/_FBTweakListViewController.m b/FBTweak/_FBTweakListViewController.m new file mode 100644 index 00000000..9746860d --- /dev/null +++ b/FBTweak/_FBTweakListViewController.m @@ -0,0 +1,270 @@ +// +// _FBTweakListViewController.m +// FBTweak +// +// Created by Paulo Andrade on 14/12/14. +// Copyright (c) 2014 Facebook. All rights reserved. +// + +#import "_FBTweakListViewController.h" +#import "FBTweakCollection.h" +#import "FBTweak.h" + +@interface _FBTableView : NSTableView @end +@implementation _FBTableView +- (BOOL)validateProposedFirstResponder:(NSResponder *)responder forEvent:(NSEvent *)event { return YES; } +@end + +@interface _FBTweakListViewController () + +@property (nonatomic, weak) NSTableView *tableView; + +@end + +@implementation _FBTweakListViewController { + NSArray *_flattenedTweaks; +} + +- (void)loadView +{ + NSView *view = [[NSView alloc] initWithFrame:CGRectMake(0, 0, 300, 500)]; + NSScrollView *scrollView = [[NSScrollView alloc] initWithFrame:view.bounds]; + scrollView.autoresizingMask = NSViewWidthSizable|NSViewHeightSizable; + + NSTableView *tableView = [[_FBTableView alloc] initWithFrame:scrollView.bounds]; + tableView.autoresizingMask = NSViewWidthSizable|NSViewHeightSizable; + tableView.dataSource = self; + tableView.delegate = self; + tableView.target = self; + tableView.doubleAction = @selector(tableViewDoubleClicked:); + + NSTableColumn *column = [[NSTableColumn alloc] initWithIdentifier:@"Name"]; + column.title = column.identifier; + column.width = 150; + [tableView addTableColumn:column]; + column = [[NSTableColumn alloc] initWithIdentifier:@"Default Value"]; + column.title = column.identifier; + [tableView addTableColumn:column]; + column = [[NSTableColumn alloc] initWithIdentifier:@"Current Value"]; + column.title = column.identifier; + [tableView addTableColumn:column]; + + scrollView.documentView = tableView; + scrollView.autoresizesSubviews = YES; + + [view addSubview:scrollView]; + + self.tableView = tableView; + self.view = view; +} + +- (void)viewWillAppear +{ + [super viewWillAppear]; + [self.tableView reloadData]; +} + +#pragma mark - Properties + +- (void)setTweakCategory:(FBTweakCategory *)tweakCategory +{ + _tweakCategory = tweakCategory; + NSArray *sortedCollections = [_tweakCategory.tweakCollections sortedArrayUsingComparator:^(FBTweakCollection *a, FBTweakCollection *b) { + return [a.name localizedStandardCompare:b.name]; + }]; + + NSMutableArray *array = [NSMutableArray array]; + [sortedCollections enumerateObjectsUsingBlock:^(FBTweakCollection *collection, NSUInteger idx, BOOL *stop) { + [array addObject:collection]; + [array addObjectsFromArray:collection.tweaks]; + }]; + _flattenedTweaks = [array copy]; + + [self.tableView reloadData]; +} + +#pragma mark - Actions + +- (void)showFontPanel:(id)sender +{ + NSFontManager * fontManager = [NSFontManager sharedFontManager]; + [fontManager setTarget:self]; + + if ( [self.tableView selectedRow] >= 0) { + id object = [_flattenedTweaks objectAtIndex:[self.tableView selectedRow]]; + + if ([object isKindOfClass:[FBTweak class]]) { + FBTweak *tweak = (FBTweak *)object; + if ([[tweak defaultValue] isKindOfClass:[NSFont class]]) { + [fontManager setSelectedFont:[tweak currentValue]?:[tweak defaultValue] isMultiple:NO]; + } + } + } + + [fontManager orderFrontFontPanel:self]; +} + +- (void)tableViewDoubleClicked:(id)sender +{ + if ( [self.tableView selectedRow] >= 0) { + if ( [self.tableView selectedRow] >= 0) { + id object = [_flattenedTweaks objectAtIndex:[self.tableView selectedRow]]; + + if ([object isKindOfClass:[FBTweak class]]) { + FBTweak *tweak = (FBTweak *)object; + + if ([tweak isAction]) { + dispatch_block_t block = tweak.defaultValue; + if (block != NULL) { + block(); + } + } + } + } + } +} + + +#pragma mark - NSTableView + +#pragma mark datasource + +- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView +{ + return [_flattenedTweaks count]; +} + + +- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row +{ + NSTableCellView *cellView = nil; + id object = _flattenedTweaks[row]; + + if ([object isKindOfClass:[FBTweakCollection class]]) { + cellView = [self textCellViewWithString:[(FBTweakCollection *)object name]]; + } + else { + FBTweak *tweak = (FBTweak *)object; + + id defaultValue = [tweak defaultValue]; + + if ( [tableColumn.identifier isEqualToString:@"Name"] ) { + cellView = [self textCellViewWithString:[tweak name]]; + } + else if ( [tableColumn.identifier isEqualToString:@"Default Value"] ){ + + if ([defaultValue isKindOfClass:[NSString class]]) { + cellView = [self textCellViewWithString:[tweak defaultValue]]; + } + else if( [defaultValue isKindOfClass:[NSNumber class]] ) { + cellView = [self textCellViewWithString:[NSNumberFormatter localizedStringFromNumber:defaultValue numberStyle:NSNumberFormatterDecimalStyle]]; + } + else if( [tweak isAction] ){ + cellView = [self textCellViewWithString:@"Double-click to perform action"]; + } + + } + else if ( [tableColumn.identifier isEqualToString:@"Current Value"] ){ + if ([defaultValue isKindOfClass:[NSString class]]) { + cellView = [self editTextCellViewWithTweak:tweak]; + } + else if ([defaultValue isKindOfClass:[NSNumber class]]) { + cellView = [self editNumberCellViewWithTweak:tweak]; + } + } + } + + return cellView; +} + +- (NSTableCellView *)textCellViewWithString:(NSString *)string +{ + NSTableCellView *cellView = [[NSTableCellView alloc] initWithFrame:CGRectMake(0, 0, 100, 44)]; + NSTextField *textField = [[NSTextField alloc] initWithFrame:cellView.bounds]; + textField.bordered = NO; + textField.drawsBackground = NO; + textField.editable = NO; + textField.autoresizingMask = NSViewHeightSizable|NSViewWidthSizable; + textField.stringValue = string ?: @""; + + [cellView addSubview:textField]; + cellView.textField = textField; + + return cellView; +} + +- (NSTableCellView *)editTextCellViewWithTweak:(FBTweak *)tweak +{ + NSTableCellView *cellView = [[NSTableCellView alloc] initWithFrame:CGRectMake(0, 0, 100, 44)]; + NSTextField *textField = [[NSTextField alloc] initWithFrame:cellView.bounds]; + textField.bordered = YES; + textField.editable = YES; + textField.autoresizingMask = NSViewHeightSizable|NSViewWidthSizable; + + [textField bind:@"value" toObject:tweak withKeyPath:@"currentValue" options:nil]; + + [cellView addSubview:textField]; + cellView.textField = textField; + + return cellView; +} + +- (NSTableCellView *)editNumberCellViewWithTweak:(FBTweak *)tweak +{ + id value = [tweak defaultValue]; + + NSTableCellView *cellView = [[NSTableCellView alloc] initWithFrame:CGRectMake(0, 0, 100, 44)]; + + // In the 64-bit runtime, BOOL is a real boolean. + // NSNumber doesn't always agree; compare both. + if (strcmp([value objCType], @encode(char)) == 0 || + strcmp([value objCType], @encode(_Bool)) == 0) { + // boolean + NSButton *checkbox = [[NSButton alloc] initWithFrame:CGRectMake(0, 0, 16, 16)]; + [checkbox setButtonType:NSSwitchButton]; + [cellView addSubview:checkbox]; + [checkbox bind:@"value" toObject:tweak withKeyPath:@"currentValue" options:nil]; + + } else { + NSTextField *textField = [[NSTextField alloc] initWithFrame:cellView.bounds]; + textField.bordered = YES; + textField.editable = YES; + textField.autoresizingMask = NSViewHeightSizable|NSViewWidthSizable; + + NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init]; + formatter.numberStyle = NSNumberFormatterDecimalStyle; + if (strcmp([value objCType], @encode(NSInteger)) == 0 || + strcmp([value objCType], @encode(NSUInteger)) == 0) { + // integer + formatter.allowsFloats = NO; + } else { + // real + formatter.allowsFloats = YES; + } + + if (tweak.minimumValue != nil) { + formatter.minimum = tweak.minimumValue; + } + if (tweak.maximumValue != nil) { + formatter.maximum = tweak.maximumValue; + } + + textField.formatter = formatter; + [cellView addSubview:textField]; + cellView.textField = textField; + [textField bind:@"value" toObject:tweak withKeyPath:@"currentValue" options:nil]; + } + return cellView; +} + + +#pragma mark delegate + +- (BOOL)tableView:(NSTableView *)tableView isGroupRow:(NSInteger)row +{ + return [_flattenedTweaks[row] isKindOfClass:[FBTweakCollection class]]; +} + + + +@end diff --git a/FBTweakExample.xcodeproj/project.pbxproj b/FBTweakExample.xcodeproj/project.pbxproj index 691b6884..99516014 100644 --- a/FBTweakExample.xcodeproj/project.pbxproj +++ b/FBTweakExample.xcodeproj/project.pbxproj @@ -15,6 +15,11 @@ 18EFE4FC189F02F800DA6A5D /* FBAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 18EFE4FB189F02F800DA6A5D /* FBAppDelegate.m */; }; 18EFE4FE189F02F800DA6A5D /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 18EFE4FD189F02F800DA6A5D /* Images.xcassets */; }; 18EFE524189F04B000DA6A5D /* libFBTweak.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18EFE523189F04B000DA6A5D /* libFBTweak.a */; }; + 2731A2B11A3DA5CD003BFA2D /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 2731A2B01A3DA5CD003BFA2D /* AppDelegate.m */; }; + 2731A2B31A3DA5CD003BFA2D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 2731A2B21A3DA5CD003BFA2D /* main.m */; }; + 2731A2B51A3DA5CD003BFA2D /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2731A2B41A3DA5CD003BFA2D /* Images.xcassets */; }; + 2731A2CC1A3DA86E003BFA2D /* libFBTweakOSX.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2731A2CB1A3DA86E003BFA2D /* libFBTweakOSX.a */; }; + 2731A2CD1A3DA884003BFA2D /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2731A2B61A3DA5CD003BFA2D /* MainMenu.xib */; }; 29E9F17D18E35D2B001EAF7D /* MessageUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 29E9F17C18E35D2B001EAF7D /* MessageUI.framework */; }; /* End PBXBuildFile section */ @@ -32,6 +37,14 @@ 18EFE4FD189F02F800DA6A5D /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 18EFE504189F02F800DA6A5D /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; 18EFE523189F04B000DA6A5D /* libFBTweak.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libFBTweak.a; path = "../FBTweak/build/Debug-iphoneos/libFBTweak.a"; sourceTree = ""; }; + 2731A2AB1A3DA5CD003BFA2D /* FBTweakOSXExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = FBTweakOSXExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 2731A2AE1A3DA5CD003BFA2D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 2731A2AF1A3DA5CD003BFA2D /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 2731A2B01A3DA5CD003BFA2D /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 2731A2B21A3DA5CD003BFA2D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 2731A2B41A3DA5CD003BFA2D /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 2731A2B71A3DA5CD003BFA2D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; + 2731A2CB1A3DA86E003BFA2D /* libFBTweakOSX.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libFBTweakOSX.a; path = "../../Library/Developer/Xcode/DerivedData/FBTweakExample-cjwkgcrffjkgsjaicqbywmnmhjiq/Build/Products/Debug/libFBTweakOSX.a"; sourceTree = ""; }; 29E9F17C18E35D2B001EAF7D /* MessageUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MessageUI.framework; path = System/Library/Frameworks/MessageUI.framework; sourceTree = SDKROOT; }; /* End PBXFileReference section */ @@ -48,6 +61,14 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 2731A2A81A3DA5CD003BFA2D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 2731A2CC1A3DA86E003BFA2D /* libFBTweakOSX.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ @@ -55,6 +76,7 @@ isa = PBXGroup; children = ( 18EFE4F1189F02F800DA6A5D /* FBTweakExample */, + 2731A2AC1A3DA5CD003BFA2D /* FBTweakOSXExample */, 18EFE4EA189F02F800DA6A5D /* Frameworks */, 18EFE4E9189F02F800DA6A5D /* Products */, ); @@ -64,6 +86,7 @@ isa = PBXGroup; children = ( 18EFE4E8189F02F800DA6A5D /* FBTweakExample.app */, + 2731A2AB1A3DA5CD003BFA2D /* FBTweakOSXExample.app */, ); name = Products; sourceTree = ""; @@ -71,6 +94,7 @@ 18EFE4EA189F02F800DA6A5D /* Frameworks */ = { isa = PBXGroup; children = ( + 2731A2CB1A3DA86E003BFA2D /* libFBTweakOSX.a */, 29E9F17C18E35D2B001EAF7D /* MessageUI.framework */, 18EFE523189F04B000DA6A5D /* libFBTweak.a */, 18EFE4EB189F02F800DA6A5D /* Foundation.framework */, @@ -103,6 +127,27 @@ name = "Supporting Files"; sourceTree = ""; }; + 2731A2AC1A3DA5CD003BFA2D /* FBTweakOSXExample */ = { + isa = PBXGroup; + children = ( + 2731A2AF1A3DA5CD003BFA2D /* AppDelegate.h */, + 2731A2B01A3DA5CD003BFA2D /* AppDelegate.m */, + 2731A2B41A3DA5CD003BFA2D /* Images.xcassets */, + 2731A2B61A3DA5CD003BFA2D /* MainMenu.xib */, + 2731A2AD1A3DA5CD003BFA2D /* Supporting Files */, + ); + path = FBTweakOSXExample; + sourceTree = ""; + }; + 2731A2AD1A3DA5CD003BFA2D /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 2731A2AE1A3DA5CD003BFA2D /* Info.plist */, + 2731A2B21A3DA5CD003BFA2D /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -123,6 +168,23 @@ productReference = 18EFE4E8189F02F800DA6A5D /* FBTweakExample.app */; productType = "com.apple.product-type.application"; }; + 2731A2AA1A3DA5CD003BFA2D /* FBTweakOSXExample */ = { + isa = PBXNativeTarget; + buildConfigurationList = 2731A2C91A3DA5CE003BFA2D /* Build configuration list for PBXNativeTarget "FBTweakOSXExample" */; + buildPhases = ( + 2731A2A71A3DA5CD003BFA2D /* Sources */, + 2731A2A81A3DA5CD003BFA2D /* Frameworks */, + 2731A2A91A3DA5CD003BFA2D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = FBTweakOSXExample; + productName = FBTweakOSXExample; + productReference = 2731A2AB1A3DA5CD003BFA2D /* FBTweakOSXExample.app */; + productType = "com.apple.product-type.application"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ @@ -132,6 +194,11 @@ CLASSPREFIX = FB; LastUpgradeCheck = 0510; ORGANIZATIONNAME = Facebook; + TargetAttributes = { + 2731A2AA1A3DA5CD003BFA2D = { + CreatedOnToolsVersion = 6.1.1; + }; + }; }; buildConfigurationList = 18EFE4E3189F02F800DA6A5D /* Build configuration list for PBXProject "FBTweakExample" */; compatibilityVersion = "Xcode 3.2"; @@ -139,6 +206,7 @@ hasScannedForEncodings = 0; knownRegions = ( en, + Base, ); mainGroup = 18EFE4DF189F02F800DA6A5D; productRefGroup = 18EFE4E9189F02F800DA6A5D /* Products */; @@ -146,6 +214,7 @@ projectRoot = ""; targets = ( 18EFE4E7189F02F800DA6A5D /* FBTweakExample */, + 2731A2AA1A3DA5CD003BFA2D /* FBTweakOSXExample */, ); }; /* End PBXProject section */ @@ -160,6 +229,15 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 2731A2A91A3DA5CD003BFA2D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 2731A2B51A3DA5CD003BFA2D /* Images.xcassets in Resources */, + 2731A2CD1A3DA884003BFA2D /* MainMenu.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -172,6 +250,15 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 2731A2A71A3DA5CD003BFA2D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 2731A2B31A3DA5CD003BFA2D /* main.m in Sources */, + 2731A2B11A3DA5CD003BFA2D /* AppDelegate.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXSourcesBuildPhase section */ /* Begin PBXVariantGroup section */ @@ -183,6 +270,14 @@ name = InfoPlist.strings; sourceTree = ""; }; + 2731A2B61A3DA5CD003BFA2D /* MainMenu.xib */ = { + isa = PBXVariantGroup; + children = ( + 2731A2B71A3DA5CD003BFA2D /* Base */, + ); + name = MainMenu.xib; + sourceTree = ""; + }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ @@ -294,6 +389,55 @@ }; name = Release; }; + 2731A2C51A3DA5CE003BFA2D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_WARN_UNREACHABLE_CODE = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + INFOPLIST_FILE = FBTweakOSXExample/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(USER_LIBRARY_DIR)/Developer/Xcode/DerivedData/FBTweakExample-cjwkgcrffjkgsjaicqbywmnmhjiq/Build/Products/Debug", + ); + MACOSX_DEPLOYMENT_TARGET = 10.10; + MTL_ENABLE_DEBUG_INFO = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Debug; + }; + 2731A2C61A3DA5CE003BFA2D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_WARN_UNREACHABLE_CODE = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + INFOPLIST_FILE = FBTweakOSXExample/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(USER_LIBRARY_DIR)/Developer/Xcode/DerivedData/FBTweakExample-cjwkgcrffjkgsjaicqbywmnmhjiq/Build/Products/Debug", + ); + MACOSX_DEPLOYMENT_TARGET = 10.10; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -315,6 +459,14 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + 2731A2C91A3DA5CE003BFA2D /* Build configuration list for PBXNativeTarget "FBTweakOSXExample" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 2731A2C51A3DA5CE003BFA2D /* Debug */, + 2731A2C61A3DA5CE003BFA2D /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; /* End XCConfigurationList section */ }; rootObject = 18EFE4E0189F02F800DA6A5D /* Project object */; diff --git a/FBTweakOSXExample/AppDelegate.h b/FBTweakOSXExample/AppDelegate.h new file mode 100644 index 00000000..ab546b5a --- /dev/null +++ b/FBTweakOSXExample/AppDelegate.h @@ -0,0 +1,16 @@ +// +// AppDelegate.h +// FBTweakOSXExample +// +// Created by Paulo Andrade on 14/12/14. +// Copyright (c) 2014 Facebook. All rights reserved. +// + +#import + + +@interface AppDelegate : NSObject + + +@end + diff --git a/FBTweakOSXExample/AppDelegate.m b/FBTweakOSXExample/AppDelegate.m new file mode 100644 index 00000000..fc390119 --- /dev/null +++ b/FBTweakOSXExample/AppDelegate.m @@ -0,0 +1,79 @@ +// +// AppDelegate.m +// FBTweakOSXExample +// +// Created by Paulo Andrade on 14/12/14. +// Copyright (c) 2014 Facebook. All rights reserved. +// + +#import "AppDelegate.h" +#import +#import +#import + +@interface AppDelegate () + +@property (weak) IBOutlet NSWindow *window; +@property (weak) IBOutlet NSTextField *label; + +@property (strong) NSWindowController *tweaksWindowController; + +@end + +@implementation AppDelegate { + _FBTweakBindObserver *_observer; +} + +FBTweakAction(@"Actions", @"Global", @"Hello", ^{ + + NSAlert *alert = [[NSAlert alloc] init]; + alert.messageText = @"Hello"; + alert.informativeText = @"Global alert test."; + [alert runModal]; +}); + + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application + + FBTweakAction(@"Actions", @"Scoped", @"One", ^{ + NSAlert *alert = [[NSAlert alloc] init]; + alert.messageText = @"Hello"; + alert.informativeText = @"Scoped alert test #1."; + [alert runModal]; + }); + + FBTweakValue(@"Window", @"Teste", @"Bu", (NSInteger)1); + self.window.backgroundColor = [NSColor colorWithRed:FBTweakValue(@"Window", @"Color", @"Red", 0.9, 0.0, 1.0) + green:FBTweakValue(@"Window", @"Color", @"Green", 0.9, 0.0, 1.0) + blue:FBTweakValue(@"Window", @"Color", @"Blue", 0.9, 0.0, 1.0) + alpha:1.0]; + + FBTweakBind(_label, stringValue, @"Content", @"Label", @"String", @"Tweaks"); + FBTweakBind(_label, alphaValue, @"Content", @"Label", @"Alpha", 0.5, 0.0, 1.0); + _label.backgroundColor = [NSColor whiteColor]; + FBTweakBind(_label, drawsBackground, @"Content", @"Label", @"Background", NO); + + FBTweakAction(@"Actions", @"Scoped", @"Two", ^{ + NSAlert *alert = [[NSAlert alloc] init]; + alert.messageText = @"Hello"; + alert.informativeText = @"Scoped alert test #2."; + [alert runModal]; + }); +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + // Insert code here to tear down your application +} + +- (IBAction)openTweakWindow:(id)sender { + if (self.tweaksWindowController == nil) { + FBTweakEditorViewController *editor = [[FBTweakEditorViewController alloc] init]; + NSWindow *window = [NSWindow windowWithContentViewController:editor]; + self.tweaksWindowController = [[NSWindowController alloc] initWithWindow:window]; + } + + [self.tweaksWindowController showWindow:self]; +} + +@end diff --git a/FBTweakOSXExample/Base.lproj/MainMenu.xib b/FBTweakOSXExample/Base.lproj/MainMenu.xib new file mode 100644 index 00000000..deb0a89a --- /dev/null +++ b/FBTweakOSXExample/Base.lproj/MainMenu.xib @@ -0,0 +1,708 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FBTweakOSXExample/Images.xcassets/AppIcon.appiconset/Contents.json b/FBTweakOSXExample/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..2db2b1c7 --- /dev/null +++ b/FBTweakOSXExample/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,58 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/FBTweakOSXExample/Info.plist b/FBTweakOSXExample/Info.plist new file mode 100644 index 00000000..ab78ff07 --- /dev/null +++ b/FBTweakOSXExample/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + com.maracujja.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2014 Facebook. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/FBTweakOSXExample/main.m b/FBTweakOSXExample/main.m new file mode 100644 index 00000000..df8ced54 --- /dev/null +++ b/FBTweakOSXExample/main.m @@ -0,0 +1,13 @@ +// +// main.m +// FBTweakOSXExample +// +// Created by Paulo Andrade on 14/12/14. +// Copyright (c) 2014 Facebook. All rights reserved. +// + +#import + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +} diff --git a/README.md b/README.md index 1424d8ac..c9a1b5c7 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Tweaks -Tweaks is an easy way to fine-tune an iOS app. +Tweaks is an easy way to fine-tune an iOS or OS X app. ![Tweaks](https://github.com/facebook/Tweaks/blob/master/Images/Tweaks.gif?raw=true) From 35d7b625efdd64df92ecf40d8c3d3d437563c359 Mon Sep 17 00:00:00 2001 From: "Paulo F. Andrade" Date: Tue, 16 Dec 2014 17:08:00 +0000 Subject: [PATCH 2/2] Fixed bug when retrieving selected category in _FBTweakCategoriesViewController --- FBTweak/_FBTweakCategoriesViewController.m | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/FBTweak/_FBTweakCategoriesViewController.m b/FBTweak/_FBTweakCategoriesViewController.m index f47b0170..34ddbbc5 100644 --- a/FBTweak/_FBTweakCategoriesViewController.m +++ b/FBTweak/_FBTweakCategoriesViewController.m @@ -70,7 +70,10 @@ - (void)loadView - (FBTweakCategory *)selectedCategory { - return _sortedCategories[[self.outlineView selectedRow]]; + if ([self.outlineView selectedRow] >= 0) { + return _sortedCategories[[self.outlineView selectedRow]]; + } + return nil; } - (void)viewDidAppear