├── Screens ├── main.png ├── demo_map.gif ├── demo_address.gif └── demo_workspace.gif ├── XLocation ├── Resources │ └── Icon.png ├── XLWindow.h ├── XLocation-Prefix.pch ├── XLWindow.m ├── Xcode-Private-Classes │ ├── DVTDualProxyWindow.h │ ├── DVTSourceTextView.h │ ├── IDEWorkspaceWindow.h │ ├── IDEIndexCollection.h │ ├── IDEEditorDocument.h │ ├── DVTFilePath.h │ ├── IDEWorkspace.h │ └── IDEIndex.h ├── XLMapView.h ├── NSObject_Extension.h ├── Categories │ ├── NSString+Gpx.h │ └── NSString+Gpx.m ├── XLocation.h ├── Classes │ ├── XLWorkspace.h │ ├── XLAnnotation.h │ ├── XLAnnotation.m │ └── XLWorkspace.m ├── NSObject_Extension.m ├── XLWorkspaceView.h ├── Views │ ├── RMBlurredView.h │ └── RMBlurredView.m ├── XLMapView.m ├── Info.plist ├── XLWorkspaceView.m └── XLWindow.xib ├── Dependencies ├── OCLogTemplate │ ├── README │ └── OCLogTemplate.h └── XcodeEditor │ ├── XcodeEditor.h │ ├── XcodeGroupMember.h │ ├── XCAbstractDefinition.m │ ├── Utils │ ├── XCKeyBuilder.h │ └── XCKeyBuilder.m │ ├── XCFrameworkDefinition.h │ ├── XCXibDefinition.h │ ├── XcodeMemberType.h │ ├── XCSourceFileDefinition.h │ ├── XCBuildConfiguration.h │ ├── XcodeSourceFileType.h │ ├── XCFileOperationQueue.h │ ├── XCProject+SubProject.h │ ├── XCAbstractDefinition.h │ ├── XCClassDefinition.h │ ├── XCFrameworkDefinition.m │ ├── XCSubProjectDefinition.h │ ├── XCXibDefinition.m │ ├── XCSourceFile.h │ ├── XCSourceFileDefinition.m │ ├── XCTarget.h │ ├── XcodeSourceFileType.m │ ├── XCClassDefinition.m │ ├── XcodeMemberType.m │ ├── XCProject.h │ ├── XCGroup.h │ ├── XCFileOperationQueue.m │ ├── XCSubProjectDefinition.m │ ├── XCSourceFile.m │ ├── XCBuildConfiguration.m │ ├── XCProject.m │ ├── XCTarget.m │ ├── XCProject+SubProject.m │ └── XCGroup.m ├── XLocation.xcodeproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcshareddata │ └── xcschemes │ └── XLocation.xcscheme ├── .gitignore ├── LICENSE └── README.md /Screens/main.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StefanLage/XLocation/HEAD/Screens/main.png -------------------------------------------------------------------------------- /Screens/demo_map.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StefanLage/XLocation/HEAD/Screens/demo_map.gif -------------------------------------------------------------------------------- /Screens/demo_address.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StefanLage/XLocation/HEAD/Screens/demo_address.gif -------------------------------------------------------------------------------- /Screens/demo_workspace.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StefanLage/XLocation/HEAD/Screens/demo_workspace.gif -------------------------------------------------------------------------------- /XLocation/Resources/Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StefanLage/XLocation/HEAD/XLocation/Resources/Icon.png -------------------------------------------------------------------------------- /Dependencies/OCLogTemplate/README: -------------------------------------------------------------------------------- 1 | A logging framework for Objective-C projects. 2 | 3 | Based on Brenwill workshop's Flexible iOS Logging Framework: http://brenwill.com/2010/flexible-ios-logging/ 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /XLocation.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /XLocation/XLWindow.h: -------------------------------------------------------------------------------- 1 | // 2 | // LWindow.h 3 | // LXLocation 4 | // 5 | // Created by Stefan Lage on 16/05/14. 6 | // Copyright (c) 2014 Stefan Lage. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface XLWindow : NSWindow 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /XLocation/XLocation-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // XLocation-PRefix.pch 3 | // XLocation 4 | // 5 | // Created by Stefan Lage on 17/09/15. 6 | // Copyright (c) 2015 Stefan Lage. All rights reserved. 7 | // 8 | 9 | #ifdef __OBJC__ 10 | #import 11 | #endif 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | */build/* 3 | *.pbxuser 4 | !default.pbxuser 5 | *.mode1v3 6 | !default.mode1v3 7 | *.mode2v3 8 | !default.mode2v3 9 | *.perspectivev3 10 | !default.perspectivev3 11 | xcuserdata 12 | *.moved-aside 13 | DerivedData 14 | .idea/ 15 | *.hmap 16 | *.xccheckout 17 | -------------------------------------------------------------------------------- /XLocation/XLWindow.m: -------------------------------------------------------------------------------- 1 | // 2 | // LWindow.m 3 | // LXLocation 4 | // 5 | // Created by Stefan Lage on 16/05/14. 6 | // Copyright (c) 2014 Stefan Lage. All rights reserved. 7 | // 8 | 9 | #import "XLWindow.h" 10 | 11 | @implementation XLWindow 12 | 13 | - (BOOL)canBecomeKeyWindow { 14 | return YES; 15 | } 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /XLocation/Xcode-Private-Classes/DVTDualProxyWindow.h: -------------------------------------------------------------------------------- 1 | // 2 | // DVTDualProxyWindow.h 3 | // LXLocation 4 | // 5 | // Created by Stefan Lage on 16/05/14. 6 | // Copyright (c) 2014 Stefan Lage. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface DVTDualProxyWindow : NSWindow 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /XLocation/Xcode-Private-Classes/DVTSourceTextView.h: -------------------------------------------------------------------------------- 1 | // 2 | // DVTSourceTextView.h 3 | // LXLocation 4 | // 5 | // Created by Stefan Lage on 16/05/14. 6 | // Copyright (c) 2014 Stefan Lage. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface DVTSourceTextView : NSTextView 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /XLocation/Xcode-Private-Classes/IDEWorkspaceWindow.h: -------------------------------------------------------------------------------- 1 | // 2 | // IDEWorkspaceWindow.h 3 | // LXLocation 4 | // 5 | // Created by Stefan Lage on 16/05/14. 6 | // Copyright (c) 2014 Stefan Lage. All rights reserved. 7 | // 8 | 9 | #import "DVTDualProxyWindow.h" 10 | 11 | @interface IDEWorkspaceWindow : DVTDualProxyWindow 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /XLocation/XLMapView.h: -------------------------------------------------------------------------------- 1 | // 2 | // LMapView.h 3 | // XLocation 4 | // 5 | // Created by Stefan Lage on 17/05/14. 6 | // Copyright (c) 2014 StefanLage. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface XLMapView : MKMapView 12 | 13 | @property (nonatomic) BOOL isEnable; 14 | -(void)resetRegion; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /XLocation/Xcode-Private-Classes/IDEIndexCollection.h: -------------------------------------------------------------------------------- 1 | // 2 | // IDEIndexCollection.h 3 | // LXLocation 4 | // 5 | // Created by Stefan Lage on 16/05/14. 6 | // Copyright (c) 2014 Stefan Lage. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface IDEIndexCollection : NSObject 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /XLocation/NSObject_Extension.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject_Extension.h 3 | // XLocation 4 | // 5 | // Created by Stefan Lage on 17/09/15. 6 | // Copyright (c) 2015 Stefan Lage. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSObject (Xcode_Plugin_Template_Extension) 12 | 13 | + (void)pluginDidLoad:(NSBundle *)plugin; 14 | 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /XLocation/Xcode-Private-Classes/IDEEditorDocument.h: -------------------------------------------------------------------------------- 1 | // 2 | // IDEEditorDocument.h 3 | // LXLocation 4 | // 5 | // Created by Stefan Lage on 16/05/14. 6 | // Copyright (c) 2014 Stefan Lage. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class DVTFilePath; 12 | 13 | @interface IDEEditorDocument : NSDocument 14 | 15 | @property (retain) DVTFilePath *filePath; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /XLocation/Xcode-Private-Classes/DVTFilePath.h: -------------------------------------------------------------------------------- 1 | // 2 | // DVTFilePath.h 3 | // LXLocation 4 | // 5 | // Created by Stefan Lage on 16/05/14. 6 | // Copyright (c) 2014 Stefan Lage. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface DVTFilePath : NSObject 12 | 13 | @property (readonly) NSString *fileName; 14 | @property (readonly) NSURL *fileURL; 15 | @property (readonly) NSArray *pathComponents; 16 | @property (readonly) NSString *pathString; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /XLocation/Categories/NSString+Gpx.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+Gpx.h 3 | // XLocation 4 | // 5 | // Created by Stefan Lage on 16/05/14. 6 | // Copyright (c) 2014 StefanLage. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSString (Gpx) 12 | 13 | + (NSString *)generateGpxWithFilename:(NSString*) filename latitude:(NSNumber *)lat longitude:(NSNumber *)lng address:(NSString*)address city:(NSString*)city country:(NSString*)country zip:(NSString*)zipCode; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /XLocation/Xcode-Private-Classes/IDEWorkspace.h: -------------------------------------------------------------------------------- 1 | // 2 | // IDEWorkspace.h 3 | // LXLocation 4 | // 5 | // Created by Stefan Lage on 16/05/14. 6 | // Copyright (c) 2014 Stefan Lage. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class IDEIndex; 12 | @class DVTFilePath; 13 | 14 | @interface IDEWorkspace : NSObject 15 | 16 | @property (retain) IDEIndex *index; 17 | @property (readonly) DVTFilePath *representingFilePath; 18 | 19 | - (void)_updateIndexableFiles:(id)arg1; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /XLocation/Xcode-Private-Classes/IDEIndex.h: -------------------------------------------------------------------------------- 1 | // 2 | // IDEIndex.h 3 | // Lin 4 | // 5 | // Created by Tanaka Katsuma on 2013/08/23. 6 | // Copyright (c) 2013年 Tanaka Katsuma. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class DVTFilePath; 12 | 13 | @interface IDEIndex : NSObject 14 | 15 | @property (readonly, nonatomic) DVTFilePath *workspaceFile; 16 | @property (readonly, nonatomic) NSString *workspaceName; 17 | 18 | - (void)close; 19 | - (id)filesContaining:(id)arg1 anchorStart:(BOOL)arg2 anchorEnd:(BOOL)arg3 subsequence:(BOOL)arg4 ignoreCase:(BOOL)arg5 cancelWhen:(id)arg6; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /XLocation/XLocation.h: -------------------------------------------------------------------------------- 1 | // 2 | // XLocation.h 3 | // XLocation 4 | // 5 | // Created by Stefan Lage on 17/09/15. 6 | // Copyright (c) 2015 Stefan Lage. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "XLWorkspaceView.h" 11 | 12 | @class XLocation; 13 | 14 | static XLocation *sharedPlugin; 15 | 16 | @interface XLocation : NSObject 17 | 18 | @property (nonatomic, strong, readonly) NSBundle* bundle; 19 | 20 | + (instancetype)sharedPlugin; 21 | - (id)initWithBundle:(NSBundle *)plugin; 22 | - (IBAction)cancel:(id)sender; 23 | - (IBAction)generateFromMap:(id)sender; 24 | - (IBAction)generateFromAddress:(id)sender; 25 | 26 | @end -------------------------------------------------------------------------------- /XLocation/Classes/XLWorkspace.h: -------------------------------------------------------------------------------- 1 | // 2 | // LWorkspace.h 3 | // XLocation 4 | // 5 | // Created by Stefan Lage on 10/06/14. 6 | // Copyright (c) 2014 StefanLage. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface XLWorkspace : NSObject 12 | 13 | // Get all projects contains in a workspace 14 | // 15 | // Dictionnary : 16 | // name: projectName 17 | // filename: filename.extension 18 | // location : path to the project 19 | // 20 | @property (strong, nonatomic) NSMutableArray *projects; 21 | @property (strong, nonatomic) NSString *currentWorkspacePath; 22 | 23 | -(id)initWithUrl:(NSString*)url currentPath:(NSString*)path; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /XLocation/NSObject_Extension.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject_Extension.m 3 | // XLocation 4 | // 5 | // Created by Stefan Lage on 17/09/15. 6 | // Copyright (c) 2015 Stefan Lage. All rights reserved. 7 | // 8 | 9 | 10 | #import "NSObject_Extension.h" 11 | #import "XLocation.h" 12 | 13 | @implementation NSObject (Xcode_Plugin_Template_Extension) 14 | 15 | + (void)pluginDidLoad:(NSBundle *)plugin 16 | { 17 | static dispatch_once_t onceToken; 18 | NSString *currentApplicationName = [[NSBundle mainBundle] infoDictionary][@"CFBundleName"]; 19 | if ([currentApplicationName isEqual:@"Xcode"]) { 20 | dispatch_once(&onceToken, ^{ 21 | sharedPlugin = [[XLocation alloc] initWithBundle:plugin]; 22 | }); 23 | } 24 | } 25 | @end 26 | -------------------------------------------------------------------------------- /Dependencies/XcodeEditor/XcodeEditor.h: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // JASPER BLUES 4 | // Copyright 2012 Jasper Blues 5 | // All Rights Reserved. 6 | // 7 | // NOTICE: Jasper Blues permits you to use, modify, and distribute this file 8 | // in accordance with the terms of the license agreement accompanying it. 9 | // 10 | //////////////////////////////////////////////////////////////////////////////// 11 | 12 | 13 | #import "XCAbstractDefinition.h" 14 | #import "XCGroup.h" 15 | #import "XCClassDefinition.h" 16 | #import "XCFileOperationQueue.h" 17 | #import "XCFrameworkDefinition.h" 18 | #import "XCProject.h" 19 | #import "XCSourceFile.h" 20 | #import "XCSourceFileDefinition.h" 21 | #import "XCSubProjectDefinition.h" 22 | #import "XCTarget.h" 23 | #import "XCXibDefinition.h" 24 | -------------------------------------------------------------------------------- /Dependencies/XcodeEditor/XcodeGroupMember.h: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // JASPER BLUES 4 | // Copyright 2012 Jasper Blues 5 | // All Rights Reserved. 6 | // 7 | // NOTICE: Jasper Blues permits you to use, modify, and distribute this file 8 | // in accordance with the terms of the license agreement accompanying it. 9 | // 10 | //////////////////////////////////////////////////////////////////////////////// 11 | 12 | 13 | 14 | #import "XcodeMemberType.h" 15 | 16 | @protocol XcodeGroupMember 17 | 18 | - (NSString*)key; 19 | 20 | - (NSString*)displayName; 21 | 22 | - (NSString*)pathRelativeToProjectRoot; 23 | 24 | /** 25 | * Group members can either be other groups (PBXGroup) or source files (PBXFileReference). 26 | */ 27 | - (XcodeMemberType)groupMemberType; 28 | @end -------------------------------------------------------------------------------- /XLocation/Classes/XLAnnotation.h: -------------------------------------------------------------------------------- 1 | // 2 | // LAnnotation.h 3 | // XLocation 4 | // 5 | // Created by Stefan Lage on 17/05/14. 6 | // Copyright (c) 2014 StefanLage. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface XLAnnotation : NSObject 13 | 14 | @property (nonatomic, strong) NSString * city; 15 | @property (nonatomic, strong) NSString * country; 16 | @property (nonatomic, strong) NSString * address; 17 | @property (nonatomic, strong) NSString * zipCode; 18 | @property (nonatomic, strong) MKPointAnnotation * annotation; 19 | 20 | // Custom constructor 21 | -(id)initWithCity:(NSString*)ci country:(NSString*)co address:(NSString*)ad zipCode:(NSString*)zip location:(CLLocationCoordinate2D)loc; 22 | -(NSString*)concatAddress; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /XLocation/XLWorkspaceView.h: -------------------------------------------------------------------------------- 1 | // 2 | // LWorskpaceController.h 3 | // XLocation 4 | // 5 | // Created by Stefan Lage on 10/06/14. 6 | // Copyright (c) 2014 StefanLage. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "XLWorkspace.h" 11 | #import "RMBlurredView.h" 12 | 13 | 14 | @class XLWorkspaceView; 15 | 16 | @protocol XLWorskpaceViewDelegate 17 | 18 | -(void)goBack:(XLWorkspaceView *)view; 19 | -(void)projectSelected:(XLWorkspaceView *)view index:(NSInteger)index; 20 | 21 | @end 22 | 23 | @interface XLWorkspaceView : RMBlurredView 24 | 25 | @property (nonatomic, weak) id delegate; 26 | @property (nonatomic, strong) XLWorkspace *currentWorkspace; 27 | @property (nonatomic, strong) NSButton *continueBtn; 28 | 29 | - (id)initWithFrame:(NSRect)frame workspace:(XLWorkspace*)workspace; 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /Dependencies/XcodeEditor/XCAbstractDefinition.m: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // JASPER BLUES 4 | // Copyright 2012 - 2013 Jasper Blues 5 | // All Rights Reserved. 6 | // 7 | // NOTICE: Jasper Blues permits you to use, modify, and distribute this file 8 | // in accordance with the terms of the license agreement accompanying it. 9 | // 10 | //////////////////////////////////////////////////////////////////////////////// 11 | 12 | 13 | #import "XCAbstractDefinition.h" 14 | 15 | 16 | @implementation XCAbstractDefinition 17 | 18 | @synthesize fileOperationType = _fileOperationType; 19 | 20 | 21 | /* ====================================================================================================================================== */ 22 | #pragma mark - Initialization & Destruction 23 | 24 | - (id)init 25 | { 26 | self = [super init]; 27 | if (self) 28 | { 29 | _fileOperationType = XCFileOperationTypeOverwrite; 30 | } 31 | return self; 32 | } 33 | 34 | 35 | @end -------------------------------------------------------------------------------- /Dependencies/XcodeEditor/Utils/XCKeyBuilder.h: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // JASPER BLUES 4 | // Copyright 2012 - 2013 Jasper Blues 5 | // All Rights Reserved. 6 | // 7 | // NOTICE: Jasper Blues permits you to use, modify, and distribute this file 8 | // in accordance with the terms of the license agreement accompanying it. 9 | // 10 | //////////////////////////////////////////////////////////////////////////////// 11 | 12 | 13 | #import 14 | #import 15 | 16 | #define HASH_VALUE_STORAGE_SIZE 48 17 | 18 | typedef struct 19 | { 20 | char value[CC_MD5_DIGEST_LENGTH]; 21 | } HashValueMD5Hash; 22 | 23 | 24 | @interface XCKeyBuilder : NSObject 25 | { 26 | unsigned char _value[HASH_VALUE_STORAGE_SIZE]; 27 | } 28 | 29 | + (XCKeyBuilder*)forItemNamed:(NSString*)name; 30 | 31 | + (XCKeyBuilder*)createUnique; 32 | 33 | - (id)initHashValueMD5HashWithBytes:(const void*)bytes length:(NSUInteger)length; 34 | 35 | - (NSString*)build; 36 | 37 | @end 38 | 39 | -------------------------------------------------------------------------------- /Dependencies/XcodeEditor/XCFrameworkDefinition.h: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // JASPER BLUES 4 | // Copyright 2012 Jasper Blues 5 | // All Rights Reserved. 6 | // 7 | // NOTICE: Jasper Blues permits you to use, modify, and distribute this file 8 | // in accordance with the terms of the license agreement accompanying it. 9 | // 10 | //////////////////////////////////////////////////////////////////////////////// 11 | 12 | 13 | 14 | #import 15 | #import "XCAbstractDefinition.h" 16 | 17 | 18 | @interface XCFrameworkDefinition : XCAbstractDefinition 19 | { 20 | NSString* _filePath; 21 | BOOL _copyToDestination; 22 | } 23 | 24 | @property(nonatomic, strong, readonly) NSString* filePath; 25 | @property(nonatomic, readonly) BOOL copyToDestination; 26 | 27 | + (XCFrameworkDefinition*)frameworkDefinitionWithFilePath:(NSString*)filePath copyToDestination:(BOOL)copyToDestination; 28 | 29 | - (id)initWithFilePath:(NSString*)filePath copyToDestination:(BOOL)copyToDestination; 30 | 31 | - (NSString*)name; 32 | 33 | 34 | @end -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 Stefan Lage 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /Dependencies/XcodeEditor/XCXibDefinition.h: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // JASPER BLUES 4 | // Copyright 2012 Jasper Blues 5 | // All Rights Reserved. 6 | // 7 | // NOTICE: Jasper Blues permits you to use, modify, and distribute this file 8 | // in accordance with the terms of the license agreement accompanying it. 9 | // 10 | //////////////////////////////////////////////////////////////////////////////// 11 | 12 | 13 | 14 | #import 15 | #import "XCAbstractDefinition.h" 16 | 17 | 18 | @interface XCXibDefinition : XCAbstractDefinition 19 | { 20 | NSString* _name; 21 | NSString* _content; 22 | } 23 | @property(nonatomic, strong, readonly) NSString* name; 24 | @property(nonatomic, strong) NSString* content; 25 | 26 | + (XCXibDefinition*)xibDefinitionWithName:(NSString*)name; 27 | 28 | + (XCXibDefinition*)xibDefinitionWithName:(NSString*)name content:(NSString*)content; 29 | 30 | - (id)initWithName:(NSString*)name; 31 | 32 | - (id)initWithName:(NSString*)name content:(NSString*)content; 33 | 34 | - (NSString*)xibFileName; 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /Dependencies/XcodeEditor/XcodeMemberType.h: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // JASPER BLUES 4 | // Copyright 2012 Jasper Blues 5 | // All Rights Reserved. 6 | // 7 | // NOTICE: Jasper Blues permits you to use, modify, and distribute this file 8 | // in accordance with the terms of the license agreement accompanying it. 9 | // 10 | //////////////////////////////////////////////////////////////////////////////// 11 | 12 | 13 | 14 | typedef enum 15 | { 16 | PBXNilType, 17 | PBXBuildFileType, 18 | PBXContainerItemProxyType, 19 | PBXCopyFilesBuildPhaseType, 20 | PBXFileReferenceType, 21 | PBXFrameworksBuildPhaseType, 22 | PBXGroupType, 23 | PBXNativeTargetType, 24 | PBXProjectType, 25 | PBXReferenceProxyType, 26 | PBXResourcesBuildPhaseType, 27 | PBXSourcesBuildPhaseType, 28 | PBXTargetDependencyType, 29 | PBXVariantGroupType, 30 | XCBuildConfigurationType, 31 | XCConfigurationListType 32 | } XcodeMemberType; 33 | 34 | @interface NSString (XcodeMemberTypeExtensions) 35 | 36 | + (NSString*)stringFromMemberType:(XcodeMemberType)nodeType; 37 | 38 | - (XcodeMemberType)asMemberType; 39 | 40 | @end 41 | 42 | 43 | -------------------------------------------------------------------------------- /XLocation/Views/RMBlurredView.h: -------------------------------------------------------------------------------- 1 | // 2 | // RMBlurredView.h 3 | // 4 | // Created by Raffael Hannemann on 08.10.13. 5 | // Copyright (c) 2013 Raffael Hannemann. All rights reserved. 6 | // 7 | 8 | #import 9 | 10 | // Make sure to import QuartzCore and add it to your Linked Libraries of your target 11 | #import 12 | 13 | @interface RMBlurredView : NSView { 14 | // Keep a reference to the filters for later modification 15 | CIFilter *_blurFilter, *_saturationFilter; 16 | CALayer *_hostedLayer; 17 | } 18 | 19 | /** The layer will be tinted using the tint color. By default it is a 70% White Color */ 20 | @property (strong,nonatomic) NSColor *tintColor; 21 | 22 | /** To get more vibrant colors, a filter to increase the saturation of the colors can be applied. The default value is 2.5. */ 23 | @property (assign,nonatomic) float saturationFactor; 24 | 25 | /** The blur radius defines the strength of the Gaussian Blur filter. The default value is 20.0. */ 26 | @property (assign,nonatomic) float blurRadius; 27 | 28 | /** Use the following property names in the User Defined Runtime Attributes in Interface Builder to set up your RMBlurredView on the fly. Note: The color can be set up, too, using 'tintColor'. */ 29 | @property (strong,nonatomic) NSNumber *saturationFactorNumber; 30 | @property (strong,nonatomic) NSNumber *blurRadiusNumber; 31 | 32 | @end -------------------------------------------------------------------------------- /Dependencies/XcodeEditor/XCSourceFileDefinition.h: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // JASPER BLUES 4 | // Copyright 2012 Jasper Blues 5 | // All Rights Reserved. 6 | // 7 | // NOTICE: Jasper Blues permits you to use, modify, and distribute this file 8 | // in accordance with the terms of the license agreement accompanying it. 9 | // 10 | //////////////////////////////////////////////////////////////////////////////// 11 | 12 | 13 | 14 | #import 15 | #import "XCAbstractDefinition.h" 16 | #import "XcodeSourceFileType.h" 17 | 18 | @interface XCSourceFileDefinition : XCAbstractDefinition 19 | { 20 | 21 | NSString* _sourceFileName; 22 | XcodeSourceFileType _type; 23 | NSData* _data; 24 | 25 | } 26 | 27 | @property(nonatomic, strong, readonly) NSString* sourceFileName; 28 | @property(nonatomic, strong, readonly) NSData* data; 29 | @property(nonatomic, readonly) XcodeSourceFileType type; 30 | 31 | + (XCSourceFileDefinition*)sourceDefinitionWithName:(NSString*)name text:(NSString*)text type:(XcodeSourceFileType)type; 32 | 33 | + (XCSourceFileDefinition*)sourceDefinitionWithName:(NSString*)name data:(NSData*)data type:(XcodeSourceFileType)type; 34 | 35 | - (id)initWithName:(NSString*)name text:(NSString*)text type:(XcodeSourceFileType)type; 36 | 37 | - (id)initWithName:(NSString*)name data:(NSData*)data type:(XcodeSourceFileType)type; 38 | 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /Dependencies/XcodeEditor/XCBuildConfiguration.h: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // JASPER BLUES 4 | // Copyright 2012 Jasper Blues 5 | // All Rights Reserved. 6 | // 7 | // NOTICE: Jasper Blues permits you to use, modify, and distribute this file 8 | // in accordance with the terms of the license agreement accompanying it. 9 | // 10 | //////////////////////////////////////////////////////////////////////////////// 11 | 12 | 13 | 14 | @class XCProject; 15 | 16 | @interface XCBuildConfiguration : NSObject 17 | { 18 | @private 19 | __weak XCProject* _project; 20 | NSString* _key; 21 | 22 | NSMutableDictionary* _buildSettings; 23 | NSMutableDictionary* _xcconfigSettings; 24 | } 25 | 26 | @property(nonatomic, readonly) NSDictionary* specifiedBuildSettings; 27 | 28 | + (NSDictionary*)buildConfigurationsFromArray:(NSArray*)array inProject:(XCProject*)project; 29 | 30 | - (instancetype)initWithProject:(XCProject*)project key:(NSString*)key; 31 | 32 | - (void)addBuildSettings:(NSDictionary*)buildSettings; 33 | 34 | - (void)addOrReplaceSetting:(id )setting forKey:(NSString*)key; 35 | 36 | - (id )valueForKey:(NSString*)key; 37 | 38 | + (NSString*)duplicatedBuildConfigurationListWithKey:(NSString*)buildConfigurationListKey inProject:(XCProject*)project 39 | withBuildConfigurationVisitor:(void (^)(NSMutableDictionary*))buildConfigurationVisitor; 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /Dependencies/XcodeEditor/XcodeSourceFileType.h: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // JASPER BLUES 4 | // Copyright 2012 Jasper Blues 5 | // All Rights Reserved. 6 | // 7 | // NOTICE: Jasper Blues permits you to use, modify, and distribute this file 8 | // in accordance with the terms of the license agreement accompanying it. 9 | // 10 | //////////////////////////////////////////////////////////////////////////////// 11 | 12 | 13 | 14 | typedef enum 15 | { 16 | FileTypeNil, // Unknown filetype 17 | Framework, // .framework 18 | PropertyList, // .plist 19 | SourceCodeHeader, // .h 20 | SourceCodeObjC, // .m 21 | SourceCodeObjCPlusPlus, // .mm 22 | SourceCodeCPlusPlus, // .cpp 23 | XibFile, // .xib 24 | ImageResourcePNG, // .png 25 | Bundle, // .bundle .octet 26 | Archive, // .a files 27 | HTML, // HTML file 28 | TEXT, // Some text file 29 | GPX, // GPX file 30 | XcodeProject // .xcodeproj 31 | } XcodeSourceFileType; 32 | 33 | NSString* NSStringFromXCSourceFileType(XcodeSourceFileType type); 34 | 35 | XcodeSourceFileType XCSourceFileTypeFromStringRepresentation(NSString* string); 36 | 37 | XcodeSourceFileType XCSourceFileTypeFromFileName(NSString* fileName); 38 | 39 | -------------------------------------------------------------------------------- /Dependencies/XcodeEditor/XCFileOperationQueue.h: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // JASPER BLUES 4 | // Copyright 2012 Jasper Blues 5 | // All Rights Reserved. 6 | // 7 | // NOTICE: Jasper Blues permits you to use, modify, and distribute this file 8 | // in accordance with the terms of the license agreement accompanying it. 9 | // 10 | //////////////////////////////////////////////////////////////////////////////// 11 | 12 | 13 | #import 14 | 15 | 16 | @interface XCFileOperationQueue : NSObject 17 | { 18 | 19 | @private 20 | NSString* _baseDirectory; 21 | NSMutableDictionary* _filesToWrite; 22 | NSMutableDictionary* _frameworksToCopy; 23 | NSMutableArray* _filesToDelete; 24 | NSMutableArray* _directoriesToCreate; 25 | } 26 | 27 | 28 | - (id)initWithBaseDirectory:(NSString*)baseDirectory; 29 | 30 | - (BOOL)fileWithName:(NSString*)name existsInProjectDirectory:(NSString*)directory; 31 | 32 | - (void)queueTextFile:(NSString*)fileName inDirectory:(NSString*)directory withContents:(NSString*)contents; 33 | 34 | - (void)queueDataFile:(NSString*)fileName inDirectory:(NSString*)directory withContents:(NSData*)contents; 35 | 36 | - (void)queueFrameworkWithFilePath:(NSString*)filePath inDirectory:(NSString*)directory; 37 | 38 | - (void)queueDeletion:(NSString*)filePath; 39 | 40 | - (void)queueDirectory:(NSString*)withName inDirectory:(NSString*)parentDirectory; 41 | 42 | - (void)commitFileOperations; 43 | 44 | @end 45 | 46 | -------------------------------------------------------------------------------- /Dependencies/XcodeEditor/XCProject+SubProject.h: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // JASPER BLUES 4 | // Copyright 2012 Jasper Blues 5 | // All Rights Reserved. 6 | // 7 | // NOTICE: Jasper Blues permits you to use, modify, and distribute this file 8 | // in accordance with the terms of the license agreement accompanying it. 9 | // 10 | //////////////////////////////////////////////////////////////////////////////// 11 | 12 | 13 | 14 | #import 15 | #import "XCProject.h" 16 | 17 | @interface XCProject (SubProject) 18 | 19 | 20 | - (NSString*)referenceProxyKeyForName:(NSString*)name; 21 | 22 | - (NSArray*)buildProductsForTargets:(NSString*)xcodeprojKey; 23 | 24 | - (void)addAsTargetDependency:(XCSubProjectDefinition*)xcodeprojDefinition toTargets:(NSArray*)targets; 25 | 26 | - (NSArray*)keysForProjectObjectsOfType:(XcodeMemberType)memberType withIdentifier:(NSString*)identifier singleton:(BOOL)singleton 27 | required:(BOOL)required; 28 | 29 | - (NSMutableDictionary*)PBXProjectDict; 30 | 31 | - (void)removeProxies:(NSString*)xcodeprojKey; 32 | 33 | - (void)addProxies:(XCSubProjectDefinition*)xcodeproj; 34 | 35 | - (void)removeFromProjectReferences:(NSString*)key forProductsGroup:(NSString*)productsGroupKey; 36 | 37 | - (void)removeTargetDependencies:(NSString*)name; 38 | 39 | - (NSString*)containerItemProxyKeyForName:(NSString*)name proxyType:(NSString*)proxyType; 40 | 41 | - (NSString*)productsGroupKeyForKey:(NSString*)key; 42 | 43 | @end -------------------------------------------------------------------------------- /XLocation/XLMapView.m: -------------------------------------------------------------------------------- 1 | // 2 | // LMapView.m 3 | // XLocation 4 | // 5 | // Created by Stefan Lage on 17/05/14. 6 | // Copyright (c) 2014 StefanLage. All rights reserved. 7 | // 8 | 9 | #import "XLMapView.h" 10 | 11 | @interface XLMapView () 12 | 13 | @property (nonatomic) MKCoordinateRegion bkRegion; 14 | 15 | @end 16 | 17 | @implementation XLMapView 18 | 19 | -(id)initWithCoder:(NSCoder *)aDecoder{ 20 | self = [super initWithCoder:aDecoder]; 21 | if(self){ 22 | _bkRegion = self.region; 23 | _isEnable = YES; 24 | } 25 | return self; 26 | } 27 | 28 | /* 29 | * Handle right click on the map 30 | */ 31 | - (void) rightMouseDown:(NSEvent*) event{ 32 | // Get point in the current main Window 33 | NSPoint selfPoint = [self convertPoint:event.locationInWindow fromView:nil]; 34 | // Adapt it to the mapView 35 | CLLocationCoordinate2D locCoord = [self convertPoint:selfPoint toCoordinateFromView:self]; 36 | CLLocation *loc = [[CLLocation alloc] initWithLatitude:locCoord.latitude longitude:locCoord.longitude]; 37 | // Broadcast the location to find 38 | [[NSNotificationCenter defaultCenter] postNotificationName:@"findLocationFromPointNotification" 39 | object:loc]; 40 | } 41 | 42 | -(void)resetRegion{ 43 | self.region = self.bkRegion; 44 | } 45 | 46 | -(NSView*)hitTest:(NSPoint)aPoint{ 47 | if(self.isEnable) 48 | return [super hitTest:aPoint]; 49 | else 50 | return nil; 51 | } 52 | 53 | @end 54 | -------------------------------------------------------------------------------- /Dependencies/XcodeEditor/XCAbstractDefinition.h: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // JASPER BLUES 4 | // Copyright 2012 - 2013 Jasper Blues 5 | // All Rights Reserved. 6 | // 7 | // NOTICE: Jasper Blues permits you to use, modify, and distribute this file 8 | // in accordance with the terms of the license agreement accompanying it. 9 | // 10 | //////////////////////////////////////////////////////////////////////////////// 11 | 12 | 13 | #import 14 | 15 | typedef enum 16 | { 17 | 18 | /** 19 | * Creates the reference in the project and writes the contents to disk. If a file already exists at the specified 20 | * location, its contents will be updated. 21 | */ 22 | XCFileOperationTypeOverwrite, 23 | 24 | /** 25 | * Creates the reference in the project. If a file already exists at the specified location, the contents will not 26 | * be updated. 27 | */ 28 | XCFileOperationTypeAcceptExisting, 29 | 30 | /** 31 | * Creates the reference in the project, but does not write to disk. The filesystem is expected to be updated 32 | * through some other means. 33 | */ 34 | XCFileOperationTypeReferenceOnly 35 | } XCFileOperationType; 36 | 37 | /** 38 | * Holds properties to all types of resource that can be added to an Xcode project. 39 | */ 40 | @interface XCAbstractDefinition : NSObject 41 | { 42 | XCFileOperationType _fileOperationType; 43 | } 44 | 45 | @property(nonatomic) XCFileOperationType fileOperationType; 46 | 47 | 48 | @end -------------------------------------------------------------------------------- /XLocation/Classes/XLAnnotation.m: -------------------------------------------------------------------------------- 1 | // 2 | // LAnnotation.m 3 | // XLocation 4 | // 5 | // Created by Stefan Lage on 17/05/14. 6 | // Copyright (c) 2014 StefanLage. All rights reserved. 7 | // 8 | 9 | #import "XLAnnotation.h" 10 | 11 | @implementation XLAnnotation 12 | 13 | -(id)initWithCity:(NSString*)ci country:(NSString*)co address:(NSString*)ad zipCode:(NSString*)zip location:(CLLocationCoordinate2D)loc{ 14 | self = [super init]; 15 | if(self){ 16 | _city = ci; 17 | _country = co; 18 | _address = ad; 19 | _zipCode = zip; 20 | _annotation = [[MKPointAnnotation alloc] init]; 21 | _annotation.coordinate = loc; 22 | _annotation.title = [NSString stringWithFormat:@"%@\n%@", _city, _country]; 23 | } 24 | return self; 25 | } 26 | 27 | /* 28 | * Concat all properties to get a complete address 29 | */ 30 | -(NSString*)concatAddress{ 31 | NSMutableString *result = [[NSMutableString alloc] init]; 32 | if(![self.address isEqualToString:@""]) 33 | [result appendString:[NSString stringWithFormat:@"%@, ", self.address]]; 34 | if(![self.zipCode isEqualToString:@""]) 35 | [result appendString:[NSString stringWithFormat:@"%@, ", self.zipCode]]; 36 | if(![self.city isEqualToString:@""]) 37 | [result appendString:[NSString stringWithFormat:@"%@, ", self.city]]; 38 | if(![self.country isEqualToString:@""]) 39 | [result appendString:[NSString stringWithFormat:@"%@", self.country]]; 40 | return result; 41 | } 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /Dependencies/XcodeEditor/XCClassDefinition.h: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // JASPER BLUES 4 | // Copyright 2012 - 2013 Jasper Blues 5 | // All Rights Reserved. 6 | // 7 | // NOTICE: Jasper Blues permits you to use, modify, and distribute this file 8 | // in accordance with the terms of the license agreement accompanying it. 9 | // 10 | //////////////////////////////////////////////////////////////////////////////// 11 | 12 | 13 | #import 14 | #import "XCAbstractDefinition.h" 15 | 16 | typedef enum 17 | { 18 | ObjectiveC, 19 | ObjectiveCPlusPlus, 20 | CPlusPlus, 21 | } ClassDefinitionLanguage; 22 | 23 | @interface XCClassDefinition : XCAbstractDefinition 24 | { 25 | 26 | NSString* _className; 27 | NSString* _header; 28 | NSString* _source; 29 | 30 | @private 31 | ClassDefinitionLanguage _language; 32 | } 33 | 34 | @property(strong, nonatomic, readonly) NSString* className; 35 | @property(nonatomic, strong) NSString* header; 36 | @property(nonatomic, strong) NSString* source; 37 | 38 | + (XCClassDefinition*)classDefinitionWithName:(NSString*)fileName; 39 | 40 | + (XCClassDefinition*)classDefinitionWithName:(NSString*)className language:(ClassDefinitionLanguage)language; 41 | 42 | /** 43 | * Initializes a new objective-c class definition. 44 | */ 45 | - (id)initWithName:(NSString*)fileName; 46 | 47 | /** 48 | * Initializes a new class definition with the specified language. 49 | */ 50 | - (id)initWithName:(NSString*)className language:(ClassDefinitionLanguage)language; 51 | 52 | - (BOOL)isObjectiveC; 53 | 54 | - (BOOL)isObjectiveCPlusPlus; 55 | 56 | - (BOOL)isCPlusPlus; 57 | 58 | - (NSString*)headerFileName; 59 | 60 | - (NSString*)sourceFileName; 61 | 62 | @end 63 | -------------------------------------------------------------------------------- /Dependencies/XcodeEditor/XCFrameworkDefinition.m: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // JASPER BLUES 4 | // Copyright 2012 Jasper Blues 5 | // All Rights Reserved. 6 | // 7 | // NOTICE: Jasper Blues permits you to use, modify, and distribute this file 8 | // in accordance with the terms of the license agreement accompanying it. 9 | // 10 | //////////////////////////////////////////////////////////////////////////////// 11 | 12 | 13 | 14 | #import "XCFrameworkDefinition.h" 15 | 16 | @implementation XCFrameworkDefinition 17 | 18 | @synthesize filePath = _filePath; 19 | @synthesize copyToDestination = _copyToDestination; 20 | 21 | /* ====================================================================================================================================== */ 22 | #pragma mark - Class Methods 23 | 24 | + (XCFrameworkDefinition*)frameworkDefinitionWithFilePath:(NSString*)filePath copyToDestination:(BOOL)copyToDestination 25 | { 26 | 27 | return [[XCFrameworkDefinition alloc] initWithFilePath:filePath copyToDestination:copyToDestination]; 28 | } 29 | 30 | /* ====================================================================================================================================== */ 31 | #pragma mark - Initialization & Destruction 32 | 33 | - (id)initWithFilePath:(NSString*)filePath copyToDestination:(BOOL)copyToDestination 34 | { 35 | self = [super init]; 36 | if (self) 37 | { 38 | _filePath = [filePath copy]; 39 | _copyToDestination = copyToDestination; 40 | } 41 | return self; 42 | } 43 | 44 | /* ====================================================================================================================================== */ 45 | #pragma mark - Interface Methods 46 | 47 | - (NSString*)name 48 | { 49 | return [_filePath lastPathComponent]; 50 | } 51 | 52 | 53 | @end -------------------------------------------------------------------------------- /Dependencies/XcodeEditor/XCSubProjectDefinition.h: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // JASPER BLUES 4 | // Copyright 2012 Jasper Blues 5 | // All Rights Reserved. 6 | // 7 | // NOTICE: Jasper Blues permits you to use, modify, and distribute this file 8 | // in accordance with the terms of the license agreement accompanying it. 9 | // 10 | //////////////////////////////////////////////////////////////////////////////// 11 | 12 | 13 | 14 | #import 15 | #import "XCAbstractDefinition.h" 16 | #import "XcodeSourceFileType.h" 17 | 18 | @class XCProject; 19 | 20 | 21 | @interface XCSubProjectDefinition : XCAbstractDefinition 22 | { 23 | 24 | NSString* _name; 25 | NSString* _path; 26 | XcodeSourceFileType _type; 27 | XCProject* _subProject; 28 | XCProject* _parentProject; 29 | NSString* _key; 30 | NSString* _fullProjectPath; 31 | NSString* _relativePath; 32 | } 33 | 34 | 35 | @property(nonatomic, strong, readonly) NSString* name; 36 | @property(nonatomic, strong, readonly) NSString* path; 37 | @property(nonatomic, readonly) XcodeSourceFileType type; 38 | @property(nonatomic, strong, readonly) XCProject* subProject; 39 | @property(nonatomic, strong, readonly) XCProject* parentProject; 40 | @property(nonatomic, strong, readonly) NSString* key; 41 | @property(nonatomic, strong, readwrite) NSString* fullProjectPath; 42 | 43 | + (XCSubProjectDefinition*)withName:(NSString*)name path:(NSString*)path parentProject:(XCProject*)parentProject; 44 | 45 | - (id)initWithName:(NSString*)name path:(NSString*)path parentProject:(XCProject*)parentProject; 46 | 47 | - (NSString*)projectFileName; 48 | 49 | - (NSString*)fullPathName; 50 | 51 | - (NSArray*)buildProductNames; 52 | 53 | - (NSString*)projectKey; 54 | 55 | - (NSString*)pathRelativeToProjectRoot; 56 | 57 | - (NSString*)description; 58 | 59 | - (void)initFullProjectPath:(NSString*)fullProjectPath groupPath:(NSString*)groupPath; 60 | 61 | @end 62 | -------------------------------------------------------------------------------- /Dependencies/XcodeEditor/XCXibDefinition.m: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // JASPER BLUES 4 | // Copyright 2012 Jasper Blues 5 | // All Rights Reserved. 6 | // 7 | // NOTICE: Jasper Blues permits you to use, modify, and distribute this file 8 | // in accordance with the terms of the license agreement accompanying it. 9 | // 10 | //////////////////////////////////////////////////////////////////////////////// 11 | 12 | 13 | #import "XCXibDefinition.h" 14 | 15 | @implementation XCXibDefinition 16 | 17 | @synthesize name = _name; 18 | @synthesize content = _content; 19 | 20 | /* ====================================================================================================================================== */ 21 | #pragma mark - Class Methods 22 | 23 | + (XCXibDefinition*)xibDefinitionWithName:(NSString*)name 24 | { 25 | return [[XCXibDefinition alloc] initWithName:name]; 26 | } 27 | 28 | + (XCXibDefinition*)xibDefinitionWithName:(NSString*)name content:(NSString*)content 29 | { 30 | return [[XCXibDefinition alloc] initWithName:name content:content]; 31 | } 32 | 33 | 34 | /* ====================================================================================================================================== */ 35 | #pragma mark - Initialization & Destruction 36 | 37 | - (id)initWithName:(NSString*)name 38 | { 39 | return [self initWithName:name content:nil]; 40 | } 41 | 42 | 43 | - (id)initWithName:(NSString*)name content:(NSString*)content 44 | { 45 | self = [super init]; 46 | if (self) 47 | { 48 | _name = [name copy]; 49 | _content = [content copy]; 50 | } 51 | return self; 52 | } 53 | 54 | 55 | /* ====================================================================================================================================== */ 56 | #pragma mark - Interface Methods 57 | 58 | - (NSString*)xibFileName 59 | { 60 | return [_name stringByAppendingString:@".xib"]; 61 | } 62 | 63 | @end -------------------------------------------------------------------------------- /XLocation/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | StefanLage.$(PRODUCT_NAME:rfc1034identifier) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | BNDL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | DVTPlugInCompatibilityUUIDs 26 | 27 | C4A681B0-4A26-480E-93EC-1218098B9AA0 28 | AD68E85B-441B-4301-B564-A45E4919A6AD 29 | A16FF353-8441-459E-A50C-B071F53F51B7 30 | 9F75337B-21B4-4ADC-B558-F9CADF7073A7 31 | E969541F-E6F9-4D25-8158-72DC3545A6C6 32 | 7FDF5C7A-131F-4ABB-9EDC-8C5F8F0B8A90 33 | 0420B86A-AA43-4792-9ED0-6FE0F2B16A13 34 | CC0D0F4F-05B3-431A-8F33-F84AFCB2C651 35 | 7265231C-39B4-402C-89E1-16167C4CC990 36 | 9AFF134A-08DC-4096-8CEE-62A4BB123046 37 | F41BD31E-2683-44B8-AE7F-5F09E919790E 38 | E71C2CFE-BFD8-4044-8F06-00AE685A406C 39 | ACA8656B-FEA8-4B6D-8E4A-93F4C95C362C 40 | 41 | LSMinimumSystemVersion 42 | $(MACOSX_DEPLOYMENT_TARGET) 43 | NSPrincipalClass 44 | XLocation 45 | XC4Compatible 46 | 47 | XCPluginHasUI 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /XLocation/Categories/NSString+Gpx.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+Gpx.m 3 | // XLocation 4 | // 5 | // Created by Stefan Lage on 16/05/14. 6 | // Copyright (c) 2014 StefanLage. All rights reserved. 7 | // 8 | 9 | #import "NSString+Gpx.h" 10 | 11 | @implementation NSString (Gpx) 12 | 13 | +(NSString *)generateGpxWithFilename:(NSString*) filename latitude:(NSNumber *)lat longitude:(NSNumber *)lng address:(NSString *)address city:(NSString *)city country:(NSString *)country zip:(NSString *)zipCode{ 14 | return [NSString stringWithFormat:@"\n\ 15 | \n\ 24 | \n\ 25 | \n\ 26 | %@\n\ 27 | \n\ 28 | \n\ 29 | \n\ 30 | %@\n\ 31 | %@\n\ 32 | %@\n\ 33 | %@\n\ 34 | \n\ 35 | \n\ 36 | \n\ 37 | \n\ 38 | ", lat, lng, [NSDate new], filename, address, city, country, zipCode]; 39 | } 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /Dependencies/XcodeEditor/XCSourceFile.h: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // JASPER BLUES 4 | // Copyright 2012 Jasper Blues 5 | // All Rights Reserved. 6 | // 7 | // NOTICE: Jasper Blues permits you to use, modify, and distribute this file 8 | // in accordance with the terms of the license agreement accompanying it. 9 | // 10 | //////////////////////////////////////////////////////////////////////////////// 11 | 12 | 13 | 14 | #import 15 | #import "XcodeGroupMember.h" 16 | #import "XcodeSourceFileType.h" 17 | 18 | @class XCProject; 19 | 20 | /** 21 | * Represents a file resource in an xcode project. 22 | */ 23 | @interface XCSourceFile : NSObject 24 | { 25 | 26 | @private 27 | XCProject* _project; 28 | 29 | NSNumber* _isBuildFile; 30 | NSString* _buildFileKey; 31 | NSString* _name; 32 | NSString* _sourceTree; 33 | NSString* _key; 34 | NSString* _path; 35 | XcodeSourceFileType _type; 36 | } 37 | 38 | @property(nonatomic, readonly) XcodeSourceFileType type; 39 | @property(nonatomic, strong, readonly) NSString* key; 40 | @property(nonatomic, strong) NSString* name; 41 | @property(nonatomic, strong, readonly) NSString* sourceTree; 42 | @property(nonatomic, strong) NSString* path; 43 | 44 | + (XCSourceFile*)sourceFileWithProject:(XCProject*)project key:(NSString*)key type:(XcodeSourceFileType)type name:(NSString*)name 45 | sourceTree:(NSString*)tree path:(NSString*)path; 46 | 47 | - (id)initWithProject:(XCProject*)project key:(NSString*)key type:(XcodeSourceFileType)type name:(NSString*)name sourceTree:(NSString*)tree 48 | path:(NSString*)path; 49 | 50 | /** 51 | * If yes, indicates the file is able to be included for compilation in an `XCTarget`. 52 | */ 53 | - (BOOL)isBuildFile; 54 | 55 | - (BOOL)canBecomeBuildFile; 56 | 57 | - (XcodeMemberType)buildPhase; 58 | 59 | - (NSString*)buildFileKey; 60 | 61 | /** 62 | * Adds this file to the project as an `xcode_BuildFile`, ready to be included in targets. 63 | */ 64 | - (void)becomeBuildFile; 65 | 66 | @end 67 | -------------------------------------------------------------------------------- /Dependencies/XcodeEditor/Utils/XCKeyBuilder.m: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // JASPER BLUES 4 | // Copyright 2012 - 2013 Jasper Blues 5 | // All Rights Reserved. 6 | // 7 | // NOTICE: Jasper Blues permits you to use, modify, and distribute this file 8 | // in accordance with the terms of the license agreement accompanying it. 9 | // 10 | //////////////////////////////////////////////////////////////////////////////// 11 | 12 | #import "XCKeyBuilder.h" 13 | 14 | @implementation XCKeyBuilder 15 | 16 | /* ================================================= Class Methods ================================================== */ 17 | + (XCKeyBuilder*)forItemNamed:(NSString*)name 18 | { 19 | NSData* data = [name dataUsingEncoding:NSUTF8StringEncoding]; 20 | return [[XCKeyBuilder alloc] initHashValueMD5HashWithBytes:[data bytes] length:[data length]]; 21 | 22 | } 23 | 24 | + (XCKeyBuilder*)createUnique 25 | { 26 | CFUUIDRef theUUID = CFUUIDCreate(NULL); 27 | CFUUIDBytes bytes = CFUUIDGetUUIDBytes(theUUID); 28 | CFRelease(theUUID); 29 | 30 | return [[XCKeyBuilder alloc] initHashValueMD5HashWithBytes:&bytes length:sizeof(bytes)]; 31 | } 32 | 33 | /* ================================================== Initializers ================================================== */ 34 | - (id)initHashValueMD5HashWithBytes:(const void*)bytes length:(NSUInteger)length 35 | { 36 | self = [super init]; 37 | if (self != nil) 38 | { 39 | CC_MD5(bytes, (int) length, _value); 40 | } 41 | return self; 42 | } 43 | 44 | /* ================================================ Interface Methods =============================================== */ 45 | - (NSString*)build 46 | { 47 | NSInteger byteLength = sizeof(HashValueMD5Hash); 48 | NSMutableString* stringValue = [NSMutableString stringWithCapacity:byteLength * 2]; 49 | NSInteger i; 50 | for (i = 0; i < byteLength; i++) 51 | { 52 | [stringValue appendFormat:@"%02x", _value[i]]; 53 | } 54 | return [[stringValue substringToIndex:24] uppercaseString]; 55 | } 56 | 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /Dependencies/XcodeEditor/XCSourceFileDefinition.m: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // JASPER BLUES 4 | // Copyright 2012 Jasper Blues 5 | // All Rights Reserved. 6 | // 7 | // NOTICE: Jasper Blues permits you to use, modify, and distribute this file 8 | // in accordance with the terms of the license agreement accompanying it. 9 | // 10 | //////////////////////////////////////////////////////////////////////////////// 11 | 12 | 13 | 14 | #import "XCSourceFileDefinition.h" 15 | 16 | @implementation XCSourceFileDefinition 17 | 18 | @synthesize sourceFileName = _sourceFileName; 19 | @synthesize type = _type; 20 | @synthesize data = _data; 21 | 22 | /* ====================================================================================================================================== */ 23 | #pragma mark - Class Methods 24 | 25 | + (XCSourceFileDefinition*)sourceDefinitionWithName:(NSString*)name text:(NSString*)text type:(XcodeSourceFileType)type 26 | { 27 | 28 | return [[XCSourceFileDefinition alloc] initWithName:name text:text type:type]; 29 | } 30 | 31 | + (XCSourceFileDefinition*)sourceDefinitionWithName:(NSString*)name data:(NSData*)data type:(XcodeSourceFileType)type 32 | { 33 | 34 | return [[XCSourceFileDefinition alloc] initWithName:name data:data type:type]; 35 | } 36 | 37 | 38 | /* ====================================================================================================================================== */ 39 | #pragma mark - Initialization & Destruction 40 | 41 | - (id)initWithName:(NSString*)name text:(NSString*)text type:(XcodeSourceFileType)type 42 | { 43 | self = [super init]; 44 | if (self) 45 | { 46 | _sourceFileName = [name copy]; 47 | _data = [[text dataUsingEncoding:NSUTF8StringEncoding] copy]; 48 | _type = type; 49 | } 50 | return self; 51 | } 52 | 53 | - (id)initWithName:(NSString*)name data:(NSData*)data type:(XcodeSourceFileType)type 54 | { 55 | self = [super init]; 56 | if (self) 57 | { 58 | _sourceFileName = [name copy]; 59 | _data = [data copy]; 60 | _type = type; 61 | } 62 | return self; 63 | 64 | } 65 | 66 | @end -------------------------------------------------------------------------------- /Dependencies/XcodeEditor/XCTarget.h: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // JASPER BLUES 4 | // Copyright 2012 Jasper Blues 5 | // All Rights Reserved. 6 | // 7 | // NOTICE: Jasper Blues permits you to use, modify, and distribute this file 8 | // in accordance with the terms of the license agreement accompanying it. 9 | // 10 | //////////////////////////////////////////////////////////////////////////////// 11 | 12 | 13 | #import 14 | 15 | @class XCProject; 16 | @class XCSourceFile; 17 | @class XCBuildConfiguration; 18 | 19 | /** 20 | * Represents a target in an xcode project. 21 | */ 22 | @interface XCTarget : NSObject 23 | { 24 | 25 | XCProject* _project; 26 | NSString* _key; 27 | NSString* _name; 28 | NSString* _productName; 29 | NSString* _productReference; 30 | NSString* _defaultConfigurationName; 31 | 32 | @private 33 | NSMutableArray* _members; 34 | NSMutableArray* _resources; 35 | NSMutableDictionary* _configurations; 36 | } 37 | 38 | @property(nonatomic, strong, readonly) NSString* key; 39 | @property(nonatomic, strong) NSString* name; 40 | @property(nonatomic, strong) NSString* productName; 41 | @property(nonatomic, strong, readonly) NSString* productReference; 42 | 43 | + (XCTarget*)targetWithProject:(XCProject*)project key:(NSString*)key name:(NSString*)name productName:(NSString*)productName 44 | productReference:(NSString*)productReference; 45 | 46 | - (id)initWithProject:(XCProject*)project key:(NSString*)key name:(NSString*)name productName:(NSString*)productName 47 | productReference:(NSString*)productReference; 48 | 49 | - (NSArray*)resources; 50 | 51 | - (NSArray*)members; 52 | 53 | - (NSDictionary*)configurations; 54 | 55 | - (XCBuildConfiguration*)configurationWithName:(NSString*)name; 56 | 57 | - (XCBuildConfiguration*)defaultConfiguration; 58 | 59 | - (void)addMember:(XCSourceFile*)member; 60 | 61 | - (void)removeMemberWithKey:(NSString*)key; 62 | 63 | - (void)removeMembersWithKeys:(NSArray*)keys; 64 | 65 | - (void)addDependency:(NSString*)key; 66 | 67 | - (instancetype)duplicateWithTargetName:(NSString*)targetName productName:(NSString*)productName; 68 | 69 | @end 70 | 71 | -------------------------------------------------------------------------------- /XLocation/Classes/XLWorkspace.m: -------------------------------------------------------------------------------- 1 | // 2 | // LWorkspace.m 3 | // XLocation 4 | // 5 | // Created by Stefan Lage on 10/06/14. 6 | // Copyright (c) 2014 StefanLage. All rights reserved. 7 | // 8 | 9 | #import "XLWorkspace.h" 10 | 11 | static NSString * const workspaceContent = @"contents.xcworkspacedata"; 12 | static NSString * const fileRefElement = @"FileRef"; 13 | static NSString * const locationKey = @"location"; 14 | static NSString * const locationNoise = @"group:"; 15 | 16 | @implementation XLWorkspace 17 | 18 | -(id)initWithUrl:(NSString*)url currentPath:(NSString*)path{ 19 | self = [super init]; 20 | if(self){ 21 | _currentWorkspacePath = path; 22 | NSString *worskpacePath = [NSString stringWithFormat:@"%@/%@", url, workspaceContent]; 23 | NSData *xmlData = [NSData dataWithContentsOfURL:[NSURL fileURLWithPath:worskpacePath]]; 24 | if(xmlData == nil) 25 | // Can't read the file -> return nil 26 | return nil; 27 | NSXMLParser* xmlParser = [[NSXMLParser alloc] initWithData:xmlData]; 28 | xmlParser.delegate = self; 29 | [xmlParser parse]; 30 | } 31 | return self; 32 | } 33 | 34 | // Check if the path has the right format : /Users/.... 35 | -(NSString*)checkPath:(NSString*)path{ 36 | NSMutableString *newpath = [[NSMutableString alloc] initWithString:path]; 37 | if([newpath characterAtIndex:0] != '/') 38 | [newpath insertString:self.currentWorkspacePath 39 | atIndex:0]; 40 | return newpath; 41 | } 42 | 43 | #pragma mark - NSXMLParser 44 | 45 | - (void)parserDidStartDocument:(NSXMLParser *)parser 46 | { 47 | self.projects = [NSMutableArray new]; 48 | } 49 | 50 | -(void) parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{ 51 | // Project found ? 52 | if([elementName isEqualToString:fileRefElement]) 53 | { 54 | NSString *location = [[attributeDict objectForKey:locationKey] stringByReplacingOccurrencesOfString:locationNoise 55 | withString:@""]; 56 | // correct the path if needed 57 | location = [self checkPath:location]; 58 | NSString* projectName = [[location lastPathComponent] stringByDeletingPathExtension]; 59 | NSDictionary *dic = @{ 60 | @"name": projectName, 61 | @"filename": [location lastPathComponent], 62 | @"location": location 63 | }; 64 | // Add project infos 65 | [self.projects addObject:dic]; 66 | } 67 | } 68 | 69 | @end 70 | -------------------------------------------------------------------------------- /Dependencies/XcodeEditor/XcodeSourceFileType.m: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // JASPER BLUES 4 | // Copyright 2012 Jasper Blues 5 | // All Rights Reserved. 6 | // 7 | // NOTICE: Jasper Blues permits you to use, modify, and distribute this file 8 | // in accordance with the terms of the license agreement accompanying it. 9 | // 10 | //////////////////////////////////////////////////////////////////////////////// 11 | 12 | 13 | 14 | #import "XcodeSourceFileType.h" 15 | 16 | NSDictionary* NSDictionaryWithXCFileReferenceTypes() 17 | { 18 | static NSDictionary* dictionary; 19 | static dispatch_once_t onceToken; 20 | dispatch_once(&onceToken, ^ 21 | { 22 | dictionary = @{ 23 | @"sourcecode.c.h" : @(SourceCodeHeader), 24 | @"sourcecode.c.objc" : @(SourceCodeObjC), 25 | @"wrapper.framework" : @(Framework), 26 | @"text.plist.strings" : @(PropertyList), 27 | @"sourcecode.cpp.objcpp" : @(SourceCodeObjCPlusPlus), 28 | @"sourcecode.cpp.cpp" : @(SourceCodeCPlusPlus), 29 | @"file.xib" : @(XibFile), 30 | @"image.png" : @(ImageResourcePNG), 31 | @"wrapper.cfbundle" : @(Bundle), 32 | @"archive.ar" : @(Archive), 33 | @"text.html" : @(HTML), 34 | @"text" : @(TEXT), 35 | @"gpx" : @(GPX), 36 | @"wrapper.pb-project" : @(XcodeProject) 37 | }; 38 | }); 39 | 40 | return dictionary; 41 | } 42 | 43 | NSString* NSStringFromXCSourceFileType(XcodeSourceFileType type) 44 | { 45 | return [[NSDictionaryWithXCFileReferenceTypes() allKeysForObject:@(type)] objectAtIndex:0]; 46 | } 47 | 48 | XcodeSourceFileType XCSourceFileTypeFromStringRepresentation(NSString* string) 49 | { 50 | NSDictionary* typeStrings = NSDictionaryWithXCFileReferenceTypes(); 51 | 52 | if ([typeStrings objectForKey:string]) 53 | { 54 | return (XcodeSourceFileType) [[typeStrings objectForKey:string] intValue]; 55 | } 56 | else 57 | { 58 | return FileTypeNil; 59 | } 60 | } 61 | 62 | 63 | XcodeSourceFileType XCSourceFileTypeFromFileName(NSString* fileName) 64 | { 65 | if ([fileName hasSuffix:@".h"] || [fileName hasSuffix:@".hh"] || [fileName hasSuffix:@".hpp"] || [fileName hasSuffix:@".hxx"]) 66 | { 67 | return SourceCodeHeader; 68 | } 69 | if ([fileName hasSuffix:@".c"] || [fileName hasSuffix:@".m"]) 70 | { 71 | return SourceCodeObjC; 72 | } 73 | if ([fileName hasSuffix:@".mm"]) 74 | { 75 | return SourceCodeObjCPlusPlus; 76 | } 77 | if ([fileName hasSuffix:@".cpp"]) 78 | { 79 | return SourceCodeCPlusPlus; 80 | } 81 | return FileTypeNil; 82 | } 83 | 84 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # XLocation 2 | 3 | **XLocation** is an open source **XCode** plugin. 4 |
5 | It lets you add a new location from an address known to your current xcode project. **NEW**, now it works in a **Workspace** too. 6 |
7 | 8 | ![Main](Screens/main.png) 9 | 10 | ##Features 11 | 12 | The process is very easy, you just need to enter an address (at least a city and its country), then the plug-in while get the coordinates corresponding to this address and generate the GPX file. 13 | 14 | ###Using a Map 15 | 16 | You get a location from the map view. 17 |
18 | Just need to do a `right click` on the map everywhere you want, then the plugin will get the corresponding address. 19 | 20 | ![Demo](Screens/demo_map.gif) 21 | 22 | ###Using your `Own` address 23 | 24 | You can create a new GPX file informing the following fields: 25 | 26 | ```` objective-c 27 | @Required 28 | ```` 29 | 30 | - City 31 | - Country 32 | 33 | ```` objective-c 34 | @Optional 35 | ```` 36 | 37 | - Address (Default value: `Downtown`) 38 | - Zip Code 39 | - The filename 40 | 41 | ![Demo](Screens/demo_address.gif) 42 | 43 | ##Workspace 44 | 45 | If you are using a workspace with severals projects, you will have to select in which project you would like to add the GPX file. 46 | 47 | 48 | ![Demo](Screens/demo_workspace.gif) 49 | 50 | ##Install 51 | 52 | ###Via Alcatraz 53 | 54 | XLocation plugin is available through the [Alcatraz](http://alcatraz.io/). 55 | 56 | ###From Source 57 | 58 | Download the project and build it, then relaunch Xcode. 59 |
60 | A new item named `Add new Location` should appear in the menu item `Debug`. 61 |
62 | XLocation will be installed in `~/Library/Application Support/Developer/Shared/Xcode/Plug-ins` automatically. 63 | 64 | If you want to uninstall XLocation, remove XLocation in Plug-ins directory. 65 | 66 | ##Dependency 67 | 68 | [`XcodeEditor`](https://github.com/jasperblues/XcodeEditor) to manipulate Xcode project files, made by [`AppsQuick.ly`](https://github.com/appsquickly). 69 | 70 | 71 | ##License 72 | 73 | Copyright (c) 2014 Stefan Lage 74 | 75 | Permission is hereby granted, free of charge, to any person obtaining 76 | a copy of this software and associated documentation files (the 77 | "Software"), to deal in the Software without restriction, including 78 | without limitation the rights to use, copy, modify, merge, publish, 79 | distribute, sublicense, and/or sell copies of the Software, and to 80 | permit persons to whom the Software is furnished to do so, subject to 81 | the following conditions: 82 | 83 | The above copyright notice and this permission notice shall be 84 | included in all copies or substantial portions of the Software. 85 | 86 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 87 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 88 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 89 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 90 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 91 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 92 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 93 | -------------------------------------------------------------------------------- /Dependencies/XcodeEditor/XCClassDefinition.m: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // JASPER BLUES 4 | // Copyright 2012 - 2013 Jasper Blues 5 | // All Rights Reserved. 6 | // 7 | // NOTICE: Jasper Blues permits you to use, modify, and distribute this file 8 | // in accordance with the terms of the license agreement accompanying it. 9 | // 10 | //////////////////////////////////////////////////////////////////////////////// 11 | 12 | 13 | 14 | 15 | 16 | #import "XCClassDefinition.h" 17 | 18 | @implementation XCClassDefinition 19 | 20 | 21 | @synthesize className = _className; 22 | @synthesize header = _header; 23 | @synthesize source = _source; 24 | 25 | /* ====================================================================================================================================== */ 26 | #pragma mark - Class Methods 27 | 28 | + (XCClassDefinition*)classDefinitionWithName:(NSString*)fileName 29 | { 30 | return [[XCClassDefinition alloc] initWithName:fileName]; 31 | } 32 | 33 | + (XCClassDefinition*)classDefinitionWithName:(NSString*)className language:(ClassDefinitionLanguage)language 34 | { 35 | return [[XCClassDefinition alloc] initWithName:className language:language]; 36 | } 37 | 38 | /* ====================================================================================================================================== */ 39 | #pragma mark - Initialization & Destruction 40 | 41 | - (id)initWithName:(NSString*)className 42 | { 43 | return [self initWithName:className language:ObjectiveC]; 44 | } 45 | 46 | - (id)initWithName:(NSString*)className language:(ClassDefinitionLanguage)language 47 | { 48 | self = [super init]; 49 | if (self) 50 | { 51 | _className = [className copy]; 52 | if (!(language == ObjectiveC || language == ObjectiveCPlusPlus || language == CPlusPlus)) 53 | { 54 | [NSException raise:NSInvalidArgumentException format:@"Language must be one of ObjectiveC, ObjectiveCPlusPlus"]; 55 | } 56 | _language = language; 57 | } 58 | return self; 59 | } 60 | 61 | 62 | /* ====================================================================================================================================== */ 63 | #pragma mark - Interface Methods 64 | 65 | - (BOOL)isObjectiveC 66 | { 67 | return _language == ObjectiveC; 68 | } 69 | 70 | - (BOOL)isObjectiveCPlusPlus 71 | { 72 | return _language == ObjectiveCPlusPlus; 73 | } 74 | 75 | - (BOOL)isCPlusPlus 76 | { 77 | return _language == CPlusPlus; 78 | } 79 | 80 | - (NSString*)headerFileName 81 | { 82 | return [_className stringByAppendingString:@".h"]; 83 | 84 | } 85 | 86 | - (NSString*)sourceFileName 87 | { 88 | NSString* sourceFileName = nil; 89 | if ([self isObjectiveC]) 90 | { 91 | sourceFileName = [_className stringByAppendingString:@".m"]; 92 | } 93 | else if ([self isObjectiveCPlusPlus]) 94 | { 95 | sourceFileName = [_className stringByAppendingString:@".mm"]; 96 | } 97 | else if ([self isCPlusPlus]) 98 | { 99 | sourceFileName = [_className stringByAppendingString:@".cpp"]; 100 | } 101 | return sourceFileName; 102 | } 103 | 104 | 105 | @end -------------------------------------------------------------------------------- /Dependencies/XcodeEditor/XcodeMemberType.m: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // JASPER BLUES 4 | // Copyright 2012 Jasper Blues 5 | // All Rights Reserved. 6 | // 7 | // NOTICE: Jasper Blues permits you to use, modify, and distribute this file 8 | // in accordance with the terms of the license agreement accompanying it. 9 | // 10 | //////////////////////////////////////////////////////////////////////////////// 11 | 12 | 13 | 14 | 15 | #import "XcodeMemberType.h" 16 | 17 | 18 | @implementation NSDictionary (XcodeMemberType) 19 | 20 | 21 | + (NSDictionary*)dictionaryWithProjectNodeTypesAsStrings 22 | { 23 | // This is the most vital operation on adding 500+ files 24 | // So, we caching this dictionary 25 | static NSDictionary* _projectNodeTypesAsStrings; 26 | static dispatch_once_t onceToken; 27 | dispatch_once(&onceToken, ^ 28 | { 29 | _projectNodeTypesAsStrings = 30 | [[NSDictionary alloc] initWithObjectsAndKeys:@(PBXNilType), @"PBXNilType", 31 | @(PBXBuildFileType), @"PBXBuildFile", 32 | @(PBXContainerItemProxyType), @"PBXContainerItemProxy", 33 | @(PBXCopyFilesBuildPhaseType), @"PBXCopyFilesBuildPhase", 34 | @(PBXFileReferenceType), @"PBXFileReference", 35 | @(PBXFrameworksBuildPhaseType), @"PBXFrameworksBuildPhase", 36 | @(PBXGroupType), @"PBXGroup", 37 | @(PBXNativeTargetType), @"PBXNativeTarget", 38 | @(PBXProjectType), @"PBXProject", 39 | @(PBXReferenceProxyType), @"PBXReferenceProxy", 40 | @(PBXResourcesBuildPhaseType), @"PBXResourcesBuildPhase", 41 | @(PBXSourcesBuildPhaseType), @"PBXSourcesBuildPhase", 42 | @(PBXTargetDependencyType), @"PBXTargetDependency", 43 | @(PBXVariantGroupType), @"PBXVariantGroup", 44 | @(XCBuildConfigurationType), @"XCBuildConfiguration", 45 | @(XCConfigurationListType), @"XCConfigurationList", nil]; 46 | }); 47 | return _projectNodeTypesAsStrings; 48 | } 49 | 50 | @end 51 | 52 | @implementation NSString (XcodeMemberTypeExtensions) 53 | 54 | + (NSString*)stringFromMemberType:(XcodeMemberType)nodeType 55 | { 56 | NSDictionary* nodeTypesToString = [NSDictionary dictionaryWithProjectNodeTypesAsStrings]; 57 | return [[nodeTypesToString allKeysForObject:@(nodeType)] objectAtIndex:0]; 58 | } 59 | 60 | 61 | - (XcodeMemberType)asMemberType 62 | { 63 | NSDictionary* nodeTypesToString = [NSDictionary dictionaryWithProjectNodeTypesAsStrings]; 64 | return (XcodeMemberType) [[nodeTypesToString objectForKey:self] intValue]; 65 | } 66 | 67 | 68 | @end -------------------------------------------------------------------------------- /XLocation.xcodeproj/xcshareddata/xcschemes/XLocation.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 46 | 47 | 58 | 60 | 61 | 62 | 68 | 69 | 70 | 71 | 72 | 73 | 79 | 80 | 82 | 83 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /XLocation/Views/RMBlurredView.m: -------------------------------------------------------------------------------- 1 | // 2 | // RMBlurredView.m 3 | // 4 | // Created by Raffael Hannemann on 08.10.13. 5 | // Copyright (c) 2013 Raffael Hannemann. All rights reserved. 6 | // 7 | 8 | #import "RMBlurredView.h" 9 | 10 | #define kRMBlurredViewDefaultTintColor [NSColor colorWithCalibratedWhite:1.0 alpha:0.7] 11 | #define kRMBlurredViewDefaultSaturationFactor 2.0 12 | #define kRMBlurredViewDefaultBlurRadius 20.0 13 | 14 | @implementation RMBlurredView 15 | 16 | - (id)initWithFrame:(NSRect)frame 17 | { 18 | self = [super initWithFrame:frame]; 19 | if (self) { 20 | [self setUp]; 21 | } 22 | return self; 23 | } 24 | 25 | - (id)initWithCoder:(NSCoder *)coder 26 | { 27 | self = [super initWithCoder:coder]; 28 | if (self) { 29 | [self setUp]; 30 | } 31 | return self; 32 | } 33 | 34 | - (void) setTintColor:(NSColor *)tintColor { 35 | _tintColor = tintColor; 36 | 37 | // Since we need a CGColor reference, store it for the drawing of the layer. 38 | if (_tintColor) { 39 | [self.layer setBackgroundColor:_tintColor.CGColor]; 40 | } 41 | 42 | // Trigger a re-drawing of the layer 43 | [self.layer setNeedsDisplay]; 44 | } 45 | 46 | - (void) setBlurRadius:(float)blurRadius { 47 | // Setting the blur radius requires a resetting of the filters 48 | _blurRadius = blurRadius; 49 | [self resetFilters]; 50 | } 51 | 52 | - (void) setBlurRadiusNumber:(NSNumber *)blurRadiusNumber { 53 | [self setBlurRadius:blurRadiusNumber.floatValue]; 54 | } 55 | 56 | - (void) setSaturationFactor:(float)saturationFactor { 57 | // Setting the saturation factor also requires a resetting of the filters 58 | _saturationFactor = saturationFactor; 59 | [self resetFilters]; 60 | } 61 | 62 | - (void) setSaturationFactorNumber:(NSNumber *)saturationFactorNumber { 63 | [self setSaturationFactor:saturationFactorNumber.floatValue]; 64 | } 65 | 66 | - (void) setUp { 67 | // Instantiate a new CALayer and set it as the NSView's layer (layer-hosting) 68 | _hostedLayer = [CALayer layer]; 69 | [self setWantsLayer:YES]; 70 | [self setLayer:_hostedLayer]; 71 | 72 | // Set up the default parameters 73 | _blurRadius = kRMBlurredViewDefaultBlurRadius; 74 | _saturationFactor = kRMBlurredViewDefaultSaturationFactor; 75 | [self setTintColor:kRMBlurredViewDefaultTintColor]; 76 | 77 | // It's important to set the layer to mask to its bounds, otherwise the whole parent view might get blurred 78 | [self.layer setMasksToBounds:YES]; 79 | 80 | // To apply CIFilters on OS X 10.9, we need to set the property accordingly: 81 | if ([self respondsToSelector:@selector(setLayerUsesCoreImageFilters:)]) { 82 | BOOL flag = YES; 83 | NSInvocation *inv = [NSInvocation invocationWithMethodSignature:[self methodSignatureForSelector:@selector(setLayerUsesCoreImageFilters:)]]; 84 | [inv setSelector:@selector(setLayerUsesCoreImageFilters:)]; 85 | [inv setArgument:&flag atIndex:2]; 86 | [inv invokeWithTarget:self]; 87 | } 88 | 89 | // Set the layer to redraw itself once it's size is changed 90 | [self.layer setNeedsDisplayOnBoundsChange:YES]; 91 | 92 | // Initially create the filter instances 93 | [self resetFilters]; 94 | } 95 | 96 | - (void) resetFilters { 97 | // To get a higher color saturation, we create a ColorControls filter 98 | _saturationFilter = [CIFilter filterWithName:@"CIColorControls"]; 99 | [_saturationFilter setDefaults]; 100 | [_saturationFilter setValue:[NSNumber numberWithFloat:_saturationFactor] forKey:@"inputSaturation"]; 101 | 102 | // Next, we create the blur filter 103 | _blurFilter = [CIFilter filterWithName:@"CIGaussianBlur"]; 104 | [_blurFilter setDefaults]; 105 | [_blurFilter setValue:[NSNumber numberWithFloat:_blurRadius] forKey:@"inputRadius"]; 106 | 107 | // Now we apply the two filters as the layer's background filters 108 | [self.layer setBackgroundFilters:@[_saturationFilter, _blurFilter]]; 109 | 110 | // ... and trigger a refresh 111 | [self.layer setNeedsDisplay]; 112 | } 113 | 114 | @end -------------------------------------------------------------------------------- /XLocation/XLWorkspaceView.m: -------------------------------------------------------------------------------- 1 | // 2 | // LWorskpaceController.m 3 | // XLocation 4 | // 5 | // Created by Stefan Lage on 10/06/14. 6 | // Copyright (c) 2014 StefanLage. All rights reserved. 7 | // 8 | 9 | #import "XLWorkspaceView.h" 10 | 11 | static NSString * const defaultMessage = @"It seems you're using a Workspace.\nPlease select in which project you'd like to add the GPX:"; 12 | static NSString * const goBackTitle = @"Go Back"; 13 | static NSString * const continueTitle = @"Continue"; 14 | 15 | @interface XLWorkspaceView () 16 | 17 | @property (nonatomic, strong) NSButton *back; 18 | @property (nonatomic, strong) NSMatrix *projectsMatrix; 19 | 20 | @end 21 | 22 | @implementation XLWorkspaceView 23 | 24 | - (id)initWithFrame:(NSRect)frame workspace:(XLWorkspace*)workspace 25 | { 26 | self = [super initWithFrame:frame]; 27 | if(self){ 28 | _currentWorkspace = workspace; 29 | // Get the mid point of this view 30 | float x = frame.size.width / 2; 31 | float y = frame.size.height / 2; 32 | NSPoint midPoint = NSMakePoint(x, y); 33 | 34 | NSTextField *txtField = [[NSTextField alloc] initWithFrame:NSMakeRect((x - 340/2), y + 60, 340, 60)]; 35 | [txtField setStringValue:defaultMessage]; 36 | [txtField setEditable:NO]; 37 | [txtField setBordered:NO]; 38 | [txtField setBackgroundColor:[NSColor clearColor]]; 39 | [self addSubview:txtField]; 40 | 41 | [self setButtons:midPoint]; 42 | [self setMatrix:midPoint]; 43 | } 44 | return self; 45 | } 46 | 47 | -(void)setButtons:(NSPoint)midPoint{ 48 | 49 | float x = midPoint.x - 115; 50 | float y = midPoint.y - 125.0; 51 | _back = [[NSButton alloc] initWithFrame:NSMakeRect(x, y, 115, 32)]; 52 | [_back setTitle:goBackTitle]; 53 | [_back setTarget:self]; 54 | [_back setAction:@selector(back:)]; 55 | [_back setButtonType:NSMomentaryLightButton]; 56 | [_back setBezelStyle:NSRoundedBezelStyle]; 57 | // Set escpace key as shortcut 58 | [_back setKeyEquivalent:@"\033"]; 59 | 60 | _continueBtn = [[NSButton alloc] initWithFrame:NSMakeRect(x+125, y, 115, 32)]; 61 | [_continueBtn setTitle:continueTitle]; 62 | [_continueBtn setTarget:self]; 63 | [_continueBtn setAction:@selector(projectSelected:)]; 64 | [_continueBtn setButtonType:NSMomentaryLightButton]; 65 | [_continueBtn setBezelStyle:NSRoundedBezelStyle]; 66 | // Set enter/return key as shortcut 67 | [_continueBtn setKeyEquivalent:@"\r"]; 68 | 69 | [self addSubview:_back]; 70 | [self addSubview:_continueBtn]; 71 | } 72 | 73 | // Create a matrix containing all projects name 74 | -(void) setMatrix:(NSPoint)midPoint{ 75 | // Create a long title sample to be sure it could be contain a long name 76 | NSMutableString *title = [[NSMutableString alloc] initWithString:@" "]; 77 | for (int i = 0; i < 200; i++) 78 | [title appendString:@" "]; 79 | // Set a prototype of radio button 80 | NSButtonCell *prototype = [[NSButtonCell alloc] init]; 81 | [prototype setTitle:title]; 82 | [prototype setButtonType:NSRadioButton]; 83 | 84 | float x = midPoint.x - 125.0/2; 85 | float y = midPoint.y - 125.0/2; 86 | NSRect matrixRect = NSMakeRect(x, y, 200.0, 125.0); 87 | NSInteger rows = self.currentWorkspace.projects.count; 88 | self.projectsMatrix = [[NSMatrix alloc] initWithFrame:matrixRect 89 | mode:NSRadioModeMatrix 90 | prototype:(NSCell *)prototype 91 | numberOfRows:rows 92 | numberOfColumns:1]; 93 | 94 | [self addSubview:self.projectsMatrix]; 95 | NSArray *cellArray = [self.projectsMatrix cells]; 96 | for(int i = 0; i < rows ; i++){ 97 | NSDictionary *project = [self.currentWorkspace.projects objectAtIndex:i]; 98 | [[cellArray objectAtIndex:i] setTitle:[project objectForKey:@"name"]]; 99 | } 100 | } 101 | 102 | #pragma mark - Handlers 103 | 104 | -(void)back:(id)sender{ 105 | if([self.delegate respondsToSelector:@selector(goBack:)]) 106 | [self.delegate goBack:self]; 107 | } 108 | 109 | -(void)projectSelected:(id)sender{ 110 | if([self.delegate respondsToSelector:@selector(projectSelected:index:)]) 111 | [self.delegate projectSelected:self index:[self.projectsMatrix selectedRow]]; 112 | } 113 | 114 | @end 115 | -------------------------------------------------------------------------------- /Dependencies/XcodeEditor/XCProject.h: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // JASPER BLUES 4 | // Copyright 2012 - 2013 Jasper Blues 5 | // All Rights Reserved. 6 | // 7 | // NOTICE: Jasper Blues permits you to use, modify, and distribute this file 8 | // in accordance with the terms of the license agreement accompanying it. 9 | // 10 | //////////////////////////////////////////////////////////////////////////////// 11 | 12 | #import 13 | #import "XcodeMemberType.h" 14 | #import "XcodeSourceFileType.h" 15 | 16 | @class XCClassDefinition; 17 | @class XCGroup; 18 | @class XCFileOperationQueue; 19 | @class XCSourceFile; 20 | @class XCTarget; 21 | @class XCSubProjectDefinition; 22 | @class XCBuildConfiguration; 23 | 24 | static NSString* const XCProjectNotFoundException; 25 | 26 | @interface XCProject : NSObject 27 | { 28 | @protected 29 | XCFileOperationQueue* _fileOperationQueue; 30 | 31 | NSString* _filePath; 32 | NSMutableDictionary* _dataStore; 33 | NSMutableArray* _targets; 34 | 35 | NSMutableDictionary* _groups; 36 | NSMutableDictionary* _configurations; 37 | 38 | NSString* _defaultConfigurationName; 39 | NSString* _rootObjectKey; 40 | } 41 | 42 | @property(nonatomic, strong, readonly) XCFileOperationQueue* fileOperationQueue; 43 | 44 | /* ============================================================ Initializers ============================================================ */ 45 | 46 | + (XCProject*)projectWithFilePath:(NSString*)filePath; 47 | 48 | /** 49 | * Creates a new project editor instance with the specified Project.xcodeproj file. 50 | */ 51 | - (id)initWithFilePath:(NSString*)filePath; 52 | 53 | /* ====================================================================================================================================== */ 54 | 55 | #pragma mark Files 56 | /** 57 | * Returns all file resources in the project, as an array of `XCSourceFile` objects. 58 | */ 59 | - (NSArray*)files; 60 | 61 | /** 62 | * Returns the project file with the specified key, or nil. 63 | */ 64 | - (XCSourceFile*)fileWithKey:(NSString*)key; 65 | 66 | /** 67 | * Returns the project file with the specified name, or nil. If more than one project file matches the specified name, 68 | * which one is returned is undefined. 69 | */ 70 | - (XCSourceFile*)fileWithName:(NSString*)name; 71 | 72 | /** 73 | * Returns all header files in the project, as an array of `XCSourceFile` objects. 74 | */ 75 | - (NSArray*)headerFiles; 76 | 77 | /** 78 | * Returns all implementation obj-c implementation files in the project, as an array of `XCSourceFile` objects. 79 | */ 80 | - (NSArray*)objectiveCFiles; 81 | 82 | /** 83 | * Returns all implementation obj-c++ implementation files in the project, as an array of `XCSourceFile` objects. 84 | */ 85 | - (NSArray*)objectiveCPlusPlusFiles; 86 | 87 | /** 88 | * Returns all the xib files in the project, as an array of `XCSourceFile` objects. 89 | */ 90 | - (NSArray*)xibFiles; 91 | 92 | - (NSArray*)imagePNGFiles; 93 | 94 | - (NSString*)filePath; 95 | 96 | 97 | /* ====================================================================================================================================== */ 98 | #pragma mark Groups 99 | /** 100 | * Lists the groups in an xcode project, returning an array of `XCGroup` objects. 101 | */ 102 | - (NSArray*)groups; 103 | 104 | /** 105 | * Returns the root (top-level) group. 106 | */ 107 | - (XCGroup*)rootGroup; 108 | 109 | /** 110 | * Returns the root (top-level) groups, if there are multiple. An array of rootGroup if there is only one. 111 | */ 112 | - (NSArray*)rootGroups; 113 | 114 | /** 115 | * Returns the group with the given key, or nil. 116 | */ 117 | - (XCGroup*)groupWithKey:(NSString*)key; 118 | 119 | /** 120 | * Returns the group with the specified display name path - the directory relative to the root group. Eg Source/Main 121 | */ 122 | - (XCGroup*)groupWithPathFromRoot:(NSString*)path; 123 | 124 | /** 125 | * Returns the parent group for the group or file with the given key; 126 | */ 127 | - (XCGroup*)groupForGroupMemberWithKey:(NSString*)key; 128 | 129 | /** 130 | * Returns the parent group for the group or file with the source file 131 | */ 132 | - (XCGroup*)groupWithSourceFile:(XCSourceFile*)sourceFile; 133 | 134 | /* ====================================================================================================================================== */ 135 | #pragma mark Targets 136 | /** 137 | * Lists the targets in an xcode project, returning an array of `XCTarget` objects. 138 | */ 139 | - (NSArray*)targets; 140 | 141 | /** 142 | * Returns the target with the specified name, or nil. 143 | */ 144 | - (XCTarget*)targetWithName:(NSString*)name; 145 | 146 | #pragma mark Configurations 147 | 148 | /** 149 | * Returns the target with the specified name, or nil. 150 | */ 151 | - (NSDictionary*)configurations; 152 | 153 | - (NSDictionary*)configurationWithName:(NSString*)name; 154 | 155 | - (XCBuildConfiguration*)defaultConfiguration; 156 | 157 | /* ====================================================================================================================================== */ 158 | #pragma mark Saving 159 | /** 160 | * Saves a project after editing. 161 | */ 162 | - (void)save; 163 | 164 | 165 | /* ====================================================================================================================================== */ 166 | /** 167 | * Raw project data. 168 | */ 169 | - (NSMutableDictionary*)objects; 170 | 171 | - (NSMutableDictionary*)dataStore; 172 | 173 | - (void)dropCache; 174 | 175 | @end 176 | -------------------------------------------------------------------------------- /Dependencies/XcodeEditor/XCGroup.h: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // JASPER BLUES 4 | // Copyright 2012 Jasper Blues 5 | // All Rights Reserved. 6 | // 7 | // NOTICE: Jasper Blues permits you to use, modify, and distribute this file 8 | // in accordance with the terms of the license agreement accompanying it. 9 | // 10 | //////////////////////////////////////////////////////////////////////////////// 11 | 12 | 13 | #import 14 | #import "XcodeGroupMember.h" 15 | 16 | @class XCProject; 17 | @class XCClassDefinition; 18 | @class XCSourceFile; 19 | @class XCXibDefinition; 20 | @class XCFileOperationQueue; 21 | @class XCFrameworkDefinition; 22 | @class XCSourceFileDefinition; 23 | @class XCSubProjectDefinition; 24 | 25 | 26 | /** 27 | * Represents a group container in an Xcode project. A group can contain members of type `XCSourceFile` or other 28 | * groups. 29 | */ 30 | @interface XCGroup : NSObject 31 | { 32 | 33 | NSString* _pathRelativeToParent; 34 | NSString* _key; 35 | NSString* _alias; 36 | 37 | 38 | @private 39 | NSString* _pathRelativeToProjectRoot; 40 | NSMutableArray* _children; 41 | NSMutableArray* _members; 42 | 43 | XCFileOperationQueue* _fileOperationQueue; // weak 44 | XCProject* _project; 45 | 46 | } 47 | 48 | 49 | /** 50 | * The alias of the group, which can be used to give the group a name other than the last path component. 51 | * 52 | * See: [XcodeGroupMember displayName] 53 | */ 54 | @property(nonatomic, strong, readonly) NSString* alias; 55 | 56 | /** 57 | * The path of the group relative to the group's parent. 58 | * 59 | * See: [XcodeGroupMember displayName] 60 | */ 61 | @property(nonatomic, strong, readonly) NSString* pathRelativeToParent; 62 | 63 | /** 64 | * The group's unique key. 65 | */ 66 | @property(nonatomic, strong, readonly) NSString* key; 67 | 68 | /** 69 | * An array containing the groups members as `XcodeGroupMember` types. 70 | */ 71 | @property(nonatomic, strong, readonly) NSMutableArray* children; 72 | 73 | 74 | #pragma mark Initializers 75 | 76 | + (XCGroup*)groupWithProject:(XCProject*)project key:(NSString*)key alias:(NSString*)alias path:(NSString*)path children:(NSArray*)children; 77 | 78 | - (id)initWithProject:(XCProject*)project key:(NSString*)key alias:(NSString*)alias path:(NSString*)path children:(NSArray*)children; 79 | 80 | #pragma mark Parent group 81 | 82 | - (void)removeFromParentGroup; 83 | 84 | - (void)removeFromParentDeletingChildren:(BOOL)deleteChildren; 85 | 86 | - (XCGroup*)parentGroup; 87 | 88 | - (BOOL)isRootGroup; 89 | 90 | #pragma mark Adding children 91 | /** 92 | * Adds a class to the group, as specified by the ClassDefinition. If the group already contains a class by the same 93 | * name, the contents will be updated. 94 | */ 95 | - (void)addClass:(XCClassDefinition*)classDefinition; 96 | 97 | /** 98 | * Adds a class to the group, making it a member of the specified [targets](XCTarget). 99 | */ 100 | - (void)addClass:(XCClassDefinition*)classDefinition toTargets:(NSArray*)targets; 101 | 102 | /** 103 | * Adds a framework to the group. If the group already contains the framework, the contents will be updated if the 104 | * framework definition's copyToDestination flag is yes, otherwise it will be ignored. 105 | */ 106 | - (void)addFramework:(XCFrameworkDefinition*)frameworkDefinition; 107 | 108 | /** 109 | * Adds a group with a path relative to this group. 110 | */ 111 | - (XCGroup*)addGroupWithPath:(NSString*)path; 112 | 113 | /** 114 | * Adds a framework to the group, making it a member of the specified targets. 115 | */ 116 | - (void)addFramework:(XCFrameworkDefinition*)framework toTargets:(NSArray*)targets; 117 | 118 | /** 119 | * Adds a source file of arbitrary type - image resource, header, etc. 120 | */ 121 | - (void)addSourceFile:(XCSourceFileDefinition*)sourceFileDefinition; 122 | 123 | 124 | /** 125 | * Adds a xib file to the group. If the group already contains a class by the same name, the contents will be updated. 126 | */ 127 | - (void)addXib:(XCXibDefinition*)xibDefinition; 128 | 129 | /** 130 | * Adds a xib to the group, making it a member of the specified [targets](XCTarget). 131 | */ 132 | - (void)addXib:(XCXibDefinition*)xibDefinition toTargets:(NSArray*)targets; 133 | 134 | /** 135 | * Adds a sub-project to the group. If the group already contains a sub-project by the same name, the contents will be 136 | * updated. 137 | * Returns boolean success/fail; if method fails, caller should assume that project file is corrupt (or file format has 138 | * changed). 139 | */ 140 | - (void)addSubProject:(XCSubProjectDefinition*)projectDefinition; 141 | 142 | /** 143 | * Adds a sub-project to the group, making it a member of the specified [targets](XCTarget). 144 | */ 145 | - (void)addSubProject:(XCSubProjectDefinition*)projectDefinition toTargets:(NSArray*)targets; 146 | 147 | - (void)removeSubProject:(XCSubProjectDefinition*)projectDefinition; 148 | 149 | - (void)removeSubProject:(XCSubProjectDefinition*)projectDefinition fromTargets:(NSArray*)targets; 150 | 151 | 152 | #pragma mark Locating children 153 | /** 154 | * Instances of `XCSourceFile` and `XCGroup` returned as the type `XcodeGroupMember`. 155 | */ 156 | - (NSArray*)members; 157 | 158 | /** 159 | * Instances of `XCSourceFile` from this group and any child groups. 160 | */ 161 | - (NSArray*)recursiveMembers; 162 | 163 | 164 | - (NSArray*)buildFileKeys; 165 | 166 | /** 167 | * Returns the child with the specified key, or nil. 168 | */ 169 | - (id )memberWithKey:(NSString*)key; 170 | 171 | /** 172 | * Returns the child with the specified name, or nil. 173 | */ 174 | - (id )memberWithDisplayName:(NSString*)name; 175 | 176 | 177 | @end 178 | -------------------------------------------------------------------------------- /Dependencies/OCLogTemplate/OCLogTemplate.h: -------------------------------------------------------------------------------- 1 | /** 2 | * For Objective-C code, this library adds flexible, non-intrusive logging capabilities 3 | * that can be efficiently enabled or disabled via compile switches. 4 | * 5 | * There are four levels of logging: Trace, Info, Error and Debug, and each can be enabled 6 | * independently via the LOGGING_LEVEL_TRACE, LOGGING_LEVEL_INFO, LOGGING_LEVEL_ERROR and 7 | * LOGGING_LEVEL_DEBUG switches, respectively. 8 | * 9 | * In addition, ALL logging can be enabled or disabled via the LOGGING_ENABLED switch. 10 | * 11 | * Logging functions are implemented here via macros. Disabling logging, either entirely, or 12 | * at a specific level, completely removes the corresponding log invocations from the compiled 13 | * code, thus eliminating both the memory and CPU overhead that the logging calls would add. 14 | * You might choose, for example, to completely remove all logging from production release code, 15 | * by setting LOGGING_ENABLED off in your production builds settings. Or, as another example, 16 | * you might choose to include Error logging in your production builds by turning only 17 | * LOGGING_ENABLED and LOGGING_LEVEL_ERROR on, and turning the others off. 18 | * 19 | * To perform logging, use any of the following function calls in your code: 20 | * 21 | * LogTrace(fmt, ...) - recommended for detailed tracing of program flow 22 | * - will print if LOGGING_LEVEL_TRACE is set on. 23 | * 24 | * LogInfo(fmt, ...) - recommended for general, infrequent, information messages 25 | * - will print if LOGGING_LEVEL_INFO is set on. 26 | * 27 | * LogError(fmt, ...) - recommended for use only when there is an error to be logged 28 | * - will print if LOGGING_LEVEL_ERROR is set on. 29 | * 30 | * LogDebug(fmt, ...) - recommended for temporary use during debugging 31 | * - will print if LOGGING_LEVEL_DEBUG is set on. 32 | * 33 | * In each case, the functions follow the general NSLog/printf template, where the first argument 34 | * "fmt" is an NSString that optionally includes embedded Format Specifiers, and subsequent optional 35 | * arguments indicate data to be formatted and inserted into the string. As with NSLog, the number 36 | * of optional arguments must match the number of embedded Format Specifiers. For more info, see the 37 | * core documentation for NSLog and String Format Specifiers. 38 | * 39 | * You can choose to have each logging entry automatically include class, method and line information 40 | * by enabling the LOGGING_INCLUDE_CODE_LOCATION switch. 41 | * 42 | * Although you can directly edit this file to turn on or off the switches below, the preferred 43 | * technique is to set these switches via the compiler build setting GCC_PREPROCESSOR_DEFINITIONS 44 | * in your build configuration. 45 | */ 46 | 47 | /** 48 | * Set this switch to enable or disable logging capabilities. 49 | * This can be set either here or via the compiler build setting GCC_PREPROCESSOR_DEFINITIONS 50 | * in your build configuration. Using the compiler build setting is preferred for this to 51 | * ensure that logging is not accidentally left enabled by accident in release builds. 52 | */ 53 | #ifndef LOGGING_ENABLED 54 | # define LOGGING_ENABLED 1 55 | #endif 56 | 57 | /** 58 | * Set any or all of these switches to enable or disable logging at specific levels. 59 | * These can be set either here or as a compiler build settings. 60 | * For these settings to be effective, LOGGING_ENABLED must also be defined and non-zero. 61 | */ 62 | #ifndef LOGGING_LEVEL_TRACE 63 | # define LOGGING_LEVEL_TRACE 0 64 | #endif 65 | #ifndef LOGGING_LEVEL_INFO 66 | # define LOGGING_LEVEL_INFO 1 67 | #endif 68 | #ifndef LOGGING_LEVEL_ERROR 69 | # define LOGGING_LEVEL_ERROR 1 70 | #endif 71 | #ifndef LOGGING_LEVEL_DEBUG 72 | # define LOGGING_LEVEL_DEBUG 1 73 | #endif 74 | 75 | /** 76 | * Set this switch to indicate whether or not to include class, method and line information 77 | * in the log entries. This can be set either here or as a compiler build setting. 78 | */ 79 | #ifndef LOGGING_INCLUDE_CODE_LOCATION 80 | #define LOGGING_INCLUDE_CODE_LOCATION 1 81 | #endif 82 | 83 | // *********** END OF USER SETTINGS - Do not change anything below this line *********** 84 | 85 | 86 | #if !(defined(LOGGING_ENABLED) && LOGGING_ENABLED) 87 | #undef LOGGING_LEVEL_TRACE 88 | #undef LOGGING_LEVEL_INFO 89 | #undef LOGGING_LEVEL_ERROR 90 | #undef LOGGING_LEVEL_DEBUG 91 | #endif 92 | 93 | // Logging format 94 | #define LOG_FORMAT_NO_LOCATION(fmt, lvl, ...) NSLog((@"[%@] " fmt), lvl, ##__VA_ARGS__) 95 | #define LOG_FORMAT_WITH_LOCATION(fmt, lvl, ...) NSLog((@"%s[Line %d] [%@] " fmt), __PRETTY_FUNCTION__, __LINE__, lvl, ##__VA_ARGS__) 96 | 97 | #if defined(LOGGING_INCLUDE_CODE_LOCATION) && LOGGING_INCLUDE_CODE_LOCATION 98 | #define LOG_FORMAT(fmt, lvl, ...) LOG_FORMAT_WITH_LOCATION(fmt, lvl, ##__VA_ARGS__) 99 | #else 100 | #define LOG_FORMAT(fmt, lvl, ...) LOG_FORMAT_NO_LOCATION(fmt, lvl, ##__VA_ARGS__) 101 | #endif 102 | 103 | // Trace logging - for detailed tracing 104 | #if defined(LOGGING_LEVEL_TRACE) && LOGGING_LEVEL_TRACE 105 | #define LogTrace(fmt, ...) LOG_FORMAT(fmt, @"trace", ##__VA_ARGS__) 106 | #else 107 | #define LogTrace(...) 108 | #endif 109 | 110 | // Info logging - for general, non-performance affecting information messages 111 | #if defined(LOGGING_LEVEL_INFO) && LOGGING_LEVEL_INFO 112 | #define LogInfo(fmt, ...) LOG_FORMAT(fmt, @"info", ##__VA_ARGS__) 113 | #else 114 | #define LogInfo(...) 115 | #endif 116 | 117 | // Error logging - only when there is an error to be logged 118 | #if defined(LOGGING_LEVEL_ERROR) && LOGGING_LEVEL_ERROR 119 | #define LogError(fmt, ...) LOG_FORMAT(fmt, @"***ERROR***", ##__VA_ARGS__) 120 | #else 121 | #define LogError(...) 122 | #endif 123 | 124 | // Debug logging - use only temporarily for highlighting and tracking down problems 125 | #if defined(LOGGING_LEVEL_DEBUG) && LOGGING_LEVEL_DEBUG 126 | #define LogDebug(fmt, ...) LOG_FORMAT(fmt, @"DEBUG", ##__VA_ARGS__) 127 | #else 128 | #define LogDebug(...) 129 | #endif 130 | -------------------------------------------------------------------------------- /Dependencies/XcodeEditor/XCFileOperationQueue.m: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // JASPER BLUES 4 | // Copyright 2012 Jasper Blues 5 | // All Rights Reserved. 6 | // 7 | // NOTICE: Jasper Blues permits you to use, modify, and distribute this file 8 | // in accordance with the terms of the license agreement accompanying it. 9 | // 10 | //////////////////////////////////////////////////////////////////////////////// 11 | 12 | 13 | 14 | #import "XCFileOperationQueue.h" 15 | 16 | @interface XCFileOperationQueue () 17 | 18 | - (NSString*)destinationPathFor:(NSString*)fileName inProjectDirectory:(NSString*)directory; 19 | 20 | - (void)performFileWrites; 21 | 22 | - (void)performCopyFrameworks; 23 | 24 | - (void)performFileDeletions; 25 | 26 | - (void)performCreateDirectories; 27 | 28 | @end 29 | 30 | 31 | @implementation XCFileOperationQueue 32 | 33 | /* ====================================================================================================================================== */ 34 | #pragma mark - Initialization & Destruction 35 | 36 | - (id)initWithBaseDirectory:(NSString*)baseDirectory 37 | { 38 | self = [super init]; 39 | if (self) 40 | { 41 | _baseDirectory = [baseDirectory copy]; 42 | _filesToWrite = [[NSMutableDictionary alloc] init]; 43 | _frameworksToCopy = [[NSMutableDictionary alloc] init]; 44 | _filesToDelete = [[NSMutableArray alloc] init]; 45 | _directoriesToCreate = [[NSMutableArray alloc] init]; 46 | } 47 | return self; 48 | } 49 | 50 | /* ====================================================================================================================================== */ 51 | #pragma mark - Interface Methods 52 | 53 | - (BOOL)fileWithName:(NSString*)name existsInProjectDirectory:(NSString*)directory 54 | { 55 | NSString* filePath = [self destinationPathFor:name inProjectDirectory:directory]; 56 | return [[NSFileManager defaultManager] fileExistsAtPath:filePath]; 57 | } 58 | 59 | 60 | - (void)queueTextFile:(NSString*)fileName inDirectory:(NSString*)directory withContents:(NSString*)contents 61 | { 62 | [_filesToWrite setObject:[contents dataUsingEncoding:NSUTF8StringEncoding] 63 | forKey:[self destinationPathFor:fileName inProjectDirectory:directory]]; 64 | } 65 | 66 | - (void)queueDataFile:(NSString*)fileName inDirectory:(NSString*)directory withContents:(NSData*)contents 67 | { 68 | [_filesToWrite setObject:contents forKey:[self destinationPathFor:fileName inProjectDirectory:directory]]; 69 | } 70 | 71 | 72 | - (void)queueFrameworkWithFilePath:(NSString*)filePath inDirectory:(NSString*)directory 73 | { 74 | 75 | NSURL* sourceUrl = [NSURL fileURLWithPath:filePath isDirectory:YES]; 76 | NSString* destinationPath = 77 | [[_baseDirectory stringByAppendingPathComponent:directory] stringByAppendingPathComponent:[filePath lastPathComponent]]; 78 | NSURL* destinationUrl = [NSURL fileURLWithPath:destinationPath isDirectory:YES]; 79 | [_frameworksToCopy setObject:sourceUrl forKey:destinationUrl]; 80 | } 81 | 82 | - (void)queueDeletion:(NSString*)filePath 83 | { 84 | NSLog(@"Queue deletion at: %@", filePath); 85 | [_filesToDelete addObject:filePath]; 86 | } 87 | 88 | - (void)queueDirectory:(NSString*)withName inDirectory:(NSString*)parentDirectory 89 | { 90 | [_directoriesToCreate addObject:[self destinationPathFor:withName inProjectDirectory:parentDirectory]]; 91 | } 92 | 93 | - (void)commitFileOperations 94 | { 95 | [self performFileWrites]; 96 | [self performCopyFrameworks]; 97 | [self performFileDeletions]; 98 | [self performCreateDirectories]; 99 | } 100 | 101 | 102 | /* ====================================================================================================================================== */ 103 | #pragma mark - Private Methods 104 | 105 | - (NSString*)destinationPathFor:(NSString*)fileName inProjectDirectory:(NSString*)directory 106 | { 107 | return [[_baseDirectory stringByAppendingPathComponent:directory] stringByAppendingPathComponent:fileName]; 108 | } 109 | 110 | - (void)performFileWrites 111 | { 112 | [_filesToWrite enumerateKeysAndObjectsUsingBlock:^(NSString* filePath, NSData* data, BOOL* stop) 113 | { 114 | NSError* error = nil; 115 | if (![data writeToFile:filePath options:NSDataWritingAtomic error:&error]) 116 | { 117 | [NSException raise:NSInternalInconsistencyException format:@"Error writing file at filePath: %@, error: %@", filePath, error]; 118 | } 119 | }]; 120 | [_filesToWrite removeAllObjects]; 121 | } 122 | 123 | - (void)performCopyFrameworks 124 | { 125 | [_frameworksToCopy enumerateKeysAndObjectsUsingBlock:^(NSURL* destinationUrl, NSURL* frameworkPath, BOOL* stop) 126 | { 127 | 128 | NSFileManager* fileManager = [NSFileManager defaultManager]; 129 | 130 | if ([fileManager fileExistsAtPath:[destinationUrl path]]) 131 | { 132 | [fileManager removeItemAtURL:destinationUrl error:nil]; 133 | } 134 | NSError* error = nil; 135 | if (![fileManager copyItemAtURL:frameworkPath toURL:destinationUrl error:&error]) 136 | { 137 | [NSException raise:NSInternalInconsistencyException format:@"Error writing file at filePath: %@", 138 | [frameworkPath absoluteString]]; 139 | } 140 | }]; 141 | [_frameworksToCopy removeAllObjects]; 142 | } 143 | 144 | - (void)performFileDeletions 145 | { 146 | for (NSString* filePath in [_filesToDelete reverseObjectEnumerator]) 147 | { 148 | NSString* fullPath = [_baseDirectory stringByAppendingPathComponent:filePath]; 149 | NSError* error = nil; 150 | 151 | if (![[NSFileManager defaultManager] removeItemAtPath:fullPath error:&error]) 152 | { 153 | NSLog(@"failed to remove item at path; error == %@", error); 154 | [NSException raise:NSInternalInconsistencyException format:@"Error deleting file at filePath: %@", filePath]; 155 | } 156 | else 157 | { 158 | NSLog(@"Deleted: %@", fullPath); 159 | } 160 | } 161 | [_filesToDelete removeAllObjects]; 162 | } 163 | 164 | - (void)performCreateDirectories 165 | { 166 | for (NSString* filePath in _directoriesToCreate) 167 | { 168 | NSFileManager* fileManager = [NSFileManager defaultManager]; 169 | if (![fileManager fileExistsAtPath:filePath]) 170 | { 171 | if (![fileManager createDirectoryAtPath:filePath withIntermediateDirectories:YES attributes:nil error:nil]) 172 | { 173 | [NSException raise:NSInvalidArgumentException format:@"Error: Create folder failed %@", filePath]; 174 | } 175 | } 176 | } 177 | } 178 | 179 | 180 | @end -------------------------------------------------------------------------------- /Dependencies/XcodeEditor/XCSubProjectDefinition.m: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // JASPER BLUES 4 | // Copyright 2012 Jasper Blues 5 | // All Rights Reserved. 6 | // 7 | // NOTICE: Jasper Blues permits you to use, modify, and distribute this file 8 | // in accordance with the terms of the license agreement accompanying it. 9 | // 10 | //////////////////////////////////////////////////////////////////////////////// 11 | 12 | 13 | 14 | #import "XCProject.h" 15 | #import "XCProject+SubProject.h" 16 | #import "XCSubProjectDefinition.h" 17 | 18 | @interface XCSubProjectDefinition () 19 | @property(nonatomic, strong, readwrite) NSString* relativePath; 20 | @end 21 | 22 | @implementation XCSubProjectDefinition 23 | 24 | @synthesize name = _name; 25 | @synthesize path = _path; 26 | @synthesize type = _type; 27 | @synthesize parentProject = _parentProject; 28 | @synthesize subProject = _subProject; 29 | @synthesize relativePath = _relativePath; 30 | @synthesize key = _key; 31 | @synthesize fullProjectPath = _fullProjectPath; 32 | 33 | /* ====================================================================================================================================== */ 34 | #pragma mark - Class Methods 35 | 36 | + (XCSubProjectDefinition*)withName:(NSString*)name path:(NSString*)path parentProject:(XCProject*)parentProject 37 | { 38 | 39 | return [[XCSubProjectDefinition alloc] initWithName:name path:path parentProject:parentProject]; 40 | } 41 | 42 | /* ====================================================================================================================================== */ 43 | #pragma mark - Initialization & Destruction 44 | 45 | // Note - _path is most often going to be an absolute path. The method pathRelativeToProjectRoot below should be 46 | // used to get the form that's stored in the main project file. 47 | - (id)initWithName:(NSString*)name path:(NSString*)path parentProject:(XCProject*)parentProject 48 | { 49 | self = [super init]; 50 | if (self) 51 | { 52 | _name = [name copy]; 53 | _path = [path copy]; 54 | _type = XcodeProject; 55 | _parentProject = parentProject; 56 | _subProject = [[XCProject alloc] initWithFilePath:[NSString stringWithFormat:@"%@/%@.xcodeproj", path, name]]; 57 | } 58 | return self; 59 | } 60 | 61 | /* ====================================================================================================================================== */ 62 | #pragma mark - Interface Methods 63 | 64 | - (NSString*)projectFileName 65 | { 66 | return [_name stringByAppendingString:@".xcodeproj"]; 67 | } 68 | 69 | - (NSString*)fullPathName 70 | { 71 | return [NSString stringWithFormat:@"%@/%@", _path, [_name stringByAppendingString:@".xcodeproj"]]; 72 | } 73 | 74 | // returns an array of names of the build products of this project 75 | - (NSArray*)buildProductNames 76 | { 77 | NSMutableArray* results = [NSMutableArray array]; 78 | NSDictionary* objects = [_subProject objects]; 79 | [objects enumerateKeysAndObjectsUsingBlock:^(NSString* key, NSDictionary* obj, BOOL* stop) 80 | { 81 | if ([[obj valueForKey:@"isa"] asMemberType] == PBXProjectType) 82 | { 83 | NSString* productRefGroupKey = [obj valueForKey:@"productRefGroup"]; 84 | NSDictionary* products = [objects valueForKey:productRefGroupKey]; 85 | NSArray* children = [products valueForKey:@"children"]; 86 | for (NSString* childKey in children) 87 | { 88 | NSDictionary* child = [objects valueForKey:childKey]; 89 | [results addObject:[child valueForKey:@"path"]]; 90 | } 91 | } 92 | }]; 93 | return results; 94 | } 95 | 96 | // returns the key of the PBXFileReference of the xcodeproj file 97 | - (NSString*)projectKey 98 | { 99 | if (_key == nil) 100 | { 101 | NSArray* xcodeprojKeys = 102 | [_parentProject keysForProjectObjectsOfType:PBXFileReferenceType withIdentifier:[self pathRelativeToProjectRoot] singleton:YES 103 | required:YES]; 104 | _key = [[xcodeprojKeys objectAtIndex:0] copy]; 105 | } 106 | return [_key copy]; 107 | } 108 | 109 | - (void)initFullProjectPath:(NSString*)fullProjectPath groupPath:(NSString*)groupPath 110 | { 111 | if (groupPath != nil) 112 | { 113 | NSMutableArray* fullPathComponents = [[fullProjectPath pathComponents] mutableCopy]; 114 | [fullPathComponents removeLastObject]; 115 | fullProjectPath = [[NSString pathWithComponents:fullPathComponents] stringByAppendingFormat:@"/%@", groupPath]; 116 | } 117 | _fullProjectPath = [fullProjectPath copy]; 118 | 119 | } 120 | 121 | // compares the given path to the filePath of the project, and returns a relative version. _fullProjectPath, which has 122 | // to hve been previously set, is the full path to the project *plus* the path to the xcodeproj's group, if any. 123 | - (NSString*)pathRelativeToProjectRoot 124 | { 125 | if (_relativePath == nil) 126 | { 127 | if (_fullProjectPath == nil) 128 | { 129 | [NSException raise:NSInvalidArgumentException format:@"fullProjectPath has not been set"]; 130 | } 131 | NSMutableArray* projectPathComponents = [[_fullProjectPath pathComponents] mutableCopy]; 132 | NSArray* objectPathComponents = [[self fullPathName] pathComponents]; 133 | NSString* convertedPath = @""; 134 | 135 | // skip over path components from root that are equal 136 | NSInteger limit = 137 | ([projectPathComponents count] < [objectPathComponents count]) ? [projectPathComponents count] : [objectPathComponents count]; 138 | NSInteger index1 = 0; 139 | for (; index1 < limit; index1++) 140 | { 141 | if ([[projectPathComponents objectAtIndex:index1] isEqualToString:[objectPathComponents objectAtIndex:index1]]) 142 | { 143 | continue; 144 | } 145 | else 146 | { 147 | break; 148 | } 149 | } 150 | // insert "../" for each remaining path component in project's xcodeproj path 151 | for (NSInteger index2 = 0; index2 < ([projectPathComponents count] - index1); index2++) 152 | { 153 | convertedPath = [convertedPath stringByAppendingString:@"../"]; 154 | } 155 | // tack on the unique part of the object's path 156 | for (NSInteger index3 = index1; index3 < [objectPathComponents count] - 1; index3++) 157 | { 158 | convertedPath = [convertedPath stringByAppendingFormat:@"%@/", [objectPathComponents objectAtIndex:index3]]; 159 | } 160 | _relativePath = [[convertedPath stringByAppendingString:[objectPathComponents lastObject]] copy]; 161 | } 162 | return [_relativePath copy]; 163 | } 164 | 165 | 166 | /* ====================================================================================================================================== */ 167 | #pragma mark - Utility Methods 168 | 169 | - (NSString*)description 170 | { 171 | return [NSString stringWithFormat:@"XcodeprojDefinition: sourceFileName = %@, path=%@, type=%d", _name, _path, _type]; 172 | } 173 | 174 | @end -------------------------------------------------------------------------------- /Dependencies/XcodeEditor/XCSourceFile.m: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // JASPER BLUES 4 | // Copyright 2012 Jasper Blues 5 | // All Rights Reserved. 6 | // 7 | // NOTICE: Jasper Blues permits you to use, modify, and distribute this file 8 | // in accordance with the terms of the license agreement accompanying it. 9 | // 10 | //////////////////////////////////////////////////////////////////////////////// 11 | 12 | 13 | 14 | #import "XCSourceFile.h" 15 | #import "XCProject.h" 16 | #import "Utils/XCKeyBuilder.h" 17 | #import "XCGroup.h" 18 | 19 | @implementation XCSourceFile 20 | 21 | @synthesize type = _type; 22 | @synthesize key = _key; 23 | @synthesize sourceTree = _sourceTree; 24 | 25 | /* ====================================================================================================================================== */ 26 | #pragma mark - Class Methods 27 | 28 | + (XCSourceFile*)sourceFileWithProject:(XCProject*)project key:(NSString*)key type:(XcodeSourceFileType)type name:(NSString*)name 29 | sourceTree:(NSString*)_tree path:(NSString*)path 30 | { 31 | return [[XCSourceFile alloc] initWithProject:project key:key type:type name:name sourceTree:_tree path:path]; 32 | } 33 | 34 | 35 | /* ====================================================================================================================================== */ 36 | #pragma mark - Initialization & Destruction 37 | 38 | - (id)initWithProject:(XCProject*)project key:(NSString*)key type:(XcodeSourceFileType)type name:(NSString*)name sourceTree:(NSString*)tree 39 | path:(NSString*)path 40 | { 41 | 42 | self = [super init]; 43 | if (self) 44 | { 45 | _project = project; 46 | _key = [key copy]; 47 | _type = type; 48 | _name = [name copy]; 49 | _sourceTree = [tree copy]; 50 | _path = [path copy]; 51 | } 52 | return self; 53 | } 54 | 55 | 56 | /* ====================================================================================================================================== */ 57 | #pragma mark - Interface Methods 58 | 59 | // Goes to the entry for this object in the project and sets a value for one of the keys, such as name, path, etc. 60 | - (void)setValue:(id)val forProjectItemPropertyWithKey:(NSString*)key 61 | { 62 | NSMutableDictionary* obj = [[[_project objects] objectForKey:_key] mutableCopy]; 63 | if (nil == obj) 64 | { 65 | [NSException raise:@"Project item not found" format:@"Project item with key %@ not found.", _key]; 66 | } 67 | [obj setValue:val forKey:key]; 68 | [[_project objects] setValue:obj forKey:_key]; 69 | } 70 | 71 | 72 | - (NSString*)name 73 | { 74 | return _name; 75 | } 76 | 77 | - (void)setName:(NSString*)name 78 | { 79 | id old = _name; 80 | _name = [name copy]; 81 | 82 | [self setValue:name forProjectItemPropertyWithKey:@"name"]; 83 | } 84 | 85 | 86 | - (NSString*)path 87 | { 88 | return _path; 89 | } 90 | 91 | - (void)setPath:(NSString*)path 92 | { 93 | id old = _path; 94 | _path = [path copy]; 95 | 96 | [self setValue:path forProjectItemPropertyWithKey:@"path"]; 97 | } 98 | 99 | - (BOOL)isBuildFile 100 | { 101 | if ([self canBecomeBuildFile] && _isBuildFile == nil) 102 | { 103 | id old = _isBuildFile; 104 | _isBuildFile = [[NSNumber numberWithBool:NO] copy]; 105 | [[_project objects] enumerateKeysAndObjectsUsingBlock:^(NSString* key, NSDictionary* obj, BOOL* stop) 106 | { 107 | if ([[obj valueForKey:@"isa"] asMemberType] == PBXBuildFileType) 108 | { 109 | if ([[obj valueForKey:@"fileRef"] isEqualToString:_key]) 110 | { 111 | _isBuildFile = nil; 112 | 113 | _isBuildFile = [[NSNumber numberWithBool:YES] copy]; 114 | } 115 | } 116 | }]; 117 | } 118 | return [_isBuildFile boolValue]; 119 | } 120 | 121 | - (BOOL)canBecomeBuildFile 122 | { 123 | return _type == SourceCodeObjC || _type == SourceCodeObjCPlusPlus || _type == SourceCodeCPlusPlus || _type == XibFile || _type == 124 | Framework || _type == ImageResourcePNG || _type == HTML || _type == Bundle || _type == Archive; 125 | } 126 | 127 | 128 | - (XcodeMemberType)buildPhase 129 | { 130 | if (_type == SourceCodeObjC || _type == SourceCodeObjCPlusPlus || _type == SourceCodeCPlusPlus || _type == XibFile) 131 | { 132 | return PBXSourcesBuildPhaseType; 133 | } 134 | else if (_type == Framework) 135 | { 136 | return PBXFrameworksBuildPhaseType; 137 | } 138 | else if (_type == ImageResourcePNG || _type == HTML || _type == Bundle) 139 | { 140 | return PBXResourcesBuildPhaseType; 141 | } 142 | else if (_type == Archive) 143 | { 144 | return PBXFrameworksBuildPhaseType; 145 | } 146 | return PBXNilType; 147 | } 148 | 149 | - (NSString*)buildFileKey 150 | { 151 | if (_buildFileKey == nil) 152 | { 153 | [[_project objects] enumerateKeysAndObjectsUsingBlock:^(NSString* key, NSDictionary* obj, BOOL* stop) 154 | { 155 | if ([[obj valueForKey:@"isa"] asMemberType] == PBXBuildFileType) 156 | { 157 | if ([[obj valueForKey:@"fileRef"] isEqualToString:_key]) 158 | { 159 | _buildFileKey = [key copy]; 160 | } 161 | } 162 | }]; 163 | } 164 | return [_buildFileKey copy]; 165 | 166 | } 167 | 168 | 169 | - (void)becomeBuildFile 170 | { 171 | if (![self isBuildFile]) 172 | { 173 | if ([self canBecomeBuildFile]) 174 | { 175 | NSMutableDictionary* sourceBuildFile = [NSMutableDictionary dictionary]; 176 | [sourceBuildFile setObject:[NSString stringFromMemberType:PBXBuildFileType] forKey:@"isa"]; 177 | [sourceBuildFile setObject:_key forKey:@"fileRef"]; 178 | NSString* buildFileKey = [[XCKeyBuilder forItemNamed:[_name stringByAppendingString:@".buildFile"]] build]; 179 | [[_project objects] setObject:sourceBuildFile forKey:buildFileKey]; 180 | } 181 | else if (_type == Framework) 182 | { 183 | [NSException raise:NSInvalidArgumentException format:@"Add framework to target not implemented yet."]; 184 | } 185 | else 186 | { 187 | [NSException raise:NSInvalidArgumentException format:@"Project file of type %@ can't become a build file.", 188 | NSStringFromXCSourceFileType(_type)]; 189 | } 190 | 191 | } 192 | } 193 | 194 | /* ====================================================================================================================================== */ 195 | #pragma mark - Protocol Methods 196 | 197 | - (XcodeMemberType)groupMemberType 198 | { 199 | return PBXFileReferenceType; 200 | } 201 | 202 | - (NSString*)displayName 203 | { 204 | return _name; 205 | } 206 | 207 | - (NSString*)pathRelativeToProjectRoot 208 | { 209 | NSString* parentPath = [[_project groupForGroupMemberWithKey:_key] pathRelativeToProjectRoot]; 210 | NSString* result = [parentPath stringByAppendingPathComponent:_name]; 211 | return result; 212 | } 213 | 214 | /* ====================================================================================================================================== */ 215 | #pragma mark - Utility Methods 216 | 217 | - (NSString*)description 218 | { 219 | return [NSString stringWithFormat:@"Project file: key=%@, name=%@, fullPath=%@", _key, _name, [self pathRelativeToProjectRoot]]; 220 | } 221 | 222 | 223 | @end 224 | 225 | -------------------------------------------------------------------------------- /Dependencies/XcodeEditor/XCBuildConfiguration.m: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // JASPER BLUES 4 | // Copyright 2012 Jasper Blues 5 | // All Rights Reserved. 6 | // 7 | // NOTICE: Jasper Blues permits you to use, modify, and distribute this file 8 | // in accordance with the terms of the license agreement accompanying it. 9 | // 10 | //////////////////////////////////////////////////////////////////////////////// 11 | 12 | 13 | 14 | #import "XCBuildConfiguration.h" 15 | #import "XCGroup.h" 16 | #import "XCKeyBuilder.h" 17 | #import "XCProject.h" 18 | #import "XCSourceFile.h" 19 | #import "OCLogTemplate.h" 20 | 21 | @implementation XCBuildConfiguration 22 | 23 | /* ====================================================================================================================================== */ 24 | #pragma mark - Class Methods 25 | 26 | + (NSDictionary*)buildConfigurationsFromArray:(NSArray*)array inProject:(XCProject*)project 27 | { 28 | NSMutableDictionary* configurations = [NSMutableDictionary dictionary]; 29 | 30 | for (NSString* buildConfigurationKey in array) 31 | { 32 | NSDictionary* buildConfiguration = [[project objects] objectForKey:buildConfigurationKey]; 33 | 34 | if ([[buildConfiguration valueForKey:@"isa"] asMemberType] == XCBuildConfigurationType) 35 | { 36 | XCBuildConfiguration* configuration = [configurations objectForKey:[buildConfiguration objectForKey:@"name"]]; 37 | if (!configuration) 38 | { 39 | configuration = [[XCBuildConfiguration alloc] initWithProject:project key:buildConfigurationKey]; 40 | 41 | [configurations setObject:configuration forKey:[buildConfiguration objectForKey:@"name"]]; 42 | } 43 | 44 | 45 | XCSourceFile* configurationFile = [project fileWithKey:[buildConfiguration objectForKey:@"baseConfigurationReference"]]; 46 | if (configurationFile) 47 | { 48 | NSString* path = configurationFile.path; 49 | 50 | if (![[NSFileManager defaultManager] fileExistsAtPath:path]) 51 | { 52 | XCGroup* group = [project groupWithSourceFile:configurationFile]; 53 | path = [[group pathRelativeToParent] stringByAppendingPathComponent:path]; 54 | } 55 | 56 | if (![[NSFileManager defaultManager] fileExistsAtPath:path]) 57 | { 58 | path = [[[project filePath] stringByDeletingLastPathComponent] stringByAppendingPathComponent:path]; 59 | } 60 | 61 | if (![[NSFileManager defaultManager] fileExistsAtPath:path]) 62 | { 63 | path = [[[project filePath] stringByDeletingLastPathComponent] stringByAppendingPathComponent:configurationFile.path]; 64 | } 65 | 66 | if (![[NSFileManager defaultManager] fileExistsAtPath:path]) 67 | { 68 | [NSException raise:@"XCConfig not found" format:@"Unable to find XCConfig file at %@", path]; 69 | } 70 | 71 | } 72 | 73 | [configuration addBuildSettings:[buildConfiguration objectForKey:@"buildSettings"]]; 74 | } 75 | } 76 | 77 | return configurations; 78 | } 79 | 80 | + (NSString*)duplicatedBuildConfigurationListWithKey:(NSString*)buildConfigurationListKey inProject:(XCProject*)project 81 | withBuildConfigurationVisitor:(void (^)(NSMutableDictionary*))buildConfigurationVisitor 82 | { 83 | 84 | NSDictionary* buildConfigurationList = project.objects[buildConfigurationListKey]; 85 | NSMutableDictionary* dupBuildConfigurationList = [buildConfigurationList mutableCopy]; 86 | 87 | NSMutableArray* dupBuildConfigurations = [NSMutableArray array]; 88 | 89 | for (NSString* buildConfigurationKey in buildConfigurationList[@"buildConfigurations"]) 90 | { 91 | [dupBuildConfigurations addObject:[self duplicatedBuildConfigurationWithKey:buildConfigurationKey inProject:project 92 | withBuildConfigurationVisitor:buildConfigurationVisitor]]; 93 | } 94 | 95 | dupBuildConfigurationList[@"buildConfigurations"] = dupBuildConfigurations; 96 | 97 | NSString* dupBuildConfigurationListKey = [[XCKeyBuilder createUnique] build]; 98 | 99 | project.objects[dupBuildConfigurationListKey] = dupBuildConfigurationList; 100 | 101 | return dupBuildConfigurationListKey; 102 | } 103 | 104 | /* ====================================================================================================================================== */ 105 | #pragma mark - Initialization & Destruction 106 | 107 | - (instancetype)initWithProject:(XCProject*)project key:(NSString*)key 108 | { 109 | self = [super init]; 110 | if (self) 111 | { 112 | _project = project; 113 | _key = [key copy]; 114 | 115 | _buildSettings = [[NSMutableDictionary alloc] init]; 116 | _xcconfigSettings = [[NSMutableDictionary alloc] init]; 117 | } 118 | return self; 119 | } 120 | 121 | - (id)init 122 | { 123 | return [self initWithProject:nil key:nil]; 124 | } 125 | 126 | 127 | /* ====================================================================================================================================== */ 128 | #pragma mark - Interface Methods 129 | 130 | - (NSDictionary*)specifiedBuildSettings 131 | { 132 | return [_buildSettings copy]; 133 | } 134 | 135 | - (void)addBuildSettings:(NSDictionary*)buildSettings 136 | { 137 | [_xcconfigSettings removeObjectsForKeys:[buildSettings allKeys]]; 138 | [_buildSettings addEntriesFromDictionary:buildSettings]; 139 | } 140 | 141 | - (void)addOrReplaceSetting:(id )setting forKey:(NSString*)key 142 | { 143 | NSDictionary* settings = [NSDictionary dictionaryWithObject:setting forKey:key]; 144 | [self addBuildSettings:settings]; 145 | 146 | LogDebug(@"$$$$$$$$$$$ before: %@", [_project.objects objectForKey:_key]); 147 | 148 | NSMutableDictionary* dict = [[[_project objects] objectForKey:_key] mutableCopy]; 149 | [dict setValue:_buildSettings forKey:@"buildSettings"]; 150 | [_project.objects setValue:dict forKey:_key]; 151 | 152 | LogDebug(@"The settings: %@", [_project.objects objectForKey:_key]); 153 | 154 | } 155 | 156 | 157 | - (id )valueForKey:(NSString*)key 158 | { 159 | id value = [_buildSettings objectForKey:key]; 160 | if (!value) 161 | { 162 | value = [_xcconfigSettings objectForKey:key]; 163 | } 164 | return value; 165 | } 166 | 167 | /* ====================================================================================================================================== */ 168 | #pragma mark - Utility Methods 169 | 170 | - (NSString*)description 171 | { 172 | NSMutableString* description = [[super description] mutableCopy]; 173 | 174 | [description appendFormat:@"build settings: %@, inherited: %@", _buildSettings, _xcconfigSettings]; 175 | 176 | return description; 177 | } 178 | 179 | 180 | /* ====================================================================================================================================== */ 181 | #pragma mark - Private Methods 182 | 183 | + (NSString*)duplicatedBuildConfigurationWithKey:(NSString*)buildConfigurationKey inProject:(XCProject*)project 184 | withBuildConfigurationVisitor:(void (^)(NSMutableDictionary*))buildConfigurationVisitor 185 | { 186 | NSDictionary* buildConfiguration = project.objects[buildConfigurationKey]; 187 | NSMutableDictionary* dupBuildConfiguration = [buildConfiguration mutableCopy]; 188 | 189 | buildConfigurationVisitor(dupBuildConfiguration); 190 | 191 | NSString* dupBuildConfigurationKey = [[XCKeyBuilder createUnique] build]; 192 | 193 | project.objects[dupBuildConfigurationKey] = dupBuildConfiguration; 194 | 195 | return dupBuildConfigurationKey; 196 | } 197 | 198 | @end 199 | -------------------------------------------------------------------------------- /Dependencies/XcodeEditor/XCProject.m: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // JASPER BLUES 4 | // Copyright 2012 - 2013 Jasper Blues 5 | // All Rights Reserved. 6 | // 7 | // NOTICE: Jasper Blues permits you to use, modify, and distribute this file 8 | // in accordance with the terms of the license agreement accompanying it. 9 | // 10 | //////////////////////////////////////////////////////////////////////////////// 11 | 12 | 13 | #import "XCProject.h" 14 | #import "XCGroup.h" 15 | #import "XCSourceFile.h" 16 | #import "XCTarget.h" 17 | #import "XCFileOperationQueue.h" 18 | #import "XCBuildConfiguration.h" 19 | 20 | 21 | @implementation XCProject 22 | 23 | 24 | @synthesize fileOperationQueue = _fileOperationQueue; 25 | 26 | /* ====================================================================================================================================== */ 27 | #pragma mark - Class Methods 28 | 29 | + (XCProject*)projectWithFilePath:(NSString*)filePath 30 | { 31 | return [[XCProject alloc] initWithFilePath:filePath]; 32 | } 33 | 34 | 35 | /* ====================================================================================================================================== */ 36 | #pragma mark - Initialization & Destruction 37 | 38 | - (id)initWithFilePath:(NSString*)filePath 39 | { 40 | if ((self = [super init])) 41 | { 42 | _filePath = [filePath copy]; 43 | _dataStore = [[NSMutableDictionary alloc] initWithContentsOfFile:[_filePath stringByAppendingPathComponent:@"project.pbxproj"]]; 44 | 45 | if (!_dataStore) 46 | { 47 | [NSException raise:XCProjectNotFoundException format:@"Project file not found at file path %@", _filePath]; 48 | } 49 | 50 | _fileOperationQueue = [[XCFileOperationQueue alloc] initWithBaseDirectory:[_filePath stringByDeletingLastPathComponent]]; 51 | 52 | } 53 | return self; 54 | } 55 | 56 | /* ====================================================================================================================================== */ 57 | #pragma mark - Interface Methods 58 | 59 | #pragma mark Files 60 | 61 | - (NSArray*)files 62 | { 63 | NSMutableArray* results = [NSMutableArray array]; 64 | [[self objects] enumerateKeysAndObjectsUsingBlock:^(NSString* key, NSDictionary* obj, BOOL* stop) 65 | { 66 | if ([[obj valueForKey:@"isa"] asMemberType] == PBXFileReferenceType) 67 | { 68 | XcodeSourceFileType fileType = XCSourceFileTypeFromStringRepresentation([obj valueForKey:@"lastKnownFileType"]); 69 | NSString* path = [obj valueForKey:@"path"]; 70 | NSString* sourceTree = [obj valueForKey:@"sourceTree"]; 71 | [results addObject:[XCSourceFile sourceFileWithProject:self key:key type:fileType name:path 72 | sourceTree:(sourceTree ? sourceTree : @"") path:nil]]; 73 | } 74 | }]; 75 | return results; 76 | } 77 | 78 | - (XCSourceFile*)fileWithKey:(NSString*)key 79 | { 80 | NSDictionary* obj = [[self objects] valueForKey:key]; 81 | if (obj && ([[obj valueForKey:@"isa"] asMemberType] == PBXFileReferenceType || [[obj valueForKey:@"isa"] asMemberType] == 82 | PBXReferenceProxyType)) 83 | { 84 | XcodeSourceFileType fileType = XCSourceFileTypeFromStringRepresentation([obj valueForKey:@"lastKnownFileType"]); 85 | 86 | NSString* name = [obj valueForKey:@"name"]; 87 | NSString* sourceTree = [obj valueForKey:@"sourceTree"]; 88 | 89 | if (name == nil) 90 | { 91 | name = [obj valueForKey:@"path"]; 92 | } 93 | return [XCSourceFile sourceFileWithProject:self key:key type:fileType name:name sourceTree:(sourceTree ? sourceTree : @"") 94 | path:[obj valueForKey:@"path"]]; 95 | } 96 | return nil; 97 | } 98 | 99 | - (XCSourceFile*)fileWithName:(NSString*)name 100 | { 101 | for (XCSourceFile* projectFile in [self files]) 102 | { 103 | if ([[projectFile name] isEqualToString:name]) 104 | { 105 | return projectFile; 106 | } 107 | } 108 | return nil; 109 | } 110 | 111 | 112 | - (NSArray*)headerFiles 113 | { 114 | return [self projectFilesOfType:SourceCodeHeader]; 115 | } 116 | 117 | - (NSArray*)objectiveCFiles 118 | { 119 | return [self projectFilesOfType:SourceCodeObjC]; 120 | } 121 | 122 | - (NSArray*)objectiveCPlusPlusFiles 123 | { 124 | return [self projectFilesOfType:SourceCodeObjCPlusPlus]; 125 | } 126 | 127 | 128 | - (NSArray*)xibFiles 129 | { 130 | return [self projectFilesOfType:XibFile]; 131 | } 132 | 133 | - (NSArray*)imagePNGFiles 134 | { 135 | return [self projectFilesOfType:ImageResourcePNG]; 136 | } 137 | 138 | // need this value to construct relative path in XcodeprojDefinition 139 | - (NSString*)filePath 140 | { 141 | return _filePath; 142 | } 143 | 144 | /* ====================================================================================================================================== */ 145 | #pragma mark Groups 146 | 147 | - (NSArray*)groups 148 | { 149 | 150 | NSMutableArray* results = [[NSMutableArray alloc] init]; 151 | [[_dataStore objectForKey:@"objects"] enumerateKeysAndObjectsUsingBlock:^(NSString* key, NSDictionary* obj, BOOL* stop) 152 | { 153 | 154 | if ([[obj valueForKey:@"isa"] asMemberType] == PBXGroupType || [[obj valueForKeyPath:@"isa"] asMemberType] == PBXVariantGroupType) 155 | { 156 | [results addObject:[self groupWithKey:key]]; 157 | } 158 | }]; 159 | return results; 160 | } 161 | 162 | //TODO: Optimize this implementation. 163 | - (XCGroup*)rootGroup 164 | { 165 | for (XCGroup* group in [self groups]) 166 | { 167 | if ([group isRootGroup]) 168 | { 169 | return group; 170 | } 171 | } 172 | return nil; 173 | } 174 | 175 | - (NSArray*)rootGroups 176 | { 177 | XCGroup* group = [self rootGroup]; 178 | if (group) 179 | { 180 | return [NSArray arrayWithObject:group]; 181 | } 182 | 183 | NSMutableArray* results = [NSMutableArray array]; 184 | for (XCGroup* group in [self groups]) 185 | { 186 | if ([group parentGroup] == nil) 187 | { 188 | [results addObject:group]; 189 | } 190 | } 191 | 192 | return [results copy]; 193 | } 194 | 195 | - (XCGroup*)groupWithKey:(NSString*)key 196 | { 197 | XCGroup* group = [_groups objectForKey:key]; 198 | if (group) 199 | { 200 | return group; 201 | } 202 | 203 | NSDictionary* obj = [[self objects] objectForKey:key]; 204 | if (obj && ([[obj valueForKey:@"isa"] asMemberType] == PBXGroupType || [[obj valueForKey:@"isa"] asMemberType] == PBXVariantGroupType)) 205 | { 206 | 207 | NSString* name = [obj valueForKey:@"name"]; 208 | NSString* path = [obj valueForKey:@"path"]; 209 | NSArray* children = [obj valueForKey:@"children"]; 210 | XCGroup* group = [XCGroup groupWithProject:self key:key alias:name path:path children:children]; 211 | 212 | [_groups setObject:group forKey:key]; 213 | 214 | return group; 215 | } 216 | return nil; 217 | } 218 | 219 | - (XCGroup*)groupForGroupMemberWithKey:(NSString*)key 220 | { 221 | for (XCGroup* group in [self groups]) 222 | { 223 | if ([group memberWithKey:key]) 224 | { 225 | return group; 226 | } 227 | } 228 | return nil; 229 | } 230 | 231 | - (XCGroup*)groupWithSourceFile:(XCSourceFile*)sourceFile 232 | { 233 | for (XCGroup* group in [self groups]) 234 | { 235 | for (id member in [group members]) 236 | { 237 | if ([member isKindOfClass:[XCSourceFile class]] && [[sourceFile key] isEqualToString:[member key]]) 238 | { 239 | return group; 240 | } 241 | } 242 | } 243 | return nil; 244 | } 245 | 246 | //TODO: This could fail if the path attribute on a given group is more than one directory. Start with candidates and 247 | //TODO: search backwards. 248 | - (XCGroup*)groupWithPathFromRoot:(NSString*)path 249 | { 250 | NSArray* pathItems = [path componentsSeparatedByString:@"/"]; 251 | XCGroup* currentGroup = [self rootGroup]; 252 | for (NSString* pathItem in pathItems) 253 | { 254 | id group = [currentGroup memberWithDisplayName:pathItem]; 255 | if ([group isKindOfClass:[XCGroup class]]) 256 | { 257 | currentGroup = group; 258 | } 259 | else 260 | { 261 | return nil; 262 | } 263 | } 264 | return currentGroup; 265 | } 266 | 267 | 268 | /* ====================================================================================================================================== */ 269 | #pragma mark targets 270 | 271 | - (NSArray*)targets 272 | { 273 | if (_targets == nil) 274 | { 275 | _targets = [[NSMutableArray alloc] init]; 276 | [[self objects] enumerateKeysAndObjectsUsingBlock:^(NSString* key, NSDictionary* obj, BOOL* stop) 277 | { 278 | if ([[obj valueForKey:@"isa"] asMemberType] == PBXNativeTargetType) 279 | { 280 | XCTarget* target = 281 | [XCTarget targetWithProject:self key:key name:[obj valueForKey:@"name"] productName:[obj valueForKey:@"productName"] 282 | productReference:[obj valueForKey:@"productReference"]]; 283 | [_targets addObject:target]; 284 | } 285 | }]; 286 | } 287 | return _targets; 288 | } 289 | 290 | - (XCTarget*)targetWithName:(NSString*)name 291 | { 292 | for (XCTarget* target in [self targets]) 293 | { 294 | if ([[target name] isEqualToString:name]) 295 | { 296 | return target; 297 | } 298 | } 299 | return nil; 300 | } 301 | 302 | - (void)save 303 | { 304 | [_fileOperationQueue commitFileOperations]; 305 | [_dataStore writeToFile:[_filePath stringByAppendingPathComponent:@"project.pbxproj"] atomically:YES]; 306 | 307 | NSLog(@"Saved project"); 308 | } 309 | 310 | - (NSMutableDictionary*)objects 311 | { 312 | return [_dataStore objectForKey:@"objects"]; 313 | } 314 | 315 | - (NSMutableDictionary*)dataStore 316 | { 317 | return _dataStore; 318 | } 319 | 320 | - (void)dropCache 321 | { 322 | _targets = nil; 323 | _configurations = nil; 324 | _rootObjectKey = nil; 325 | } 326 | 327 | 328 | - (NSDictionary*)configurations 329 | { 330 | if (_configurations == nil) 331 | { 332 | NSString* buildConfigurationRootSectionKey = 333 | [[[self objects] objectForKey:[self rootObjectKey]] objectForKey:@"buildConfigurationList"]; 334 | NSDictionary* buildConfigurationDictionary = [[self objects] objectForKey:buildConfigurationRootSectionKey]; 335 | _configurations = 336 | [[XCBuildConfiguration buildConfigurationsFromArray:[buildConfigurationDictionary objectForKey:@"buildConfigurations"] 337 | inProject:self] mutableCopy]; 338 | _defaultConfigurationName = [[buildConfigurationDictionary objectForKey:@"defaultConfigurationName"] copy]; 339 | } 340 | 341 | return [_configurations copy]; 342 | } 343 | 344 | - (NSDictionary*)configurationWithName:(NSString*)name 345 | { 346 | return [[self configurations] objectForKey:name]; 347 | } 348 | 349 | - (XCBuildConfiguration*)defaultConfiguration 350 | { 351 | return [[self configurations] objectForKey:_defaultConfigurationName]; 352 | } 353 | 354 | /* ====================================================================================================================================== */ 355 | #pragma mark Private 356 | 357 | - (NSString*)rootObjectKey 358 | { 359 | if (_rootObjectKey == nil) 360 | { 361 | _rootObjectKey = [[_dataStore objectForKey:@"rootObject"] copy];; 362 | } 363 | 364 | return _rootObjectKey; 365 | } 366 | 367 | - (NSArray*)projectFilesOfType:(XcodeSourceFileType)projectFileType 368 | { 369 | NSMutableArray* results = [NSMutableArray array]; 370 | for (XCSourceFile* file in [self files]) 371 | { 372 | if ([file type] == projectFileType) 373 | { 374 | [results addObject:file]; 375 | } 376 | } 377 | return results; 378 | } 379 | 380 | @end -------------------------------------------------------------------------------- /Dependencies/XcodeEditor/XCTarget.m: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // JASPER BLUES 4 | // Copyright 2012 Jasper Blues 5 | // All Rights Reserved. 6 | // 7 | // NOTICE: Jasper Blues permits you to use, modify, and distribute this file 8 | // in accordance with the terms of the license agreement accompanying it. 9 | // 10 | //////////////////////////////////////////////////////////////////////////////// 11 | 12 | #import "XCGroup.h" 13 | #import "XCKeyBuilder.h" 14 | #import "XCTarget.h" 15 | #import "XCSourceFile.h" 16 | #import "XCProject.h" 17 | #import "XCBuildConfiguration.h" 18 | 19 | @implementation XCTarget 20 | 21 | /* ====================================================================================================================================== */ 22 | #pragma mark - Class Methods 23 | 24 | + (XCTarget*)targetWithProject:(XCProject*)project key:(NSString*)key name:(NSString*)name productName:(NSString*)productName 25 | productReference:(NSString*)productReference 26 | { 27 | return [[XCTarget alloc] initWithProject:project key:key name:name productName:productName productReference:productReference]; 28 | } 29 | 30 | 31 | /* ====================================================================================================================================== */ 32 | #pragma mark - Initialization & Destruction 33 | 34 | - (id)initWithProject:(XCProject*)project key:(NSString*)key name:(NSString*)name productName:(NSString*)productName 35 | productReference:(NSString*)productReference 36 | { 37 | self = [super init]; 38 | if (self) 39 | { 40 | _project = project; 41 | _key = [key copy]; 42 | _name = [name copy]; 43 | _productName = [productName copy]; 44 | _productReference = [productReference copy]; 45 | } 46 | return self; 47 | } 48 | 49 | /* ====================================================================================================================================== */ 50 | #pragma mark - Interface Methods 51 | 52 | - (NSArray*)resources 53 | { 54 | if (_resources == nil) 55 | { 56 | _resources = [[NSMutableArray alloc] init]; 57 | for (NSString* buildPhaseKey in [[[_project objects] objectForKey:_key] objectForKey:@"buildPhases"]) 58 | { 59 | NSDictionary* buildPhase = [[_project objects] objectForKey:buildPhaseKey]; 60 | if ([[buildPhase valueForKey:@"isa"] asMemberType] == PBXResourcesBuildPhaseType) 61 | { 62 | for (NSString* buildFileKey in [buildPhase objectForKey:@"files"]) 63 | { 64 | XCSourceFile* targetMember = [self buildFileWithKey:buildFileKey]; 65 | if (targetMember) 66 | { 67 | [_resources addObject:[self buildFileWithKey:buildFileKey]]; 68 | } 69 | } 70 | } 71 | } 72 | } 73 | 74 | return _resources; 75 | } 76 | 77 | - (NSDictionary*)configurations 78 | { 79 | if (_configurations == nil) 80 | { 81 | NSString* buildConfigurationRootSectionKey = [[[_project objects] objectForKey:_key] objectForKey:@"buildConfigurationList"]; 82 | NSDictionary* buildConfigurationDictionary = [[_project objects] objectForKey:buildConfigurationRootSectionKey]; 83 | _configurations = 84 | [[XCBuildConfiguration buildConfigurationsFromArray:[buildConfigurationDictionary objectForKey:@"buildConfigurations"] 85 | inProject:_project] mutableCopy]; 86 | _defaultConfigurationName = [[buildConfigurationDictionary objectForKey:@"defaultConfigurationName"] copy]; 87 | } 88 | 89 | return _configurations; 90 | } 91 | 92 | - (XCBuildConfiguration*)defaultConfiguration 93 | { 94 | return [[self configurations] objectForKey:_defaultConfigurationName]; 95 | } 96 | 97 | - (XCBuildConfiguration*)configurationWithName:(NSString*)name 98 | { 99 | return [[self configurations] objectForKey:name]; 100 | } 101 | 102 | - (NSArray*)members 103 | { 104 | if (_members == nil) 105 | { 106 | _members = [[NSMutableArray alloc] init]; 107 | for (NSString* buildPhaseKey in [[[_project objects] objectForKey:_key] objectForKey:@"buildPhases"]) 108 | { 109 | NSDictionary* buildPhase = [[_project objects] objectForKey:buildPhaseKey]; 110 | if ([[buildPhase valueForKey:@"isa"] asMemberType] == PBXSourcesBuildPhaseType || 111 | [[buildPhase valueForKey:@"isa"] asMemberType] == PBXFrameworksBuildPhaseType) 112 | { 113 | for (NSString* buildFileKey in [buildPhase objectForKey:@"files"]) 114 | { 115 | XCSourceFile* targetMember = [self buildFileWithKey:buildFileKey]; 116 | if (targetMember) 117 | { 118 | [_members addObject:[_project fileWithKey:targetMember.key]]; 119 | } 120 | } 121 | } 122 | } 123 | } 124 | return _members; 125 | } 126 | 127 | - (void)addMember:(XCSourceFile*)member 128 | { 129 | [member becomeBuildFile]; 130 | NSDictionary* target = [[_project objects] objectForKey:_key]; 131 | 132 | for (NSString* buildPhaseKey in [target objectForKey:@"buildPhases"]) 133 | { 134 | NSMutableDictionary* buildPhase = [[_project objects] objectForKey:buildPhaseKey]; 135 | if ([[buildPhase valueForKey:@"isa"] asMemberType] == [member buildPhase]) 136 | { 137 | 138 | NSMutableArray* files = [buildPhase objectForKey:@"files"]; 139 | if (![files containsObject:[member buildFileKey]]) 140 | { 141 | [files addObject:[member buildFileKey]]; 142 | } 143 | 144 | [buildPhase setObject:files forKey:@"files"]; 145 | } 146 | } 147 | [self flagMembersAsDirty]; 148 | } 149 | 150 | - (NSDictionary*)buildRefWithFileRefKey 151 | { 152 | NSMutableDictionary* buildRefWithFileRefDict = [NSMutableDictionary dictionary]; 153 | NSDictionary* allObjects = [_project objects]; 154 | NSArray* keys = [allObjects allKeys]; 155 | 156 | for (NSString* key in keys) 157 | { 158 | NSDictionary* dictionaryInfo = [allObjects objectForKey:key]; 159 | 160 | NSString* type = [dictionaryInfo objectForKey:@"isa"]; 161 | if (type) 162 | { 163 | if ([type isEqualToString:@"PBXBuildFile"]) 164 | { 165 | NSString* fileRef = [dictionaryInfo objectForKey:@"fileRef"]; 166 | 167 | if (fileRef) 168 | { 169 | [buildRefWithFileRefDict setObject:key forKey:fileRef]; 170 | } 171 | } 172 | } 173 | } 174 | return buildRefWithFileRefDict; 175 | } 176 | 177 | - (void)removeMemberWithKey:(NSString*)key 178 | { 179 | 180 | NSDictionary* buildRefWithFileRef = [self buildRefWithFileRefKey]; 181 | NSDictionary* target = [[_project objects] objectForKey:_key]; 182 | NSString* buildRef = [buildRefWithFileRef objectForKey:key]; 183 | 184 | if (!buildRef) 185 | { 186 | return; 187 | } 188 | 189 | for (NSString* buildPhaseKey in [target objectForKey:@"buildPhases"]) 190 | { 191 | NSMutableDictionary* buildPhase = [[_project objects] objectForKey:buildPhaseKey]; 192 | NSMutableArray* files = [buildPhase objectForKey:@"files"]; 193 | 194 | [files removeObjectIdenticalTo:buildRef]; 195 | [buildPhase setObject:files forKey:@"files"]; 196 | } 197 | [self flagMembersAsDirty]; 198 | } 199 | 200 | - (void)removeMembersWithKeys:(NSArray*)keys 201 | { 202 | for (NSString* key in keys) 203 | { 204 | [self removeMemberWithKey:key]; 205 | } 206 | } 207 | 208 | - (void)addDependency:(NSString*)key 209 | { 210 | NSDictionary* targetObj = [[_project objects] objectForKey:_key]; 211 | NSMutableArray* dependencies = [targetObj valueForKey:@"dependencies"]; 212 | // add only if not already there 213 | BOOL found = NO; 214 | for (NSString* dependency in dependencies) 215 | { 216 | if ([dependency isEqualToString:key]) 217 | { 218 | found = YES; 219 | break; 220 | } 221 | } 222 | if (!found) 223 | { 224 | [dependencies addObject:key]; 225 | } 226 | } 227 | 228 | - (instancetype)duplicateWithTargetName:(NSString*)targetName productName:(NSString*)productName 229 | { 230 | 231 | NSDictionary* targetObj = _project.objects[_key]; 232 | NSMutableDictionary* dupTargetObj = [targetObj mutableCopy]; 233 | 234 | dupTargetObj[@"name"] = targetName; 235 | dupTargetObj[@"productName"] = productName; 236 | 237 | NSString* buildConfigurationListKey = dupTargetObj[@"buildConfigurationList"]; 238 | 239 | void(^visitor)(NSMutableDictionary*) = ^(NSMutableDictionary* buildConfiguration) 240 | { 241 | buildConfiguration[@"buildSettings"][@"PRODUCT_NAME"] = productName; 242 | }; 243 | 244 | dupTargetObj[@"buildConfigurationList"] = 245 | [XCBuildConfiguration duplicatedBuildConfigurationListWithKey:buildConfigurationListKey inProject:_project 246 | withBuildConfigurationVisitor:visitor]; 247 | 248 | [self duplicateProductReferenceForTargetObject:dupTargetObj withProductName:productName]; 249 | 250 | [self duplicateBuildPhasesForTargetObject:dupTargetObj]; 251 | 252 | [self addReferenceToProductsGroupForTargetObject:dupTargetObj]; 253 | 254 | NSString* dupTargetObjKey = [self addTargetToRootObjectTargets:dupTargetObj]; 255 | 256 | [_project dropCache]; 257 | 258 | return [[XCTarget alloc] initWithProject:_project key:dupTargetObjKey name:targetName productName:productName 259 | productReference:dupTargetObj[@"productReference"]]; 260 | } 261 | 262 | /* ====================================================================================================================================== */ 263 | #pragma mark - Overridden Methods 264 | 265 | - (void)setName:(NSString*)name 266 | { 267 | _name = name; 268 | NSDictionary* dictionary = [_project.objects objectForKey:_key]; 269 | [dictionary setValue:_name forKey:@"name"]; 270 | } 271 | 272 | - (void)setProductName:(NSString*)productName 273 | { 274 | _productName = productName; 275 | NSDictionary* dictionary = [_project.objects objectForKey:_key]; 276 | [dictionary setValue:_productName forKey:@"productName"]; 277 | } 278 | 279 | 280 | 281 | /* ====================================================================================================================================== */ 282 | #pragma mark - Utility Methods 283 | 284 | - (NSString*)description 285 | { 286 | return [NSString stringWithFormat:@"Target: name=%@, files=%@", _name, _members]; 287 | } 288 | 289 | /* ====================================================================================================================================== */ 290 | #pragma mark - Private Methods 291 | 292 | - (XCSourceFile*)buildFileWithKey:(NSString*)theKey 293 | { 294 | NSDictionary* obj = [[_project objects] valueForKey:theKey]; 295 | if (obj) 296 | { 297 | if ([[obj valueForKey:@"isa"] asMemberType] == PBXBuildFileType) 298 | { 299 | return [_project fileWithKey:[obj valueForKey:@"fileRef"]]; 300 | } 301 | } 302 | return nil; 303 | } 304 | 305 | - (void)flagMembersAsDirty 306 | { 307 | _members = nil; 308 | } 309 | 310 | - (void)duplicateProductReferenceForTargetObject:(NSMutableDictionary*)dupTargetObj withProductName:(NSString*)productName 311 | { 312 | 313 | NSString* productReferenceKey = dupTargetObj[@"productReference"]; 314 | NSMutableDictionary* dupProductReference = [_project.objects[productReferenceKey] mutableCopy]; 315 | 316 | NSString* path = dupProductReference[@"path"]; 317 | NSString* dupPath = [path stringByDeletingLastPathComponent]; 318 | dupPath = [dupPath stringByAppendingPathComponent:productName]; 319 | dupPath = [dupPath stringByAppendingPathExtension:@"app"]; 320 | dupProductReference[@"path"] = dupPath; 321 | 322 | NSString* dupProductReferenceKey = [[XCKeyBuilder createUnique] build]; 323 | 324 | _project.objects[dupProductReferenceKey] = dupProductReference; 325 | dupTargetObj[@"productReference"] = dupProductReferenceKey; 326 | } 327 | 328 | - (void)duplicateBuildPhasesForTargetObject:(NSMutableDictionary*)dupTargetObj 329 | { 330 | 331 | NSMutableArray* buildPhases = [NSMutableArray array]; 332 | 333 | for (NSString* buildPhaseKey in dupTargetObj[@"buildPhases"]) 334 | { 335 | 336 | NSMutableDictionary* dupBuildPhase = [_project.objects[buildPhaseKey] mutableCopy]; 337 | NSMutableArray* dupFiles = [NSMutableArray array]; 338 | 339 | for (NSString* fileKey in dupBuildPhase[@"files"]) 340 | { 341 | 342 | NSMutableDictionary* dupFile = [_project.objects[fileKey] mutableCopy]; 343 | NSString* dupFileKey = [[XCKeyBuilder createUnique] build]; 344 | 345 | _project.objects[dupFileKey] = dupFile; 346 | [dupFiles addObject:dupFileKey]; 347 | } 348 | 349 | dupBuildPhase[@"files"] = dupFiles; 350 | 351 | NSString* dupBuildPhaseKey = [[XCKeyBuilder createUnique] build]; 352 | _project.objects[dupBuildPhaseKey] = dupBuildPhase; 353 | [buildPhases addObject:dupBuildPhaseKey]; 354 | } 355 | 356 | dupTargetObj[@"buildPhases"] = buildPhases; 357 | } 358 | 359 | - (void)addReferenceToProductsGroupForTargetObject:(NSMutableDictionary*)dupTargetObj 360 | { 361 | 362 | XCGroup* mainGroup = nil; 363 | NSPredicate* productsPredicate = [NSPredicate predicateWithFormat:@"displayName == 'Products'"]; 364 | NSArray* filteredGroups = [_project.groups filteredArrayUsingPredicate:productsPredicate]; 365 | 366 | if (filteredGroups.count > 0) 367 | { 368 | mainGroup = filteredGroups[0]; 369 | NSMutableArray* children = [_project.objects[mainGroup.key][@"children"] mutableCopy]; 370 | [children addObject:dupTargetObj[@"productReference"]]; 371 | _project.objects[mainGroup.key][@"children"] = children; 372 | } 373 | } 374 | 375 | - (NSString*)addTargetToRootObjectTargets:(NSMutableDictionary*)dupTargetObj 376 | { 377 | NSString* dupTargetObjKey = [[XCKeyBuilder createUnique] build]; 378 | 379 | _project.objects[dupTargetObjKey] = dupTargetObj; 380 | 381 | NSString* rootObjKey = _project.dataStore[@"rootObject"]; 382 | NSMutableDictionary* rootObj = [_project.objects[rootObjKey] mutableCopy]; 383 | NSMutableArray* rootObjTargets = [rootObj[@"targets"] mutableCopy]; 384 | [rootObjTargets addObject:dupTargetObjKey]; 385 | 386 | rootObj[@"targets"] = rootObjTargets; 387 | _project.objects[rootObjKey] = rootObj; 388 | 389 | return dupTargetObjKey; 390 | } 391 | 392 | @end 393 | -------------------------------------------------------------------------------- /Dependencies/XcodeEditor/XCProject+SubProject.m: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // JASPER BLUES 4 | // Copyright 2012 Jasper Blues 5 | // All Rights Reserved. 6 | // 7 | // NOTICE: Jasper Blues permits you to use, modify, and distribute this file 8 | // in accordance with the terms of the license agreement accompanying it. 9 | // 10 | //////////////////////////////////////////////////////////////////////////////// 11 | 12 | 13 | 14 | #import "XCSourceFile.h" 15 | #import "XCTarget.h" 16 | #import "Utils/XCKeyBuilder.h" 17 | #import "XCProject+SubProject.h" 18 | #import "XCSubProjectDefinition.h" 19 | 20 | 21 | @implementation XCProject (SubProject) 22 | 23 | 24 | #pragma mark sub-project related public methods 25 | 26 | // returns the key for the reference proxy with the given path (nil if not found) 27 | // does not use keysForProjectObjectsOfType:withIdentifier: because the identifier it uses for 28 | // PBXReferenceProxy is different. 29 | - (NSString*)referenceProxyKeyForName:(NSString*)name 30 | { 31 | __block NSString* result = nil; 32 | [[self objects] enumerateKeysAndObjectsUsingBlock:^(NSString* key, NSDictionary* obj, BOOL* stop) 33 | { 34 | if ([[obj valueForKey:@"isa"] asMemberType] == PBXReferenceProxyType) 35 | { 36 | if ([[obj valueForKey:@"path"] isEqualTo:name]) 37 | { 38 | result = key; 39 | *stop = YES; 40 | } 41 | } 42 | }]; 43 | return result; 44 | } 45 | 46 | // returns an array of build products, excluding bundles with extensions other than ".bundle" (which is kind 47 | // of gross, but I didn't see a better way to exclude test bundles without giving them their own XcodeSourceFileType) 48 | - (NSArray*)buildProductsForTargets:(NSString*)xcodeprojKey 49 | { 50 | NSMutableArray* results = [[NSMutableArray alloc] init]; 51 | [[self objects] enumerateKeysAndObjectsUsingBlock:^(NSString* key, NSDictionary* obj, BOOL* stop) 52 | { 53 | if ([[obj valueForKey:@"isa"] asMemberType] == PBXReferenceProxyType) 54 | { 55 | // make sure it belongs to the xcodeproj we're adding 56 | NSString* remoteRef = [obj valueForKey:@"remoteRef"]; 57 | NSDictionary* containerProxy = [[self objects] valueForKey:remoteRef]; 58 | NSString* containerPortal = [containerProxy valueForKey:@"containerPortal"]; 59 | if ([containerPortal isEqualToString:xcodeprojKey]) 60 | { 61 | XcodeSourceFileType type = XCSourceFileTypeFromStringRepresentation([obj valueForKey:@"fileType"]); 62 | NSString* path = (NSString*) [obj valueForKey:@"path"]; 63 | if (type != Bundle || [[path pathExtension] isEqualToString:@"bundle"]) 64 | { 65 | [results addObject:[XCSourceFile sourceFileWithProject:self key:key type:type name:path sourceTree:nil path:nil]]; 66 | } 67 | } 68 | } 69 | }]; 70 | return results; 71 | } 72 | 73 | // makes PBXContainerItemProxy and PBXTargetDependency objects for the xcodeproj, and adds the dependency key 74 | // to all the specified targets 75 | - (void)addAsTargetDependency:(XCSubProjectDefinition*)xcodeprojDefinition toTargets:(NSArray*)targets 76 | { 77 | for (XCTarget* target in targets) 78 | { 79 | // make a new PBXContainerItemProxy 80 | NSString* key = [[self fileWithName:[xcodeprojDefinition pathRelativeToProjectRoot]] key]; 81 | NSString* containerItemProxyKey = 82 | [self makeContainerItemProxyForName:[xcodeprojDefinition name] fileRef:key proxyType:@"1" uniqueName:[target name]]; 83 | // make a PBXTargetDependency 84 | NSString* targetDependencyKey = 85 | [self makeTargetDependency:[xcodeprojDefinition name] forContainerItemProxyKey:containerItemProxyKey uniqueName:[target name]]; 86 | // add entry in each targets dependencies list 87 | [target addDependency:targetDependencyKey]; 88 | } 89 | } 90 | 91 | // returns an array of keys for all project objects (not just files) that match the given criteria. Since this is 92 | // a convenience method intended to save typing elsewhere, each type has its own field to match to rather than each 93 | // matching on name or path as you might expect. 94 | - (NSArray*)keysForProjectObjectsOfType:(XcodeMemberType)memberType withIdentifier:(NSString*)identifier singleton:(BOOL)singleton 95 | required:(BOOL)required 96 | { 97 | __block NSMutableArray* returnValue = [[NSMutableArray alloc] init]; 98 | [[self objects] enumerateKeysAndObjectsUsingBlock:^(NSString* key, NSDictionary* obj, BOOL* stop) 99 | { 100 | if ([[obj valueForKey:@"isa"] asMemberType] == memberType) 101 | { 102 | if (memberType == PBXContainerItemProxyType) 103 | { 104 | if ([[obj valueForKey:@"containerPortal"] isEqualToString:identifier]) 105 | { 106 | [returnValue addObject:key]; 107 | } 108 | } 109 | else if (memberType == PBXReferenceProxyType) 110 | { 111 | if ([[obj valueForKey:@"remoteRef"] isEqualToString:identifier]) 112 | { 113 | [returnValue addObject:key]; 114 | } 115 | } 116 | else if (memberType == PBXTargetDependencyType || memberType == PBXGroupType || memberType == PBXVariantGroupType) 117 | { 118 | if ([[obj valueForKey:@"name"] isEqualToString:identifier]) 119 | { 120 | [returnValue addObject:key]; 121 | } 122 | } 123 | else if (memberType == PBXNativeTargetType) 124 | { 125 | for (NSString* dependencyKey in [obj valueForKey:@"dependencies"]) 126 | { 127 | if ([dependencyKey isEqualToString:identifier]) 128 | { 129 | [returnValue addObject:key]; 130 | } 131 | } 132 | } 133 | else if (memberType == PBXBuildFileType) 134 | { 135 | if ([[obj valueForKey:@"fileRef"] isEqualToString:identifier]) 136 | { 137 | [returnValue addObject:key]; 138 | } 139 | } 140 | else if (memberType == PBXProjectType) 141 | { 142 | [returnValue addObject:key]; 143 | } 144 | else if (memberType == PBXFileReferenceType) 145 | { 146 | if ([[obj valueForKey:@"path"] isEqualToString:identifier]) 147 | { 148 | [returnValue addObject:key]; 149 | } 150 | } 151 | else if (memberType == PBXFrameworksBuildPhaseType || memberType == PBXResourcesBuildPhaseType) 152 | { 153 | [returnValue addObject:key]; 154 | } 155 | else 156 | { 157 | [NSException raise:NSInvalidArgumentException format:@"Unrecognized member type %@", 158 | [NSString stringFromMemberType:memberType]]; 159 | } 160 | } 161 | }]; 162 | if (singleton && [returnValue count] > 1) 163 | { 164 | [NSException raise:NSGenericException format:@"Searched for one instance of member type %@ with value %@, but found %ld", 165 | [NSString stringFromMemberType:memberType], identifier, [returnValue count]]; 166 | } 167 | if (required && [returnValue count] == 0) 168 | { 169 | [NSException raise:NSGenericException format:@"Searched for instances of member type %@ with value %@, but did not find any", 170 | [NSString stringFromMemberType:memberType], identifier]; 171 | } 172 | return returnValue; 173 | } 174 | 175 | // returns the dictionary for the PBXProject. Raises an exception if more or less than 1 are found. 176 | - (NSMutableDictionary*)PBXProjectDict 177 | { 178 | NSString* PBXProjectKey; 179 | NSArray* PBXProjectKeys = [self keysForProjectObjectsOfType:PBXProjectType withIdentifier:nil singleton:YES required:YES]; 180 | PBXProjectKey = [PBXProjectKeys objectAtIndex:0]; 181 | NSMutableDictionary* PBXProjectDict = [[self objects] valueForKey:PBXProjectKey]; 182 | return PBXProjectDict; 183 | } 184 | 185 | // returns the key of the PBXContainerItemProxy for the given name and proxy type. nil if not found. 186 | - (NSString*)containerItemProxyKeyForName:(NSString*)name proxyType:(NSString*)proxyType 187 | { 188 | NSMutableArray* results = [[NSMutableArray alloc] init]; 189 | [[self objects] enumerateKeysAndObjectsUsingBlock:^(NSString* key, NSDictionary* obj, BOOL* stop) 190 | { 191 | if ([[obj valueForKey:@"isa"] asMemberType] == PBXContainerItemProxyType) 192 | { 193 | NSString* remoteInfo = [obj valueForKey:@"remoteInfo"]; 194 | NSString* proxy = [obj valueForKey:@"proxyType"]; 195 | if ([remoteInfo isEqualToString:name] && [proxy isEqualToString:proxyType]) 196 | { 197 | [results addObject:key]; 198 | } 199 | } 200 | }]; 201 | if ([results count] > 1) 202 | { 203 | [NSException raise:NSGenericException format:@"Searched for one instance of member type %@ with value %@, but found %ld", 204 | @"PBXContainerItemProxy", 205 | [NSString stringWithFormat:@"%@ and proxyType of %@", name, proxyType], 206 | [results count]]; 207 | } 208 | if ([results count] == 0) 209 | { 210 | return nil; 211 | } 212 | return [results objectAtIndex:0]; 213 | } 214 | 215 | /* ====================================================================================================================================== */ 216 | #pragma mark - Private Methods 217 | #pragma mark sub-project related private methods 218 | 219 | // makes a PBXContainerItemProxy object for a given PBXFileReference object. Replaces pre-existing objects. 220 | - (NSString*)makeContainerItemProxyForName:(NSString*)name fileRef:(NSString*)fileRef proxyType:(NSString*)proxyType 221 | uniqueName:(NSString*)uniqueName 222 | { 223 | NSString* keyName; 224 | if (uniqueName != nil) 225 | { 226 | keyName = [NSString stringWithFormat:@"%@-%@", name, uniqueName]; 227 | } 228 | else 229 | { 230 | keyName = name; 231 | } 232 | // remove old if it exists 233 | NSString* existingProxyKey = [self containerItemProxyKeyForName:keyName proxyType:proxyType]; 234 | if (existingProxyKey) 235 | { 236 | [[self objects] removeObjectForKey:existingProxyKey]; 237 | } 238 | // make new one 239 | NSMutableDictionary* proxy = [NSMutableDictionary dictionary]; 240 | [proxy setObject:[NSString stringFromMemberType:PBXContainerItemProxyType] forKey:@"isa"]; 241 | [proxy setObject:fileRef forKey:@"containerPortal"]; 242 | [proxy setObject:proxyType forKey:@"proxyType"]; 243 | // give it a random key - the keys xcode puts here are not in the project file anywhere else 244 | NSString* key = [[XCKeyBuilder forItemNamed:[NSString stringWithFormat:@"%@-junk", keyName]] build]; 245 | [proxy setObject:key forKey:@"remoteGlobalIDString"]; 246 | [proxy setObject:name forKey:@"remoteInfo"]; 247 | // add to project. use proxyType to generate key, so that multiple keys for the same name don't overwrite each other 248 | key = [[XCKeyBuilder forItemNamed:[NSString stringWithFormat:@"%@-containerProxy-%@", keyName, proxyType]] build]; 249 | [[self objects] setObject:proxy forKey:key]; 250 | 251 | return key; 252 | } 253 | 254 | // makes a PBXReferenceProxy object for a given PBXContainerProxy object. Replaces pre-existing objects. 255 | - (void)makeReferenceProxyForContainerItemProxy:(NSString*)containerItemProxyKey buildProductReference:(NSDictionary*)buildProductReference 256 | { 257 | NSString* path = [buildProductReference valueForKey:@"path"]; 258 | // remove old if any exists 259 | NSArray* existingProxyKeys = [self keysForProjectObjectsOfType:PBXReferenceProxyType withIdentifier:path singleton:NO required:NO]; 260 | if ([existingProxyKeys count] > 0) 261 | { 262 | for (NSString* existingProxyKey in existingProxyKeys) 263 | { 264 | [[self objects] removeObjectForKey:existingProxyKey]; 265 | } 266 | } 267 | // make new one 268 | NSMutableDictionary* proxy = [NSMutableDictionary dictionary]; 269 | [proxy setObject:[NSString stringFromMemberType:PBXReferenceProxyType] forKey:@"isa"]; 270 | [proxy setObject:[buildProductReference valueForKey:@"explicitFileType"] forKey:@"fileType"]; 271 | [proxy setObject:path forKey:@"path"]; 272 | [proxy setObject:containerItemProxyKey forKey:@"remoteRef"]; 273 | [proxy setObject:[buildProductReference valueForKey:@"sourceTree"] forKey:@"sourceTree"]; 274 | // add to project 275 | NSString* key = [[XCKeyBuilder forItemNamed:[NSString stringWithFormat:@"%@-referenceProxy", path]] build]; 276 | [[self objects] setObject:proxy forKey:key]; 277 | } 278 | 279 | // makes a PBXTargetDependency object for a given PBXContainerItemProxy. Replaces pre-existing objects. 280 | - (NSString*)makeTargetDependency:(NSString*)name forContainerItemProxyKey:(NSString*)containerItemProxyKey uniqueName:(NSString*)uniqueName 281 | { 282 | NSString* keyName; 283 | if (uniqueName != nil) 284 | { 285 | keyName = [NSString stringWithFormat:@"%@-%@", name, uniqueName]; 286 | } 287 | else 288 | { 289 | keyName = name; 290 | } 291 | // remove old if it exists 292 | NSArray* existingDependencyKeys = 293 | [self keysForProjectObjectsOfType:PBXTargetDependencyType withIdentifier:keyName singleton:NO required:NO]; 294 | if ([existingDependencyKeys count] > 0) 295 | { 296 | for (NSString* existingDependencyKey in existingDependencyKeys) 297 | { 298 | [[self objects] removeObjectForKey:existingDependencyKey]; 299 | } 300 | } 301 | // make new one 302 | NSMutableDictionary* targetDependency = [NSMutableDictionary dictionary]; 303 | [targetDependency setObject:[NSString stringFromMemberType:PBXTargetDependencyType] forKey:@"isa"]; 304 | [targetDependency setObject:name forKey:@"name"]; 305 | [targetDependency setObject:containerItemProxyKey forKey:@"targetProxy"]; 306 | NSString* targetDependencyKey = [[XCKeyBuilder forItemNamed:[NSString stringWithFormat:@"%@-targetProxy", keyName]] build]; 307 | [[self objects] setObject:targetDependency forKey:targetDependencyKey]; 308 | return targetDependencyKey; 309 | } 310 | 311 | // make a PBXContainerItemProxy and PBXReferenceProxy for each target in the subProject 312 | - (void)addProxies:(XCSubProjectDefinition*)xcodeproj 313 | { 314 | NSString* fileRef = [[self fileWithName:[xcodeproj pathRelativeToProjectRoot]] key]; 315 | for (NSDictionary* target in [xcodeproj.subProject targets]) 316 | { 317 | NSString* containerItemProxyKey = 318 | [self makeContainerItemProxyForName:[target valueForKey:@"name"] fileRef:fileRef proxyType:@"2" uniqueName:nil]; 319 | NSString* productFileReferenceKey = [target valueForKey:@"productReference"]; 320 | NSDictionary* productFileReference = [[xcodeproj.subProject objects] valueForKey:productFileReferenceKey]; 321 | [self makeReferenceProxyForContainerItemProxy:containerItemProxyKey buildProductReference:productFileReference]; 322 | } 323 | } 324 | 325 | // remove the PBXContainerItemProxy and PBXReferenceProxy objects for the given object key (which is the PBXFilereference 326 | // for the xcodeproj file) 327 | - (void)removeProxies:(NSString*)xcodeprojKey 328 | { 329 | NSMutableArray* keysToDelete = [NSMutableArray array]; 330 | // use the xcodeproj's PBXFileReference key to get the PBXContainerItemProxy keys 331 | NSArray* containerItemProxyKeys = 332 | [self keysForProjectObjectsOfType:PBXContainerItemProxyType withIdentifier:xcodeprojKey singleton:NO required:YES]; 333 | // use the PBXContainerItemProxy keys to get the PBXReferenceProxy keys 334 | for (NSString* key in containerItemProxyKeys) 335 | { 336 | [keysToDelete addObjectsFromArray:[self keysForProjectObjectsOfType:PBXReferenceProxyType withIdentifier:key singleton:NO 337 | required:NO]]; 338 | [keysToDelete addObject:key]; 339 | } 340 | // remove all objects located above 341 | [keysToDelete enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL* stop) 342 | { 343 | [[self objects] removeObjectForKey:obj]; 344 | }]; 345 | } 346 | 347 | // returns the Products group key for the given PBXFileReference key, nil if not found. 348 | - (NSString*)productsGroupKeyForKey:(NSString*)key 349 | { 350 | NSMutableArray* projectReferences = [[self PBXProjectDict] valueForKey:@"projectReferences"]; 351 | NSString* productsGroupKey = nil; 352 | for (NSDictionary* projectRef in projectReferences) 353 | { 354 | if ([[projectRef valueForKey:@"ProjectRef"] isEqualToString:key]) 355 | { 356 | // it's an error if we find more than one 357 | if (productsGroupKey != nil) 358 | { 359 | [NSException raise:NSGenericException format:@"Found more than one project reference for key %@", key]; 360 | } 361 | productsGroupKey = [projectRef valueForKey:@"ProductGroup"]; 362 | } 363 | } 364 | return productsGroupKey; 365 | } 366 | 367 | // removes a file reference from the projectReferences array in PBXProject (removing the array itself if this action 368 | // leaves it empty). 369 | - (void)removeFromProjectReferences:(NSString*)key forProductsGroup:(NSString*)productsGroupKey 370 | { 371 | NSMutableArray* projectReferences = [[self PBXProjectDict] valueForKey:@"projectReferences"]; 372 | // remove entry from PBXProject's projectReferences 373 | NSMutableArray* referencesToRemove = [NSMutableArray array]; 374 | for (NSDictionary* projectRef in projectReferences) 375 | { 376 | if ([[projectRef valueForKey:@"ProjectRef"] isEqualToString:key]) 377 | { 378 | [referencesToRemove addObject:projectRef]; 379 | } 380 | } 381 | for (NSDictionary* projectRef in referencesToRemove) 382 | { 383 | [projectReferences removeObject:projectRef]; 384 | } 385 | // if that was the last project reference, remove the array from the project 386 | if ([projectReferences count] == 0) 387 | { 388 | [[self PBXProjectDict] removeObjectForKey:@"projectReferences"]; 389 | } 390 | } 391 | 392 | // removes a specific xcodeproj file from any targets (by name). It's not an error if no entries are found, 393 | // because we support adding a project file without adding it to any targets. 394 | - (void)removeTargetDependencies:(NSString*)name 395 | { 396 | // get the key for the PBXTargetDependency with name = xcodeproj file name (without extension) 397 | NSArray* targetDependencyKeys = [self keysForProjectObjectsOfType:PBXTargetDependencyType withIdentifier:name singleton:NO required:NO]; 398 | // we might not find any if the project wasn't added to targets in the first place 399 | if ([targetDependencyKeys count] == 0) 400 | { 401 | return; 402 | } 403 | NSString* targetDependencyKey = [targetDependencyKeys objectAtIndex:0]; 404 | // use the key for the PBXTargetDependency to get the key for any PBXNativeTargets that depend on it 405 | NSArray* nativeTargetKeys = 406 | [self keysForProjectObjectsOfType:PBXNativeTargetType withIdentifier:targetDependencyKey singleton:NO required:NO]; 407 | // remove the key for the PBXTargetDependency from the PBXNativeTarget's dependencies arrays (leave in place even if empty) 408 | for (NSString* nativeTargetKey in nativeTargetKeys) 409 | { 410 | NSMutableDictionary* nativeTarget = [[self objects] objectForKey:nativeTargetKey]; 411 | NSMutableArray* dependencies = [nativeTarget valueForKey:@"dependencies"]; 412 | [dependencies removeObject:targetDependencyKey]; 413 | [nativeTarget setObject:dependencies forKey:@"dependencies"]; 414 | } 415 | // remove the PBXTargetDependency 416 | [[self objects] removeObjectForKey:targetDependencyKey]; 417 | } 418 | 419 | @end -------------------------------------------------------------------------------- /XLocation/XLWindow.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 61 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 119 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | -------------------------------------------------------------------------------- /Dependencies/XcodeEditor/XCGroup.m: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // JASPER BLUES 4 | // Copyright 2012 Jasper Blues 5 | // All Rights Reserved. 6 | // 7 | // NOTICE: Jasper Blues permits you to use, modify, and distribute this file 8 | // in accordance with the terms of the license agreement accompanying it. 9 | // 10 | //////////////////////////////////////////////////////////////////////////////// 11 | 12 | 13 | 14 | #import "XCFrameworkDefinition.h" 15 | #import "XCTarget.h" 16 | #import "XCFileOperationQueue.h" 17 | #import "XCXibDefinition.h" 18 | #import "XCSourceFile.h" 19 | #import "XCGroup.h" 20 | #import "XCProject.h" 21 | #import "XCClassDefinition.h" 22 | #import "Utils/XCKeyBuilder.h" 23 | #import "XCSourceFileDefinition.h" 24 | #import "XCSubProjectDefinition.h" 25 | #import "XCProject+SubProject.h" 26 | 27 | 28 | @implementation XCGroup 29 | 30 | 31 | /* ====================================================================================================================================== */ 32 | #pragma mark - Class Methods 33 | 34 | + (XCGroup*)groupWithProject:(XCProject*)project key:(NSString*)key alias:(NSString*)alias path:(NSString*)path children:(NSArray*)children 35 | { 36 | 37 | return [[XCGroup alloc] initWithProject:project key:key alias:alias path:path children:children]; 38 | } 39 | 40 | /* ====================================================================================================================================== */ 41 | #pragma mark - Initialization & Destruction 42 | 43 | - (id)initWithProject:(XCProject*)project key:(NSString*)key alias:(NSString*)alias path:(NSString*)path children:(NSArray*)children 44 | { 45 | self = [super init]; 46 | if (self) 47 | { 48 | _project = project; 49 | _fileOperationQueue = [_project fileOperationQueue]; 50 | _key = [key copy]; 51 | _alias = [alias copy]; 52 | _pathRelativeToParent = [path copy]; 53 | 54 | _children = [children mutableCopy]; 55 | if (!_children) 56 | { 57 | _children = [[NSMutableArray alloc] init]; 58 | } 59 | } 60 | return self; 61 | } 62 | 63 | /* ====================================================================================================================================== */ 64 | #pragma mark - Interface Methods 65 | 66 | #pragma mark Parent group 67 | 68 | - (void)removeFromParentGroup 69 | { 70 | [self removeFromParentDeletingChildren:NO]; 71 | } 72 | 73 | 74 | - (void)removeFromParentDeletingChildren:(BOOL)deleteChildren 75 | { 76 | if (deleteChildren) 77 | { 78 | [_fileOperationQueue queueDeletion:[self pathRelativeToProjectRoot]]; 79 | } 80 | NSDictionary* dictionary = [[_project objects] objectForKey:_key]; 81 | NSLog(@"Here's the dictionary: %@", dictionary); 82 | 83 | [[_project objects] removeObjectForKey:_key]; 84 | 85 | dictionary = [[_project objects] objectForKey:_key]; 86 | NSLog(@"Here's the dictionary: %@", dictionary); 87 | 88 | for (XCTarget* target in [_project targets]) 89 | { 90 | [target removeMembersWithKeys:[self recursiveMembers]]; 91 | } 92 | NSLog(@"Done!!!"); 93 | } 94 | 95 | - (XCGroup*)parentGroup 96 | { 97 | return [_project groupForGroupMemberWithKey:_key]; 98 | } 99 | 100 | - (BOOL)isRootGroup 101 | { 102 | return [self pathRelativeToParent] == nil && [self displayName] == nil; 103 | } 104 | 105 | 106 | /* ================================================================================================================== */ 107 | #pragma mark Adding children 108 | 109 | 110 | - (void)addClass:(XCClassDefinition*)classDefinition 111 | { 112 | 113 | if ([classDefinition header]) 114 | { 115 | [self makeGroupMemberWithName:[classDefinition headerFileName] contents:[classDefinition header] type:SourceCodeHeader 116 | fileOperationStyle:[classDefinition fileOperationType]]; 117 | } 118 | 119 | if ([classDefinition isObjectiveC]) 120 | { 121 | [self makeGroupMemberWithName:[classDefinition sourceFileName] contents:[classDefinition source] type:SourceCodeObjC 122 | fileOperationStyle:[classDefinition fileOperationType]]; 123 | } 124 | else if ([classDefinition isObjectiveCPlusPlus]) 125 | { 126 | [self makeGroupMemberWithName:[classDefinition sourceFileName] contents:[classDefinition source] type:SourceCodeObjCPlusPlus 127 | fileOperationStyle:[classDefinition fileOperationType]]; 128 | } 129 | 130 | [[_project objects] setObject:[self asDictionary] forKey:_key]; 131 | } 132 | 133 | 134 | - (void)addClass:(XCClassDefinition*)classDefinition toTargets:(NSArray*)targets 135 | { 136 | [self addClass:classDefinition]; 137 | XCSourceFile* sourceFile = [_project fileWithName:[classDefinition sourceFileName]]; 138 | [self addSourceFile:sourceFile toTargets:targets]; 139 | } 140 | 141 | - (void)addFramework:(XCFrameworkDefinition*)frameworkDefinition 142 | { 143 | if (([self memberWithDisplayName:[frameworkDefinition name]]) == nil) 144 | { 145 | NSDictionary* fileReference; 146 | if ([frameworkDefinition copyToDestination]) 147 | { 148 | fileReference = [self makeFileReferenceWithPath:[frameworkDefinition name] name:nil type:Framework]; 149 | BOOL copyFramework = NO; 150 | if ([frameworkDefinition fileOperationType] == XCFileOperationTypeOverwrite) 151 | { 152 | copyFramework = YES; 153 | } 154 | else if ([frameworkDefinition fileOperationType] == XCFileOperationTypeAcceptExisting) 155 | { 156 | NSString* frameworkName = [[frameworkDefinition filePath] lastPathComponent]; 157 | if (![_fileOperationQueue fileWithName:frameworkName existsInProjectDirectory:[self pathRelativeToProjectRoot]]) 158 | { 159 | copyFramework = YES; 160 | } 161 | 162 | } 163 | if (copyFramework) 164 | { 165 | [_fileOperationQueue queueFrameworkWithFilePath:[frameworkDefinition filePath] 166 | inDirectory:[self pathRelativeToProjectRoot]]; 167 | } 168 | } 169 | else 170 | { 171 | NSString* path = [frameworkDefinition filePath]; 172 | NSString* name = [frameworkDefinition name]; 173 | fileReference = [self makeFileReferenceWithPath:path name:name type:Framework]; 174 | } 175 | NSString* frameworkKey = [[XCKeyBuilder forItemNamed:[frameworkDefinition name]] build]; 176 | [[_project objects] setObject:fileReference forKey:frameworkKey]; 177 | [self addMemberWithKey:frameworkKey]; 178 | } 179 | [[_project objects] setObject:[self asDictionary] forKey:_key]; 180 | } 181 | 182 | 183 | - (void)addFramework:(XCFrameworkDefinition*)frameworkDefinition toTargets:(NSArray*)targets 184 | { 185 | [self addFramework:frameworkDefinition]; 186 | XCSourceFile* frameworkSourceRef = (XCSourceFile*) [self memberWithDisplayName:[frameworkDefinition name]]; 187 | [self addSourceFile:frameworkSourceRef toTargets:targets]; 188 | } 189 | 190 | - (XCGroup*)addGroupWithPath:(NSString*)path 191 | { 192 | NSString* groupKeyPath = self.pathRelativeToProjectRoot ? [self.pathRelativeToProjectRoot stringByAppendingPathComponent:path] : path; 193 | 194 | NSString* groupKey = [[XCKeyBuilder forItemNamed:groupKeyPath] build]; 195 | 196 | NSArray* members = [self members]; 197 | for (id groupMember in members) 198 | { 199 | if ([groupMember groupMemberType] == PBXGroupType || [groupMember groupMemberType] == PBXVariantGroupType) 200 | { 201 | 202 | if ([[[groupMember pathRelativeToProjectRoot] lastPathComponent] isEqualToString:path] || 203 | [[groupMember displayName] isEqualToString:path] || [[groupMember key] isEqualToString:groupKey]) 204 | { 205 | return nil; 206 | } 207 | } 208 | } 209 | 210 | XCGroup* group = [[XCGroup alloc] initWithProject:_project key:groupKey alias:nil path:path children:nil]; 211 | NSDictionary* groupDict = [group asDictionary]; 212 | 213 | [[_project objects] setObject:groupDict forKey:groupKey]; 214 | [_fileOperationQueue queueDirectory:path inDirectory:[self pathRelativeToProjectRoot]]; 215 | [self addMemberWithKey:groupKey]; 216 | 217 | NSDictionary* dict = [self asDictionary]; 218 | [[_project objects] setObject:dict forKey:_key]; 219 | 220 | return group; 221 | } 222 | 223 | - (void)addSourceFile:(XCSourceFileDefinition*)sourceFileDefinition 224 | { 225 | [self makeGroupMemberWithName:[sourceFileDefinition sourceFileName] contents:[sourceFileDefinition data] 226 | type:[sourceFileDefinition type] fileOperationStyle:[sourceFileDefinition fileOperationType]]; 227 | [[_project objects] setObject:[self asDictionary] forKey:_key]; 228 | } 229 | 230 | - (void)addXib:(XCXibDefinition*)xibDefinition 231 | { 232 | [self makeGroupMemberWithName:[xibDefinition xibFileName] contents:[xibDefinition content] type:XibFile 233 | fileOperationStyle:[xibDefinition fileOperationType]]; 234 | [[_project objects] setObject:[self asDictionary] forKey:_key]; 235 | } 236 | 237 | - (void)addXib:(XCXibDefinition*)xibDefinition toTargets:(NSArray*)targets 238 | { 239 | [self addXib:xibDefinition]; 240 | XCSourceFile* sourceFile = [_project fileWithName:[xibDefinition xibFileName]]; 241 | [self addSourceFile:sourceFile toTargets:targets]; 242 | } 243 | 244 | 245 | // adds an xcodeproj as a subproject of the current project. 246 | - (void)addSubProject:(XCSubProjectDefinition*)projectDefinition 247 | { 248 | // set up path to the xcodeproj file as Xcode sees it - path to top level of project + group path if any 249 | [projectDefinition initFullProjectPath:_project.filePath groupPath:[self pathRelativeToParent]]; 250 | 251 | // create PBXFileReference for xcodeproj file and add to PBXGroup for the current group 252 | // (will retrieve existing if already there) 253 | [self makeGroupMemberWithName:[projectDefinition projectFileName] path:[projectDefinition pathRelativeToProjectRoot] type:XcodeProject 254 | fileOperationStyle:[projectDefinition fileOperationType]]; 255 | [[_project objects] setObject:[self asDictionary] forKey:_key]; 256 | 257 | // create PBXContainerItemProxies and PBXReferenceProxies 258 | [_project addProxies:projectDefinition]; 259 | 260 | // add projectReferences key to PBXProject 261 | [self addProductsGroupToProject:projectDefinition]; 262 | } 263 | 264 | // adds an xcodeproj as a subproject of the current project, and also adds all build products except for test bundle(s) 265 | // to targets. 266 | - (void)addSubProject:(XCSubProjectDefinition*)projectDefinition toTargets:(NSArray*)targets 267 | { 268 | [self addSubProject:projectDefinition]; 269 | 270 | // add subproject's build products to targets (does not add the subproject's test bundle) 271 | NSArray* buildProductFiles = [_project buildProductsForTargets:[projectDefinition projectKey]]; 272 | for (XCSourceFile* file in buildProductFiles) 273 | { 274 | [self addSourceFile:file toTargets:targets]; 275 | } 276 | // add main target of subproject as target dependency to main target of project 277 | [_project addAsTargetDependency:projectDefinition toTargets:targets]; 278 | } 279 | 280 | // removes an xcodeproj from the current project. 281 | - (void)removeSubProject:(XCSubProjectDefinition*)projectDefinition 282 | { 283 | if (projectDefinition == nil) 284 | { 285 | return; 286 | } 287 | 288 | // set up path to the xcodeproj file as Xcode sees it - path to top level of project + group path if any 289 | [projectDefinition initFullProjectPath:_project.filePath groupPath:[self pathRelativeToParent]]; 290 | 291 | NSString* xcodeprojKey = [projectDefinition projectKey]; 292 | 293 | // Remove from group and remove PBXFileReference 294 | [self removeGroupMemberWithKey:xcodeprojKey]; 295 | 296 | // remove PBXContainerItemProxies and PBXReferenceProxies 297 | [_project removeProxies:xcodeprojKey]; 298 | 299 | // get the key for the Products group 300 | NSString* productsGroupKey = [_project productsGroupKeyForKey:xcodeprojKey]; 301 | 302 | // remove from the ProjectReferences array of PBXProject 303 | [_project removeFromProjectReferences:xcodeprojKey forProductsGroup:productsGroupKey]; 304 | 305 | // remove PDXBuildFile entries 306 | [self removeProductsGroupFromProject:productsGroupKey]; 307 | 308 | // remove Products group 309 | [[_project objects] removeObjectForKey:productsGroupKey]; 310 | 311 | // remove from all targets 312 | [_project removeTargetDependencies:[projectDefinition name]]; 313 | } 314 | 315 | - (void)removeSubProject:(XCSubProjectDefinition*)projectDefinition fromTargets:(NSArray*)targets 316 | { 317 | if (projectDefinition == nil) 318 | { 319 | return; 320 | } 321 | 322 | // set up path to the xcodeproj file as Xcode sees it - path to top level of project + group path if any 323 | [projectDefinition initFullProjectPath:_project.filePath groupPath:[self pathRelativeToParent]]; 324 | 325 | NSString* xcodeprojKey = [projectDefinition projectKey]; 326 | 327 | // Remove PBXBundleFile entries and corresponding inclusion in PBXFrameworksBuildPhase and PBXResourcesBuidPhase 328 | NSString* productsGroupKey = [_project productsGroupKeyForKey:xcodeprojKey]; 329 | [self removeProductsGroupFromProject:productsGroupKey]; 330 | 331 | // Remove the PBXContainerItemProxy for this xcodeproj with proxyType 1 332 | NSString* containerItemProxyKey = [_project containerItemProxyKeyForName:[projectDefinition pathRelativeToProjectRoot] proxyType:@"1"]; 333 | if (containerItemProxyKey != nil) 334 | { 335 | [[_project objects] removeObjectForKey:containerItemProxyKey]; 336 | } 337 | 338 | // Remove PBXTargetDependency and entry in PBXNativeTarget 339 | [_project removeTargetDependencies:[projectDefinition name]]; 340 | } 341 | 342 | /* ====================================================================================================================================== */ 343 | #pragma mark Members 344 | 345 | - (NSArray*)members 346 | { 347 | if (_members == nil) 348 | { 349 | _members = [[NSMutableArray alloc] init]; 350 | for (NSString* childKey in _children) 351 | { 352 | XcodeMemberType type = [self typeForKey:childKey]; 353 | 354 | @autoreleasepool 355 | { 356 | if (type == PBXGroupType || type == PBXVariantGroupType) 357 | { 358 | [_members addObject:[_project groupWithKey:childKey]]; 359 | } 360 | else if (type == PBXFileReferenceType) 361 | { 362 | [_members addObject:[_project fileWithKey:childKey]]; 363 | } 364 | } 365 | } 366 | } 367 | return _members; 368 | } 369 | 370 | - (NSArray*)recursiveMembers 371 | { 372 | NSMutableArray* recursiveMembers = [NSMutableArray array]; 373 | for (NSString* childKey in _children) 374 | { 375 | XcodeMemberType type = [self typeForKey:childKey]; 376 | if (type == PBXGroupType || type == PBXVariantGroupType) 377 | { 378 | XCGroup* group = [_project groupWithKey:childKey]; 379 | NSArray* groupChildren = [group recursiveMembers]; 380 | [recursiveMembers addObjectsFromArray:groupChildren]; 381 | } 382 | else if (type == PBXFileReferenceType) 383 | { 384 | [recursiveMembers addObject:childKey]; 385 | } 386 | } 387 | [recursiveMembers addObject:_key]; 388 | return [recursiveMembers arrayByAddingObjectsFromArray:recursiveMembers]; 389 | } 390 | 391 | - (NSArray*)buildFileKeys 392 | { 393 | 394 | NSMutableArray* arrayOfBuildFileKeys = [NSMutableArray array]; 395 | for (id groupMember in [self members]) 396 | { 397 | 398 | if ([groupMember groupMemberType] == PBXGroupType || [groupMember groupMemberType] == PBXVariantGroupType) 399 | { 400 | XCGroup* group = (XCGroup*) groupMember; 401 | [arrayOfBuildFileKeys addObjectsFromArray:[group buildFileKeys]]; 402 | } 403 | else if ([groupMember groupMemberType] == PBXFileReferenceType) 404 | { 405 | [arrayOfBuildFileKeys addObject:[groupMember key]]; 406 | } 407 | } 408 | return arrayOfBuildFileKeys; 409 | } 410 | 411 | - (id )memberWithKey:(NSString*)key 412 | { 413 | id groupMember = nil; 414 | 415 | if ([_children containsObject:key]) 416 | { 417 | XcodeMemberType type = [self typeForKey:key]; 418 | if (type == PBXGroupType || type == PBXVariantGroupType) 419 | { 420 | groupMember = [_project groupWithKey:key]; 421 | } 422 | else if (type == PBXFileReferenceType) 423 | { 424 | groupMember = [_project fileWithKey:key]; 425 | } 426 | } 427 | return groupMember; 428 | } 429 | 430 | - (id )memberWithDisplayName:(NSString*)name 431 | { 432 | for (id member in [self members]) 433 | { 434 | if ([[member displayName] isEqualToString:name]) 435 | { 436 | return member; 437 | } 438 | } 439 | return nil; 440 | } 441 | 442 | /* ====================================================================================================================================== */ 443 | #pragma mark - Protocol Methods 444 | 445 | - (XcodeMemberType)groupMemberType 446 | { 447 | return [self typeForKey:self.key]; 448 | } 449 | 450 | - (NSString*)displayName 451 | { 452 | if (_alias) 453 | { 454 | return _alias; 455 | } 456 | return [_pathRelativeToParent lastPathComponent]; 457 | } 458 | 459 | - (NSString*)pathRelativeToProjectRoot 460 | { 461 | if (_pathRelativeToProjectRoot == nil) 462 | { 463 | NSMutableArray* pathComponents = [[NSMutableArray alloc] init]; 464 | XCGroup* group = nil; 465 | NSString* key = [_key copy]; 466 | 467 | while ((group = [_project groupForGroupMemberWithKey:key]) != nil && !([group pathRelativeToParent] == nil)) 468 | { 469 | [pathComponents addObject:[group pathRelativeToParent]]; 470 | id old = key; 471 | key = [[group key] copy]; 472 | } 473 | 474 | NSMutableString* fullPath = [[NSMutableString alloc] init]; 475 | for (NSInteger i = (NSInteger) [pathComponents count] - 1; i >= 0; i--) 476 | { 477 | [fullPath appendFormat:@"%@/", [pathComponents objectAtIndex:i]]; 478 | } 479 | _pathRelativeToProjectRoot = [[fullPath stringByAppendingPathComponent:_pathRelativeToParent] copy]; 480 | } 481 | return _pathRelativeToProjectRoot; 482 | } 483 | 484 | /* ====================================================================================================================================== */ 485 | #pragma mark - Utility Methods 486 | 487 | - (NSString*)description 488 | { 489 | return [NSString stringWithFormat:@"Group: displayName = %@, key=%@", [self displayName], _key]; 490 | } 491 | 492 | /* ====================================================================================================================================== */ 493 | #pragma mark - Private Methods 494 | 495 | #pragma mark Private 496 | 497 | - (void)addMemberWithKey:(NSString*)key 498 | { 499 | 500 | for (NSString* childKey in _children) 501 | { 502 | if ([childKey isEqualToString:key]) 503 | { 504 | [self flagMembersAsDirty]; 505 | return; 506 | } 507 | } 508 | [_children addObject:key]; 509 | [self flagMembersAsDirty]; 510 | } 511 | 512 | - (void)flagMembersAsDirty 513 | { 514 | _members = nil; 515 | } 516 | 517 | /* ====================================================================================================================================== */ 518 | 519 | - (void)makeGroupMemberWithName:(NSString*)name contents:(id)contents type:(XcodeSourceFileType)type 520 | fileOperationStyle:(XCFileOperationType)fileOperationStyle 521 | { 522 | 523 | NSString* filePath; 524 | XCSourceFile* currentSourceFile = (XCSourceFile*) [self memberWithDisplayName:name]; 525 | if ((currentSourceFile) == nil) 526 | { 527 | NSDictionary* reference = [self makeFileReferenceWithPath:name name:nil type:type]; 528 | NSString* fileKey = [[XCKeyBuilder forItemNamed:name] build]; 529 | [[_project objects] setObject:reference forKey:fileKey]; 530 | [self addMemberWithKey:fileKey]; 531 | filePath = [self pathRelativeToProjectRoot]; 532 | } 533 | else 534 | { 535 | filePath = [[currentSourceFile pathRelativeToProjectRoot] stringByDeletingLastPathComponent]; 536 | } 537 | 538 | BOOL writeFile = NO; 539 | if (fileOperationStyle == XCFileOperationTypeOverwrite) 540 | { 541 | writeFile = YES; 542 | [_fileOperationQueue fileWithName:name existsInProjectDirectory:filePath]; 543 | } 544 | else if (fileOperationStyle == XCFileOperationTypeAcceptExisting && 545 | ![_fileOperationQueue fileWithName:name existsInProjectDirectory:filePath]) 546 | { 547 | writeFile = YES; 548 | } 549 | if (writeFile) 550 | { 551 | if ([contents isKindOfClass:[NSString class]]) 552 | { 553 | [_fileOperationQueue queueTextFile:name inDirectory:filePath withContents:contents]; 554 | } 555 | else 556 | { 557 | [_fileOperationQueue queueDataFile:name inDirectory:filePath withContents:contents]; 558 | } 559 | } 560 | } 561 | 562 | /* ====================================================================================================================================== */ 563 | 564 | #pragma mark Xcodeproj methods 565 | 566 | // creates PBXFileReference and adds to group if not already there; returns key for file reference. Locates 567 | // member via path rather than name, because that is how subprojects are stored by Xcode 568 | - (void)makeGroupMemberWithName:(NSString*)name path:(NSString*)path type:(XcodeSourceFileType)type 569 | fileOperationStyle:(XCFileOperationType)fileOperationStyle 570 | { 571 | XCSourceFile* currentSourceFile = (XCSourceFile*) [self memberWithDisplayName:name]; 572 | if ((currentSourceFile) == nil) 573 | { 574 | NSDictionary* reference = [self makeFileReferenceWithPath:path name:name type:type]; 575 | NSString* fileKey = [[XCKeyBuilder forItemNamed:name] build]; 576 | [[_project objects] setObject:reference forKey:fileKey]; 577 | [self addMemberWithKey:fileKey]; 578 | } 579 | } 580 | 581 | // makes a new group called Products and returns its key 582 | - (NSString*)makeProductsGroup:(XCSubProjectDefinition*)xcodeprojDefinition 583 | { 584 | NSMutableArray* children = [NSMutableArray array]; 585 | NSString* uniquer = @""; 586 | for (NSString* productName in [xcodeprojDefinition buildProductNames]) 587 | { 588 | [children addObject:[_project referenceProxyKeyForName:productName]]; 589 | uniquer = [uniquer stringByAppendingString:productName]; 590 | } 591 | NSString* productKey = [[XCKeyBuilder forItemNamed:[NSString stringWithFormat:@"%@-Products", uniquer]] build]; 592 | XCGroup* productsGroup = [XCGroup groupWithProject:_project key:productKey alias:@"Products" path:nil children:children]; 593 | [[_project objects] setObject:[productsGroup asDictionary] forKey:productKey]; 594 | return productKey; 595 | } 596 | 597 | // makes a new Products group (by calling the method above), makes a new projectReferences array for it and 598 | // then adds it to the PBXProject object 599 | - (void)addProductsGroupToProject:(XCSubProjectDefinition*)xcodeprojDefinition 600 | { 601 | NSString* productKey = [self makeProductsGroup:xcodeprojDefinition]; 602 | 603 | NSMutableDictionary* PBXProjectDict = [_project PBXProjectDict]; 604 | NSMutableArray* projectReferences = [PBXProjectDict valueForKey:@"projectReferences"]; 605 | 606 | NSMutableDictionary* newProjectReference = [NSMutableDictionary dictionary]; 607 | [newProjectReference setObject:productKey forKey:@"ProductGroup"]; 608 | NSString* projectFileKey = [[_project fileWithName:[xcodeprojDefinition pathRelativeToProjectRoot]] key]; 609 | [newProjectReference setObject:projectFileKey forKey:@"ProjectRef"]; 610 | 611 | if (projectReferences == nil) 612 | { 613 | projectReferences = [NSMutableArray array]; 614 | } 615 | [projectReferences addObject:newProjectReference]; 616 | [PBXProjectDict setObject:projectReferences forKey:@"projectReferences"]; 617 | } 618 | 619 | // removes PBXFileReference from group and project 620 | - (void)removeGroupMemberWithKey:(NSString*)key 621 | { 622 | NSMutableArray* children = [self valueForKey:@"children"]; 623 | [children removeObject:key]; 624 | [[_project objects] setObject:[self asDictionary] forKey:_key]; 625 | // remove PBXFileReference 626 | [[_project objects] removeObjectForKey:key]; 627 | } 628 | 629 | // removes the given key from the files arrays of the given section, if found (intended to be used with 630 | // PBXFrameworksBuildPhase and PBXResourcesBuildPhase) 631 | // they are not required because we are currently not adding these entries; Xcode is doing it for us. The existing 632 | // code for adding to a target doesn't do it, and I didn't add it since Xcode will take care of it for me and I was 633 | // avoiding modifying existing code as much as possible) 634 | - (void)removeBuildPhaseFileKey:(NSString*)key forType:(XcodeMemberType)memberType 635 | { 636 | NSArray* buildPhases = [_project keysForProjectObjectsOfType:memberType withIdentifier:nil singleton:NO required:NO]; 637 | for (NSString* buildPhaseKey in buildPhases) 638 | { 639 | NSDictionary* buildPhaseDict = [[_project objects] valueForKey:buildPhaseKey]; 640 | NSMutableArray* fileKeys = [buildPhaseDict valueForKey:@"files"]; 641 | for (NSString* fileKey in fileKeys) 642 | { 643 | if ([fileKey isEqualToString:key]) 644 | { 645 | [fileKeys removeObject:fileKey]; 646 | } 647 | } 648 | } 649 | } 650 | 651 | // removes entries from PBXBuildFiles, PBXFrameworksBuildPhase and PBXResourcesBuildPhase 652 | - (void)removeProductsGroupFromProject:(NSString*)key 653 | { 654 | // remove product group's build products from PDXBuildFiles 655 | NSDictionary* productsGroup = [[_project objects] objectForKey:key]; 656 | for (NSString* childKey in [productsGroup valueForKey:@"children"]) 657 | { 658 | NSArray* buildFileKeys = [_project keysForProjectObjectsOfType:PBXBuildFileType withIdentifier:childKey singleton:NO required:NO]; 659 | // could be zero - we didn't add the test bundle as a build product 660 | if ([buildFileKeys count] == 1) 661 | { 662 | NSString* buildFileKey = [buildFileKeys objectAtIndex:0]; 663 | [[_project objects] removeObjectForKey:buildFileKey]; 664 | [self removeBuildPhaseFileKey:buildFileKey forType:PBXFrameworksBuildPhaseType]; 665 | [self removeBuildPhaseFileKey:buildFileKey forType:PBXResourcesBuildPhaseType]; 666 | } 667 | } 668 | } 669 | 670 | /* ====================================================================================================================================== */ 671 | 672 | #pragma mark Dictionary Representations 673 | 674 | - (NSDictionary*)makeFileReferenceWithPath:(NSString*)path name:(NSString*)name type:(XcodeSourceFileType)type 675 | { 676 | NSMutableDictionary* reference = [NSMutableDictionary dictionary]; 677 | [reference setObject:[NSString stringFromMemberType:PBXFileReferenceType] forKey:@"isa"]; 678 | [reference setObject:@"4" forKey:@"fileEncoding"]; 679 | [reference setObject:NSStringFromXCSourceFileType(type) forKey:@"lastKnownFileType"]; 680 | if (name != nil) 681 | { 682 | [reference setObject:[name lastPathComponent] forKey:@"name"]; 683 | } 684 | if (path != nil) 685 | { 686 | [reference setObject:path forKey:@"path"]; 687 | } 688 | [reference setObject:@"" forKey:@"sourceTree"]; 689 | return reference; 690 | } 691 | 692 | 693 | - (NSDictionary*)asDictionary 694 | { 695 | NSMutableDictionary* groupData = [NSMutableDictionary dictionary]; 696 | [groupData setObject:[NSString stringFromMemberType:PBXGroupType] forKey:@"isa"]; 697 | [groupData setObject:@"" forKey:@"sourceTree"]; 698 | 699 | if (_alias != nil) 700 | { 701 | [groupData setObject:_alias forKey:@"name"]; 702 | } 703 | 704 | if (_pathRelativeToParent) 705 | { 706 | [groupData setObject:_pathRelativeToParent forKey:@"path"]; 707 | } 708 | 709 | if (_children) 710 | { 711 | [groupData setObject:_children forKey:@"children"]; 712 | } 713 | 714 | return groupData; 715 | } 716 | 717 | - (XcodeMemberType)typeForKey:(NSString*)key 718 | { 719 | NSDictionary* obj = [[_project objects] valueForKey:key]; 720 | return [[obj valueForKey:@"isa"] asMemberType]; 721 | } 722 | 723 | - (void)addSourceFile:(XCSourceFile*)sourceFile toTargets:(NSArray*)targets 724 | { 725 | for (XCTarget* target in targets) 726 | { 727 | [target addMember:sourceFile]; 728 | } 729 | } 730 | 731 | @end --------------------------------------------------------------------------------