diff --git a/EC/EC.entitlements b/EC/EC.entitlements index 60c1f0a..09da21d 100644 --- a/EC/EC.entitlements +++ b/EC/EC.entitlements @@ -6,7 +6,7 @@ com.apple.security.application-groups - 2WQE6AU5PD.group.com.music4kid.easycode + $(TeamIdentifierPrefix)group.com.sito.easycode diff --git a/EC/ECFileParser/ECFileParser.m b/EC/ECFileParser/ECFileParser.m index 2745092..29b80ef 100644 --- a/EC/ECFileParser/ECFileParser.m +++ b/EC/ECFileParser/ECFileParser.m @@ -25,9 +25,7 @@ - (FSElementCache*)getImpElementByContent:(NSString*)content } - (FSElementCache*)getElementByContent:(NSString*)content selection:(NSRange)range { - FSElementCache* element = nil; - FSImpProcessor* p = [FSImpProcessor new]; NSArray* elementsInFile = [p createElements:content]; for (FSElementCache* e in elementsInFile) { diff --git a/EC/ECFileParser/FSElementPool.h b/EC/ECFileParser/FSElementPool.h index ab839d6..32916f9 100644 --- a/EC/ECFileParser/FSElementPool.h +++ b/EC/ECFileParser/FSElementPool.h @@ -18,7 +18,7 @@ @property (nonatomic, strong) NSMutableDictionary* elementMap; -- (void)parseElementFromProjectFile:(NSString*)filePath complete:(dispatch_block_t)completeBlock; +//- (void)parseElementFromProjectFile:(NSString*)filePath complete:(dispatch_block_t)completeBlock; - (void)parseHeaderFile:(NSString*)filePath; - (FSElementCache*)getElementFromCache:(NSString*)elementName; diff --git a/EC/ECMapping.h b/EC/ECMapping.h index 64b9099..755ffb1 100644 --- a/EC/ECMapping.h +++ b/EC/ECMapping.h @@ -7,8 +7,9 @@ // #import +#import "ECSnippetEntry.h" @interface ECMapping : NSObject -- (NSDictionary*)provideMapping; ++ (NSArray*)defaultEntries; @end diff --git a/EC/ECMapping.m b/EC/ECMapping.m index b49a440..4835054 100644 --- a/EC/ECMapping.m +++ b/EC/ECMapping.m @@ -9,7 +9,7 @@ #import "ECMapping.h" @implementation ECMapping -- (NSDictionary*)provideMapping { ++ (NSArray*)defaultEntries { return nil; } @end diff --git a/EC/ECMappingForObjectiveC.h b/EC/ECMappingForObjectiveC.h index 0f9ae55..cbcdbcb 100644 --- a/EC/ECMappingForObjectiveC.h +++ b/EC/ECMappingForObjectiveC.h @@ -10,7 +10,5 @@ #import "ECMapping.h" @interface ECMappingForObjectiveC : ECMapping - -- (NSDictionary*)provideMapping; - ++ (NSArray*)defaultEntries; @end diff --git a/EC/ECMappingForObjectiveC.m b/EC/ECMappingForObjectiveC.m index 145b92c..1e1646f 100644 --- a/EC/ECMappingForObjectiveC.m +++ b/EC/ECMappingForObjectiveC.m @@ -8,10 +8,11 @@ #import "ECMappingForObjectiveC.h" #import "OCMapping.h" +#import "ECSnippetEntry.h" @implementation ECMappingForObjectiveC -- (NSDictionary*)provideMapping { ++ (NSArray*)defaultEntries { NSDictionary* mapping = @{ //UIViewController KeyOC_UIViewController_VDL:KeyOC_UIViewController_VDL_Value, @@ -63,9 +64,14 @@ - (NSDictionary*)provideMapping { KeyOC_Template_Label:KeyOC_Template_Label_Value, KeyOC_Template_ImageView:KeyOC_Template_ImageView_Value, - }.mutableCopy; - - return mapping; + }; + NSMutableArray* snippetList = [NSMutableArray arrayWithCapacity:mapping.count]; + [mapping enumerateKeysAndObjectsUsingBlock:^(NSString* _Nonnull key, NSString* _Nonnull code, BOOL * _Nonnull stop) { + ECSnippetEntry* snippet = [ECSnippetEntry snippetWithKey:key code:code]; + [snippetList addObject:snippet]; + }]; + NSArray* snippets = [snippetList copy]; + return snippets; } diff --git a/EC/ECMappingForSwift.h b/EC/ECMappingForSwift.h index 388e4a8..87f450c 100644 --- a/EC/ECMappingForSwift.h +++ b/EC/ECMappingForSwift.h @@ -10,7 +10,5 @@ #import "ECMapping.h" @interface ECMappingForSwift : ECMapping - -- (NSDictionary*)provideMapping; - ++ (NSArray*)defaultEntries; @end diff --git a/EC/ECMappingForSwift.m b/EC/ECMappingForSwift.m index bcb3a05..03e02c2 100644 --- a/EC/ECMappingForSwift.m +++ b/EC/ECMappingForSwift.m @@ -8,16 +8,70 @@ #import "ECMappingForSwift.h" #import "SwiftMapping.h" +#import "ECSnippetEntry.h" @implementation ECMappingForSwift -- (NSDictionary*)provideMapping { ++ (NSArray*)defaultEntries { NSDictionary* mapping = @{ - + //UIViewController + KeySwift_UIViewController_VDL:KeySwift_UIViewController_VDL_Value, + KeySwift_UIViewController_VWA:KeySwift_UIViewController_VWA_Value, + KeySwift_UIViewController_VDA:KeySwift_UIViewController_VDA_Value, + KeySwift_UIViewController_VWD:KeySwift_UIViewController_VWD_Value, + KeySwift_UIViewController_VDD:KeySwift_UIViewController_VDD_Value, + KeySwift_UIViewController_DRM:KeySwift_UIViewController_DRM_Value, + KeySwift_UIViewController_SIO:KeySwift_UIViewController_SIO_Value, + KeySwift_UIViewController_PIO:KeySwift_UIViewController_PIO_Value, - }.mutableCopy; - - return mapping; + //UIView + KeySwift_UIView_HTW:KeySwift_UIView_HTW_Value, + KeySwift_UIView_PIE:KeySwift_UIView_PIE_Value, + KeySwift_UIView_CPT:KeySwift_UIView_CPT_Value, + KeySwift_UIView_CPF:KeySwift_UIView_CPF_Value, + KeySwift_UIView_CRP:KeySwift_UIView_CRP_Value, + KeySwift_UIView_CRF:KeySwift_UIView_CRF_Value, + KeySwift_UIView_DR:KeySwift_UIView_DR_Value, + + //UIApplication + KeySwift_UIApplication_DRU:KeySwift_UIApplication_DRU_Value, + KeySwift_UIApplication_DRF:KeySwift_UIApplication_DRF_Value, + KeySwift_UIApplication_DRT:KeySwift_UIApplication_DRT_Value, + KeySwift_UIApplication_DRR:KeySwift_UIApplication_DRR_Value, + KeySwift_UIApplication_DRL:KeySwift_UIApplication_DRL_Value, + + //GCD + KeySwift_GCD_DAFM:KeySwift_GCD_DAFM_Value, + KeySwift_GCD_DASM:KeySwift_GCD_DASM_Value, + KeySwift_GCD_DAFG:KeySwift_GCD_DAFG_Value, + KeySwift_GCD_DASG:KeySwift_GCD_DASG_Value, + + //MISC + KeySwift_MISC_DEL:KeySwift_MISC_DEL_Value, + KeySwift_MISC_V:KeySwift_MISC_V_Value, + KeySwift_MISC_C:KeySwift_MISC_C_Value, + KeySwift_MISC_P:KeySwift_MISC_P_Value, + KeySwift_MISC_W:KeySwift_MISC_W_Value, + KeySwift_MISC_N:KeySwift_MISC_N_Value, + KeySwift_MISC_U:KeySwift_MISC_U_Value, + KeySwift_MISC_F:KeySwift_MISC_F_Value, + KeySwift_MISC_M:KeySwift_MISC_M_Value, + KeySwift_MISC_IMG:KeySwift_MISC_IMG_Value, + KeySwift_MISC_BUN:KeySwift_MISC_BUN_Value, + + //Template + KeySwift_Template_Button:KeySwift_Template_Button_Value, + KeySwift_Template_Label:KeySwift_Template_Label_Value, + KeySwift_Template_ImageView:KeySwift_Template_ImageView_Value, + + }; + NSMutableArray* snippetList = [NSMutableArray arrayWithCapacity:mapping.count]; + [mapping enumerateKeysAndObjectsUsingBlock:^(NSString* _Nonnull key, NSString* _Nonnull code, BOOL * _Nonnull stop) { + ECSnippetEntry* snippet = [ECSnippetEntry snippetWithKey:key code:code]; + [snippetList addObject:snippet]; + }]; + NSArray* snippets = [snippetList copy]; + return snippets; } diff --git a/EC/ECMappingHelper.m b/EC/ECMappingHelper.m index e2e203f..f9de85b 100644 --- a/EC/ECMappingHelper.m +++ b/EC/ECMappingHelper.m @@ -7,58 +7,41 @@ // #import "ECMappingHelper.h" -#import "ECMappingForObjectiveC.h" -#import "ECMappingForSwift.h" +#import "NSFileManager+Additions.h" #import "ESharedUserDefault.h" +#import "ECSnippet.h" +#import "ECSnippetHelper.h" @interface ECMappingHelper () -@property (nonatomic, strong) NSMutableDictionary* mappingOC; -@property (nonatomic, strong) NSMutableDictionary* mappingSwift; +@property (nonatomic, strong) ECSnippet* curSnippets; @end @implementation ECMappingHelper -+ (instancetype)sharedInstance -{ ++ (instancetype)sharedInstance { static ECMappingHelper* instance = nil; - static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ - instance = [ECMappingHelper new]; + instance = [[ECMappingHelper alloc] init]; }); return instance; } -- (instancetype)init -{ - self = [super init]; - if (self) { - - } - return self; -} - -- (void)checkForDuplicatedKeys:(NSDictionary*)mapping -{ - //check for duplicated keys - NSArray* keys = mapping.allKeys; - NSMutableDictionary* dic = @{}.mutableCopy; - for (NSString* key in keys) { - if ([dic objectForKey:keys]) { - NSLog(@"detect duplicated keys!"); - } - else - { - dic[key] = key; - } +- (void)reloadSnippetBySourceType:(ECSourceType)sourceType { + NSString* dirname = [ECSnippetHelper directoryForSourceType:sourceType]; + NSString* versionKey = [NSString stringWithFormat:kVersionFormat,dirname]; + NSNumber* latestVer = [ESharedUserDefault objectForKey:versionKey]; + + if ([_curSnippets.version isEqualToNumber:latestVer] == NO) { //if versions are not equal,reload from UserDefaults. + NSData* data = [ESharedUserDefault dataForKey:dirname]; + _curSnippets = [NSKeyedUnarchiver unarchiveObjectWithData:data]; } } - (BOOL)handleInvocation:(XCSourceEditorCommandInvocation *)invocation { - - //read from NSUserDefault each time - [self clearMapping]; + ECSourceType sourceType = [ECSnippetHelper sourceTypeForContentUTI:invocation.buffer.contentUTI]; + [self reloadSnippetBySourceType:sourceType]; XCSourceTextRange *selection = invocation.buffer.selections.firstObject; NSMutableArray* lines = invocation.buffer.lines; @@ -67,12 +50,11 @@ - (BOOL)handleInvocation:(XCSourceEditorCommandInvocation *)invocation { int matchedCount = 0; - if (index > lines.count-1) { + if (index > lines.count - 1) { return false; } NSString* originalLine = lines[index]; - int matchLength = 8;//max match length for shortcut while (matchLength >= 1) { @@ -81,19 +63,14 @@ - (BOOL)handleInvocation:(XCSourceEditorCommandInvocation *)invocation { NSRange targetRange = NSMakeRange(column-matchLength, matchLength); NSString* lastNStr = [originalLine substringWithRange:targetRange]; - BOOL isOC = true; - if ([invocation.buffer.contentUTI isEqualToString:@"public.swift-source"]) { - isOC = false; - } - NSString* matchedVal = [self getMatchedCode:lastNStr isOC:isOC]; + NSString* matchedVal = [self matchedCode:lastNStr forSourceType:sourceType]; if (matchedVal.length > 0) { - int numberOfSpaceIndent = (int)[originalLine rangeOfString:lastNStr].location; NSString* indentStr = @""; while (numberOfSpaceIndent>0) { indentStr = [indentStr stringByAppendingString:@" "]; - numberOfSpaceIndent --; + numberOfSpaceIndent--; } NSArray* linesToInsert = [self convertToLines:matchedVal]; @@ -105,7 +82,7 @@ - (BOOL)handleInvocation:(XCSourceEditorCommandInvocation *)invocation { range:targetRange]; //insert the rest - for (int i = 1; i < linesToInsert.count; i ++) { + for (int i = 1; i < linesToInsert.count; i++) { NSString* lineToInsert = linesToInsert[i]; //indent lineToInsert = [NSString stringWithFormat:@"%@%@", indentStr, lineToInsert]; @@ -118,11 +95,10 @@ - (BOOL)handleInvocation:(XCSourceEditorCommandInvocation *)invocation { } } - matchLength --; + matchLength--; } - //adjust selection if (matchedCount > 0) { selection.start = XCSourceTextPositionMake(selection.start.line, selection.start.column-matchedCount); @@ -132,62 +108,28 @@ - (BOOL)handleInvocation:(XCSourceEditorCommandInvocation *)invocation { } -- (NSString*)getMatchedCode:(NSString*)abbr isOC:(BOOL)isOC -{ +- (NSString*)matchedCode:(NSString*)abbr forSourceType:(ECSourceType)type { //need to detect swift or oc - NSDictionary* mappingDic = nil; - - if (isOC) { - mappingDic = self.mappingOC; - } - else - { - mappingDic = self.mappingSwift; - } + NSArray* entries = _curSnippets.entries; + __block NSInteger index = NSNotFound; + [_curSnippets.entries enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock:^(ECSnippetEntry * _Nonnull entry, NSUInteger idx, BOOL * _Nonnull stop) { + if ([entry.key hasPrefix:abbr] || [entry.key isEqual:abbr]) { + index = idx; + *stop = YES; + } + }]; - if ([mappingDic objectForKey:abbr] != nil) { - return [mappingDic objectForKey:abbr]; + if (index != NSNotFound) { + NSString* matchedCode = [entries[index] code]; + return matchedCode; } return nil; } - -- (NSArray*)convertToLines:(NSString*)codeStr -{ - NSMutableArray* lines = @[].mutableCopy; - +- (NSArray*)convertToLines:(NSString*)codeStr { NSArray* arr = [codeStr componentsSeparatedByString:@"\n"]; - - for (NSString* line in arr) { - [lines addObject:line]; - } - - return lines; -} - -- (NSMutableDictionary*)mappingOC -{ - if (_mappingOC == nil) { - _mappingOC = [_UD readMappingForOC].mutableCopy; - } - return _mappingOC; -} - -- (NSMutableDictionary*)mappingSwift -{ - if (_mappingSwift == nil) { - _mappingSwift = [_UD readMappingForSwift].mutableCopy; - } - return _mappingSwift; -} - -- (void)clearMapping -{ - self.mappingOC = nil; - self.mappingSwift = nil; - - [_UD clearMapping]; + return arr; } @end diff --git a/EC/EasyCodeManager.m b/EC/EasyCodeManager.m index dc25c68..e4ac5c0 100644 --- a/EC/EasyCodeManager.m +++ b/EC/EasyCodeManager.m @@ -7,7 +7,6 @@ // #import "EasyCodeManager.h" -#import "ECMappingForObjectiveC.h" #import "ECGenerateHelper.h" #import "ECMappingHelper.h" @@ -31,6 +30,7 @@ + (instancetype)sharedInstance - (void)handleInvocation:(XCSourceEditorCommandInvocation *)invocation { + //dynamic code generation based on class parsing like FastStub(https://github.com/music4kid/FastStub-Xcode) if ([[ECGenerateHelper sharedInstance] handleInvocation:invocation]) { return; @@ -44,5 +44,4 @@ - (void)handleInvocation:(XCSourceEditorCommandInvocation *)invocation } - @end diff --git a/EC/SourceEditorExtension.m b/EC/SourceEditorExtension.m index a612dc2..89306e5 100644 --- a/EC/SourceEditorExtension.m +++ b/EC/SourceEditorExtension.m @@ -10,11 +10,10 @@ @implementation SourceEditorExtension - - (void)extensionDidFinishLaunching { - NSLog(@"extensionDidFinishLaunching..."); // If your extension needs to do any work at launch, implement this optional method. +// NSLog(@"extensionDidFinishLaunching..."); } diff --git a/EC/SwiftMapping.h b/EC/SwiftMapping.h index e7c7783..51bd3e6 100644 --- a/EC/SwiftMapping.h +++ b/EC/SwiftMapping.h @@ -9,5 +9,256 @@ #ifndef SwiftMapping_h #define SwiftMapping_h +#pragma mark- UIViewController + +#define KeySwift_UIViewController_VDL @"vdl" +#define KeySwift_UIViewController_VDL_Value @"\ +override func viewDidLoad() {\n\ +super.viewDidLoad()\n\ +\n\ +<#code#>\n\ +}" + +#define KeySwift_UIViewController_VWA @"vwa" +#define KeySwift_UIViewController_VWA_Value @"\ +override func viewWillAppear(_ animated: Bool) {\n\ +super.viewWillAppear(animated)\n\ +\n\ +<#code#>\n\ +}" + +#define KeySwift_UIViewController_VDA @"vda" +#define KeySwift_UIViewController_VDA_Value @"\ +override func viewDidAppear(_ animated: Bool) {\n\ +super.viewDidAppear(animated)\n\ +\n\ +<#code#>\n\ +}" + +#define KeySwift_UIViewController_VWD @"vwd" +#define KeySwift_UIViewController_VWD_Value @"\ +override func viewWillDisappear(_ animated: Bool) {\n\ +super.viewWillDisappear(animated)\n\ +\n\ +<#code#>\n\ +}" + +#define KeySwift_UIViewController_VDD @"vdd" +#define KeySwift_UIViewController_VDD_Value @"\ +override func viewDidDisappear(_ animated: Bool) {\n\ +super.viewDidDisappear(animated)\n\ +\n\ +<#code#>\n\ +}" + +#define KeySwift_UIViewController_DRM @"drm" +#define KeySwift_UIViewController_DRM_Value @"\ +override func didReceiveMemoryWarning() {\n\ +<#code#>\n\ +}" + +#define KeySwift_UIViewController_SIO @"sio" +#define KeySwift_UIViewController_SIO_Value @"\ +override var supportedInterfaceOrientations: UIInterfaceOrientationMask{\n\ +<#code#>\n\ +}" + +#define KeySwift_UIViewController_PIO @"pio" +#define KeySwift_UIViewController_PIO_Value @"\ +override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation{\n\ +<#code#>\n\ +}" + +#pragma mark- UIView + +#define KeySwift_UIView_HTW @"htw" +#define KeySwift_UIView_HTW_Value @"\ +- (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event\n\ +{\n\ +<#code#>\n\ +}" + +#define KeySwift_UIView_PIE @"pie" +#define KeySwift_UIView_PIE_Value @"\ +- (BOOL)pointInside:(CGPoint)point withEvent:(nullable UIEvent *)event\n\ +{\n\ +<#code#>\n\ +}" + +#define KeySwift_UIView_CPT @"cpt" +#define KeySwift_UIView_CPT_Value @"\ +- (CGPoint)convertPoint:(CGPoint)point toView:(nullable UIView *)view\n\ +{\n\ +<#code#>\n\ +}" + +#define KeySwift_UIView_CPF @"cpf" +#define KeySwift_UIView_CPF_Value @"\ +- (CGPoint)convertPoint:(CGPoint)point fromView:(nullable UIView *)view\n\ +{\n\ +<#code#>\n\ +}" + +#define KeySwift_UIView_CRP @"crp" +#define KeySwift_UIView_CRP_Value @"\ +- (CGRect)convertRect:(CGRect)rect toView:(nullable UIView *)view\n\ +{\n\ +<#code#>\n\ +}" + +#define KeySwift_UIView_CRF @"crf" +#define KeySwift_UIView_CRF_Value @"\ +- (CGRect)convertRect:(CGRect)rect fromView:(nullable UIView *)view\n\ +{\n\ +<#code#>\n\ +}" + +#define KeySwift_UIView_DR @"dr" +#define KeySwift_UIView_DR_Value @"\ +- (void)drawRect:(CGRect)rect\n\ +{\n\ +<#code#>\n\ +}" + +#pragma mark- UIAppication +#define KeySwift_UIApplication_DRU @"dru" +#define KeySwift_UIApplication_DRU_Value @"\ +- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings\n\ +{\n\ +<#code#>\n\ +}" + +#define KeySwift_UIApplication_DRF @"drf" +#define KeySwift_UIApplication_DRF_Value @"\ +- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken\n\ +{\n\ +<#code#>\n\ +}" + +#define KeySwift_UIApplication_DRT @"drt" +#define KeySwift_UIApplication_DRT_Value @"\ +- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error\n\ +{\n\ +<#code#>\n\ +}" + +#define KeySwift_UIApplication_DRR @"drr" +#define KeySwift_UIApplication_DRR_Value @"\ +- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo\n\ +{\n\ +<#code#>\n\ +}" + +#define KeySwift_UIApplication_DRL @"drl" +#define KeySwift_UIApplication_DRL_Value @"\ +- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification\n\ +{\n\ +<#code#>\n\ +}" + +#pragma mark- GCD +#define KeySwift_GCD_DAFM @"dafm" +#define KeySwift_GCD_DAFM_Value @"\ +dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(<#delayInSeconds#> * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{\n\ +<#code to be executed after a specified delay#>\n\ +});" + +#define KeySwift_GCD_DASM @"dasm" +#define KeySwift_GCD_DASM_Value @"\ +dispatch_async(dispatch_get_main_queue(), ^{\n\ +<#code#>\n\ +});" + +#define KeySwift_GCD_DAFG @"dafg" +#define KeySwift_GCD_DAFG_Value @"\ +dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(<#delayInSeconds#> * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{\n\ +<#code to be executed after a specified delay#>\n\ +});" + +#define KeySwift_GCD_DASG @"dasg" +#define KeySwift_GCD_DASG_Value @"\ +dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{\n\ +<#code#>\n\ +});" + + +#pragma mark- MISC +#define KeySwift_MISC_DEL @"del" +#define KeySwift_MISC_DEL_Value @"\ +([UIApplication sharedApplication].delegate)" + +#define KeySwift_MISC_V @"v" +#define KeySwift_MISC_V_Value @"\ +- (void)<#method#>" + +#define KeySwift_MISC_C @"c" +#define KeySwift_MISC_C_Value @"\ +[UIColor colorWith<#color#>]" + +#define KeySwift_MISC_P @"p" +#define KeySwift_MISC_P_Value @"\ +@property (nonatomic, strong) <#type#> <#name#>" + +#define KeySwift_MISC_W @"w" +#define KeySwift_MISC_W_Value @"\ +__weak __typeof(self) wself = self;" + +#define KeySwift_MISC_N @"n" +#define KeySwift_MISC_N_Value @"\ +[[NSNotificationCenter defaultCenter] <#method#>];" + +#define KeySwift_MISC_U @"u" +#define KeySwift_MISC_U_Value @"\ +[[NSUserDefaults standardUserDefaults] <#method#>];" + +#define KeySwift_MISC_F @"f" +#define KeySwift_MISC_F_Value @"\ +[[NSFileManager defaultManager] <#method#>];" + +#define KeySwift_MISC_M @"m" +#define KeySwift_MISC_M_Value @"\ +#pragma mark - <#text#>" + +#define KeySwift_MISC_URL @"url" +#define KeySwift_MISC_URL_Value @"\ +[NSURL URLWithString:<#(nonnull NSString *)#>]" + +#define KeySwift_MISC_IMG @"img" +#define KeySwift_MISC_IMG_Value @"\ +[UIImage imageNamed:<#(nonnull NSString *)#>];" + +#define KeySwift_MISC_BUN @"bun" +#define KeySwift_MISC_BUN_Value @"\ +[[NSBundle mainBundle] pathForResource:<#(nullable NSString *)#> ofType:<#(nullable NSString *)#>];" + + + +#pragma mark- Template +#define KeySwift_Template_Button @"btn" +#define KeySwift_Template_Button_Value @"\ +UIButton *btn = [UIButton new];\n\ +[btn setBackgroundColor:<#(UIColor * _Nullable)#>];\n\ +[btn setTitle:<#(nullable NSString *)#> forState:UIControlStateNormal];\n\ +[btn addTarget:<#(nullable id)#> action:<#(nonnull SEL)#> forControlEvents:UIControlEventTouchUpInside];\n\ +[<#self#> addSubview:btn];\n\ +<#self.btn#> = btn;" + +#define KeySwift_Template_Label @"lb" +#define KeySwift_Template_Label_Value @"\ +UILabel *lb = [UILabel new];\n\ +lb.text = <#text#>;\n\ +lb.textColor = <#(UIColor * _Nullable)#>;\n\ +lb.font = [UIFont systemFontOfSize:<#(CGFloat)#>];\n\ +lb.backgroundColor = [UIColor clearColor];\n\ +[<#self#> addSubview:lb];\n\ +<#self.lb#> = lb;" + +#define KeySwift_Template_ImageView @"iv" +#define KeySwift_Template_ImageView_Value @"\ +UIImageView* imgV = [UIImageView new];\n\ +imgV.backgroundColor = [UIColor clearColor];\n\ +imgV.image = [UIImage imageNamed:<#(nonnull NSString *)#>];\n\ +[<#self#> addSubview:imgV];\n\ +<#self.imgV#> = imgV;" #endif /* SwiftMapping_h */ diff --git a/EasyCode.xcodeproj/project.pbxproj b/EasyCode.xcodeproj/project.pbxproj index 5f556a8..8387f90 100644 --- a/EasyCode.xcodeproj/project.pbxproj +++ b/EasyCode.xcodeproj/project.pbxproj @@ -7,9 +7,38 @@ objects = { /* Begin PBXBuildFile section */ + 0BEB36A81E671F760039FF67 /* EditorWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6741CE661DB884DD000408E7 /* EditorWindowController.m */; }; + 2A1CD1E41E68179A007A2700 /* NSWindowController+Additions.m in Sources */ = {isa = PBXBuildFile; fileRef = 2A1CD1E31E68179A007A2700 /* NSWindowController+Additions.m */; }; + 2A2DBB171E6566E4008C78AF /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 2A2DBB161E6566E4008C78AF /* Localizable.strings */; }; + 2A2DBB2D1E66A0F6008C78AF /* NSString+Additions.m in Sources */ = {isa = PBXBuildFile; fileRef = 2A2DBB2A1E66A0F6008C78AF /* NSString+Additions.m */; }; + 2A2DBB2E1E66A0F6008C78AF /* NSWindow+Additions.m in Sources */ = {isa = PBXBuildFile; fileRef = 2A2DBB2C1E66A0F6008C78AF /* NSWindow+Additions.m */; }; + 2A2DBB311E66A133008C78AF /* NSFileManager+Additions.m in Sources */ = {isa = PBXBuildFile; fileRef = 2A2DBB301E66A133008C78AF /* NSFileManager+Additions.m */; }; + 2A68099F1E7FAB1700750C23 /* EEditorTableMenu.m in Sources */ = {isa = PBXBuildFile; fileRef = 2A68099E1E7FAB1700750C23 /* EEditorTableMenu.m */; }; + 2A6809A21E7FC4DE00750C23 /* EEditorTableRowView.m in Sources */ = {isa = PBXBuildFile; fileRef = 2A6809A11E7FC4DE00750C23 /* EEditorTableRowView.m */; }; + 2A6809A51E7FCE1900750C23 /* NSAlert+Additions.m in Sources */ = {isa = PBXBuildFile; fileRef = 2A6809A41E7FCE1900750C23 /* NSAlert+Additions.m */; }; + 2AD25BC71E67F2FE007AE3B8 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 670F2ED91DB2284400A1739F /* Assets.xcassets */; }; + 2AD25BCD1E67F6E7007AE3B8 /* ECSnippetsDocument.m in Sources */ = {isa = PBXBuildFile; fileRef = 2AD25BCC1E67F6E7007AE3B8 /* ECSnippetsDocument.m */; }; + 2AD25BD31E6806AA007AE3B8 /* ECMainWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2AD25BD11E6806AA007AE3B8 /* ECMainWindowController.m */; }; + 2AD25BD41E6806AA007AE3B8 /* ECMainWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2AD25BD21E6806AA007AE3B8 /* ECMainWindowController.xib */; }; + 2AD4BADD1E6E5195007A443C /* ECMappingForObjectiveC.m in Sources */ = {isa = PBXBuildFile; fileRef = 67302B0F1DB23C010030C360 /* ECMappingForObjectiveC.m */; }; + 2AD4BADF1E6E5205007A443C /* ECSnippetEntry.m in Sources */ = {isa = PBXBuildFile; fileRef = 6741CE6B1DB89894000408E7 /* ECSnippetEntry.m */; }; + 2AD4BAE01E6E5210007A443C /* NSString+Additions.m in Sources */ = {isa = PBXBuildFile; fileRef = 2A2DBB2A1E66A0F6008C78AF /* NSString+Additions.m */; }; + 2AD4BAE31E6E5272007A443C /* ECSnippet.m in Sources */ = {isa = PBXBuildFile; fileRef = 2AD4BAE21E6E5272007A443C /* ECSnippet.m */; }; + 2AD4BAE41E6E5272007A443C /* ECSnippet.m in Sources */ = {isa = PBXBuildFile; fileRef = 2AD4BAE21E6E5272007A443C /* ECSnippet.m */; }; + 2AD4BAFC1E6E6183007A443C /* NSFileWrapper+Additions.m in Sources */ = {isa = PBXBuildFile; fileRef = 2AD4BAFB1E6E6183007A443C /* NSFileWrapper+Additions.m */; }; + 2AD4BAFD1E6E6183007A443C /* NSFileWrapper+Additions.m in Sources */ = {isa = PBXBuildFile; fileRef = 2AD4BAFB1E6E6183007A443C /* NSFileWrapper+Additions.m */; }; + 2AD4BB001E6E67E2007A443C /* ECSnippetHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 2AD4BAFF1E6E67E2007A443C /* ECSnippetHelper.m */; }; + 2AD4BB011E6E67E2007A443C /* ECSnippetHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 2AD4BAFF1E6E67E2007A443C /* ECSnippetHelper.m */; }; + 2AD4BB0A1E6EAD6F007A443C /* NSFileManager+Additions.m in Sources */ = {isa = PBXBuildFile; fileRef = 2A2DBB301E66A133008C78AF /* NSFileManager+Additions.m */; }; + 2AD4BB911E76310E007A443C /* DetailWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2AD4BB8F1E76310E007A443C /* DetailWindowController.m */; }; + 2AD4BB921E76310E007A443C /* DetailWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2AD4BB901E76310E007A443C /* DetailWindowController.xib */; }; + 2AD4BB9A1E763131007A443C /* ECustomButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 2AD4BB951E763131007A443C /* ECustomButton.m */; }; + 2AD4BB9B1E763131007A443C /* EEditorTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 2AD4BB971E763131007A443C /* EEditorTableView.m */; }; + 2AD4BB9C1E763131007A443C /* EVerticalScrollView.m in Sources */ = {isa = PBXBuildFile; fileRef = 2AD4BB991E763131007A443C /* EVerticalScrollView.m */; }; + 2AD4BBA01E763238007A443C /* ECSafeCast.m in Sources */ = {isa = PBXBuildFile; fileRef = 2AD4BB9F1E763238007A443C /* ECSafeCast.m */; }; + 2AD4BBA11E7632DD007A443C /* ECSafeCast.m in Sources */ = {isa = PBXBuildFile; fileRef = 2AD4BB9F1E763238007A443C /* ECSafeCast.m */; }; 670F2ED51DB2284400A1739F /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 670F2ED41DB2284400A1739F /* AppDelegate.m */; }; 670F2ED81DB2284400A1739F /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 670F2ED71DB2284400A1739F /* main.m */; }; - 670F2EDA1DB2284400A1739F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 670F2ED91DB2284400A1739F /* Assets.xcassets */; }; 670F2EDD1DB2284400A1739F /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 670F2EDB1DB2284400A1739F /* MainMenu.xib */; }; 670F2EEB1DB228DD00A1739F /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 670F2EEA1DB228DD00A1739F /* Cocoa.framework */; }; 670F2EF11DB228DD00A1739F /* SourceEditorExtension.m in Sources */ = {isa = PBXBuildFile; fileRef = 670F2EF01DB228DD00A1739F /* SourceEditorExtension.m */; }; @@ -34,18 +63,9 @@ 6741CE591DB87CE8000408E7 /* ECMappingForSwift.m in Sources */ = {isa = PBXBuildFile; fileRef = 67AFF68D1DB5B45400697135 /* ECMappingForSwift.m */; }; 6741CE5A1DB87CE8000408E7 /* SwiftMapping.h in Sources */ = {isa = PBXBuildFile; fileRef = 67AFF68B1DB5B44000697135 /* SwiftMapping.h */; }; 6741CE5B1DB87CE8000408E7 /* ECMappingForObjectiveC.h in Sources */ = {isa = PBXBuildFile; fileRef = 67302B0E1DB23C010030C360 /* ECMappingForObjectiveC.h */; }; - 6741CE5C1DB87CE8000408E7 /* ECMappingForObjectiveC.m in Sources */ = {isa = PBXBuildFile; fileRef = 67302B0F1DB23C010030C360 /* ECMappingForObjectiveC.m */; }; 6741CE5D1DB87CE8000408E7 /* OCMapping.h in Sources */ = {isa = PBXBuildFile; fileRef = 6751C6251DB23D5500004735 /* OCMapping.h */; }; - 6741CE681DB884DD000408E7 /* EditorWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6741CE661DB884DD000408E7 /* EditorWindowController.m */; }; 6741CE691DB884DD000408E7 /* EditorWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6741CE671DB884DD000408E7 /* EditorWindowController.xib */; }; - 6741CE6C1DB89894000408E7 /* EShortcutEntry.m in Sources */ = {isa = PBXBuildFile; fileRef = 6741CE6B1DB89894000408E7 /* EShortcutEntry.m */; }; - 6741CE711DB8A04A000408E7 /* edit.png in Resources */ = {isa = PBXBuildFile; fileRef = 6741CE6E1DB8A04A000408E7 /* edit.png */; }; - 6741CE721DB8A04A000408E7 /* remove.png in Resources */ = {isa = PBXBuildFile; fileRef = 6741CE6F1DB8A04A000408E7 /* remove.png */; }; - 6741CE731DB8A04A000408E7 /* add.png in Resources */ = {isa = PBXBuildFile; fileRef = 6741CE701DB8A04A000408E7 /* add.png */; }; - 6741CE761DB8A713000408E7 /* EVerticalScrollView.m in Sources */ = {isa = PBXBuildFile; fileRef = 6741CE751DB8A713000408E7 /* EVerticalScrollView.m */; }; - 6741CE791DB8B4DF000408E7 /* EEditorTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 6741CE781DB8B4DF000408E7 /* EEditorTableView.m */; }; - 6741CE7E1DB8BA19000408E7 /* DetailWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6741CE7C1DB8BA19000408E7 /* DetailWindowController.m */; }; - 6741CE7F1DB8BA19000408E7 /* DetailWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6741CE7D1DB8BA19000408E7 /* DetailWindowController.xib */; }; + 6741CE6C1DB89894000408E7 /* ECSnippetEntry.m in Sources */ = {isa = PBXBuildFile; fileRef = 6741CE6B1DB89894000408E7 /* ECSnippetEntry.m */; }; 67AFF68E1DB5B45400697135 /* ECMappingForSwift.m in Sources */ = {isa = PBXBuildFile; fileRef = 67AFF68D1DB5B45400697135 /* ECMappingForSwift.m */; }; 67AFF6931DB5B71200697135 /* ECMappingHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 67AFF6921DB5B71200697135 /* ECMappingHelper.m */; }; 67AFF6A01DB5C8A100697135 /* ECGenerateHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 67AFF69F1DB5C8A100697135 /* ECGenerateHelper.m */; }; @@ -60,15 +80,6 @@ 67AFF6EB1DB5CBF500697135 /* ECFileParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 67AFF6E91DB5CBF500697135 /* ECFileParser.m */; }; 67AFF6F01DB5CC2E00697135 /* NSString+PDRegex.m in Sources */ = {isa = PBXBuildFile; fileRef = 67AFF6EF1DB5CC2E00697135 /* NSString+PDRegex.m */; }; 67AFF6F31DB5CC5B00697135 /* FSElementProperty.m in Sources */ = {isa = PBXBuildFile; fileRef = 67AFF6F21DB5CC5B00697135 /* FSElementProperty.m */; }; - 67F73F9F1DCC8A70000780C3 /* mainbg.png in Resources */ = {isa = PBXBuildFile; fileRef = 67F73F9D1DCC8A70000780C3 /* mainbg.png */; }; - 67F73FA21DCC8ADF000780C3 /* mainbg@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 67F73FA11DCC8ADF000780C3 /* mainbg@2x.png */; }; - 67F73FA51DCC8BF7000780C3 /* btnbg.png in Resources */ = {isa = PBXBuildFile; fileRef = 67F73FA31DCC8BF7000780C3 /* btnbg.png */; }; - 67F73FA61DCC8BF7000780C3 /* btnbg@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 67F73FA41DCC8BF7000780C3 /* btnbg@2x.png */; }; - 67F73FA91DCC8E31000780C3 /* btnbg2.png in Resources */ = {isa = PBXBuildFile; fileRef = 67F73FA71DCC8E31000780C3 /* btnbg2.png */; }; - 67F73FAA1DCC8E31000780C3 /* btnbg2@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 67F73FA81DCC8E31000780C3 /* btnbg2@2x.png */; }; - 67F73FAD1DCC9278000780C3 /* btnguide.png in Resources */ = {isa = PBXBuildFile; fileRef = 67F73FAB1DCC9278000780C3 /* btnguide.png */; }; - 67F73FAE1DCC9278000780C3 /* btnguide@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 67F73FAC1DCC9278000780C3 /* btnguide@2x.png */; }; - 67F73FB11DCC9625000780C3 /* CustomButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 67F73FB01DCC9625000780C3 /* CustomButton.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -96,6 +107,45 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 2A1CD1E21E68179A007A2700 /* NSWindowController+Additions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSWindowController+Additions.h"; sourceTree = ""; }; + 2A1CD1E31E68179A007A2700 /* NSWindowController+Additions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSWindowController+Additions.m"; sourceTree = ""; }; + 2A1CD20A1E697AAA007A2700 /* easycode.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = easycode.pch; sourceTree = ""; }; + 2A2DBB161E6566E4008C78AF /* Localizable.strings */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; path = Localizable.strings; sourceTree = ""; }; + 2A2DBB291E66A0F6008C78AF /* NSString+Additions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+Additions.h"; sourceTree = ""; }; + 2A2DBB2A1E66A0F6008C78AF /* NSString+Additions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+Additions.m"; sourceTree = ""; }; + 2A2DBB2B1E66A0F6008C78AF /* NSWindow+Additions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSWindow+Additions.h"; sourceTree = ""; }; + 2A2DBB2C1E66A0F6008C78AF /* NSWindow+Additions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSWindow+Additions.m"; sourceTree = ""; }; + 2A2DBB2F1E66A133008C78AF /* NSFileManager+Additions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSFileManager+Additions.h"; sourceTree = ""; }; + 2A2DBB301E66A133008C78AF /* NSFileManager+Additions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSFileManager+Additions.m"; sourceTree = ""; }; + 2A68099D1E7FAB1700750C23 /* EEditorTableMenu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EEditorTableMenu.h; sourceTree = ""; }; + 2A68099E1E7FAB1700750C23 /* EEditorTableMenu.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EEditorTableMenu.m; sourceTree = ""; }; + 2A6809A01E7FC4DE00750C23 /* EEditorTableRowView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EEditorTableRowView.h; sourceTree = ""; }; + 2A6809A11E7FC4DE00750C23 /* EEditorTableRowView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EEditorTableRowView.m; sourceTree = ""; }; + 2A6809A31E7FCE1900750C23 /* NSAlert+Additions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSAlert+Additions.h"; sourceTree = ""; }; + 2A6809A41E7FCE1900750C23 /* NSAlert+Additions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSAlert+Additions.m"; sourceTree = ""; }; + 2AD25BCB1E67F6E7007AE3B8 /* ECSnippetsDocument.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ECSnippetsDocument.h; sourceTree = ""; }; + 2AD25BCC1E67F6E7007AE3B8 /* ECSnippetsDocument.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ECSnippetsDocument.m; sourceTree = ""; }; + 2AD25BD01E6806AA007AE3B8 /* ECMainWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ECMainWindowController.h; sourceTree = ""; }; + 2AD25BD11E6806AA007AE3B8 /* ECMainWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ECMainWindowController.m; sourceTree = ""; }; + 2AD25BD21E6806AA007AE3B8 /* ECMainWindowController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ECMainWindowController.xib; sourceTree = ""; }; + 2AD4BAE11E6E5272007A443C /* ECSnippet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ECSnippet.h; sourceTree = ""; }; + 2AD4BAE21E6E5272007A443C /* ECSnippet.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ECSnippet.m; sourceTree = ""; }; + 2AD4BAFA1E6E6183007A443C /* NSFileWrapper+Additions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSFileWrapper+Additions.h"; sourceTree = ""; }; + 2AD4BAFB1E6E6183007A443C /* NSFileWrapper+Additions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSFileWrapper+Additions.m"; sourceTree = ""; }; + 2AD4BAFE1E6E67E2007A443C /* ECSnippetHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ECSnippetHelper.h; sourceTree = ""; }; + 2AD4BAFF1E6E67E2007A443C /* ECSnippetHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ECSnippetHelper.m; sourceTree = ""; }; + 2AD4BB021E6E85B4007A443C /* ECDefine.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ECDefine.h; sourceTree = ""; }; + 2AD4BB8E1E76310E007A443C /* DetailWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DetailWindowController.h; sourceTree = ""; }; + 2AD4BB8F1E76310E007A443C /* DetailWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DetailWindowController.m; sourceTree = ""; }; + 2AD4BB901E76310E007A443C /* DetailWindowController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = DetailWindowController.xib; sourceTree = ""; }; + 2AD4BB941E763131007A443C /* ECustomButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ECustomButton.h; sourceTree = ""; }; + 2AD4BB951E763131007A443C /* ECustomButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ECustomButton.m; sourceTree = ""; }; + 2AD4BB961E763131007A443C /* EEditorTableView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EEditorTableView.h; sourceTree = ""; }; + 2AD4BB971E763131007A443C /* EEditorTableView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EEditorTableView.m; sourceTree = ""; }; + 2AD4BB981E763131007A443C /* EVerticalScrollView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EVerticalScrollView.h; sourceTree = ""; }; + 2AD4BB991E763131007A443C /* EVerticalScrollView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EVerticalScrollView.m; sourceTree = ""; }; + 2AD4BB9E1E763238007A443C /* ECSafeCast.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ECSafeCast.h; sourceTree = ""; }; + 2AD4BB9F1E763238007A443C /* ECSafeCast.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ECSafeCast.m; sourceTree = ""; }; 670F2ED01DB2284400A1739F /* EasyCode.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = EasyCode.app; sourceTree = BUILT_PRODUCTS_DIR; }; 670F2ED31DB2284400A1739F /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 670F2ED41DB2284400A1739F /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; @@ -129,18 +179,8 @@ 6741CE651DB884DD000408E7 /* EditorWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EditorWindowController.h; sourceTree = ""; }; 6741CE661DB884DD000408E7 /* EditorWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EditorWindowController.m; sourceTree = ""; }; 6741CE671DB884DD000408E7 /* EditorWindowController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = EditorWindowController.xib; sourceTree = ""; }; - 6741CE6A1DB89894000408E7 /* EShortcutEntry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EShortcutEntry.h; sourceTree = ""; }; - 6741CE6B1DB89894000408E7 /* EShortcutEntry.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EShortcutEntry.m; sourceTree = ""; }; - 6741CE6E1DB8A04A000408E7 /* edit.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = edit.png; sourceTree = ""; }; - 6741CE6F1DB8A04A000408E7 /* remove.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = remove.png; sourceTree = ""; }; - 6741CE701DB8A04A000408E7 /* add.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = add.png; sourceTree = ""; }; - 6741CE741DB8A713000408E7 /* EVerticalScrollView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EVerticalScrollView.h; sourceTree = ""; }; - 6741CE751DB8A713000408E7 /* EVerticalScrollView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EVerticalScrollView.m; sourceTree = ""; }; - 6741CE771DB8B4DF000408E7 /* EEditorTableView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EEditorTableView.h; sourceTree = ""; }; - 6741CE781DB8B4DF000408E7 /* EEditorTableView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EEditorTableView.m; sourceTree = ""; }; - 6741CE7B1DB8BA19000408E7 /* DetailWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DetailWindowController.h; sourceTree = ""; }; - 6741CE7C1DB8BA19000408E7 /* DetailWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DetailWindowController.m; sourceTree = ""; }; - 6741CE7D1DB8BA19000408E7 /* DetailWindowController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = DetailWindowController.xib; sourceTree = ""; }; + 6741CE6A1DB89894000408E7 /* ECSnippetEntry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ECSnippetEntry.h; sourceTree = ""; }; + 6741CE6B1DB89894000408E7 /* ECSnippetEntry.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ECSnippetEntry.m; sourceTree = ""; }; 6751C6251DB23D5500004735 /* OCMapping.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OCMapping.h; sourceTree = ""; }; 676E320D1DB70B2000C9DC9B /* EasyCode.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = EasyCode.entitlements; sourceTree = ""; }; 67AFF68B1DB5B44000697135 /* SwiftMapping.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SwiftMapping.h; sourceTree = ""; }; @@ -172,16 +212,6 @@ 67AFF6EF1DB5CC2E00697135 /* NSString+PDRegex.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+PDRegex.m"; sourceTree = ""; }; 67AFF6F11DB5CC5B00697135 /* FSElementProperty.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FSElementProperty.h; sourceTree = ""; }; 67AFF6F21DB5CC5B00697135 /* FSElementProperty.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FSElementProperty.m; sourceTree = ""; }; - 67F73F9D1DCC8A70000780C3 /* mainbg.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = mainbg.png; sourceTree = ""; }; - 67F73FA11DCC8ADF000780C3 /* mainbg@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "mainbg@2x.png"; sourceTree = ""; }; - 67F73FA31DCC8BF7000780C3 /* btnbg.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = btnbg.png; sourceTree = ""; }; - 67F73FA41DCC8BF7000780C3 /* btnbg@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "btnbg@2x.png"; sourceTree = ""; }; - 67F73FA71DCC8E31000780C3 /* btnbg2.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = btnbg2.png; sourceTree = ""; }; - 67F73FA81DCC8E31000780C3 /* btnbg2@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "btnbg2@2x.png"; sourceTree = ""; }; - 67F73FAB1DCC9278000780C3 /* btnguide.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = btnguide.png; sourceTree = ""; }; - 67F73FAC1DCC9278000780C3 /* btnguide@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "btnguide@2x.png"; sourceTree = ""; }; - 67F73FAF1DCC9625000780C3 /* CustomButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CustomButton.h; sourceTree = ""; }; - 67F73FB01DCC9625000780C3 /* CustomButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CustomButton.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -203,6 +233,60 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 2A2DBB281E66A0F6008C78AF /* Additions */ = { + isa = PBXGroup; + children = ( + 2A2DBB291E66A0F6008C78AF /* NSString+Additions.h */, + 2A2DBB2A1E66A0F6008C78AF /* NSString+Additions.m */, + 2A2DBB2B1E66A0F6008C78AF /* NSWindow+Additions.h */, + 2A2DBB2C1E66A0F6008C78AF /* NSWindow+Additions.m */, + 2A2DBB2F1E66A133008C78AF /* NSFileManager+Additions.h */, + 2A2DBB301E66A133008C78AF /* NSFileManager+Additions.m */, + 2A1CD1E21E68179A007A2700 /* NSWindowController+Additions.h */, + 2A1CD1E31E68179A007A2700 /* NSWindowController+Additions.m */, + 2AD4BAFA1E6E6183007A443C /* NSFileWrapper+Additions.h */, + 2AD4BAFB1E6E6183007A443C /* NSFileWrapper+Additions.m */, + 2A6809A31E7FCE1900750C23 /* NSAlert+Additions.h */, + 2A6809A41E7FCE1900750C23 /* NSAlert+Additions.m */, + ); + path = Additions; + sourceTree = ""; + }; + 2AD25BCA1E67F6E7007AE3B8 /* Document */ = { + isa = PBXGroup; + children = ( + 2AD25BCB1E67F6E7007AE3B8 /* ECSnippetsDocument.h */, + 2AD25BCC1E67F6E7007AE3B8 /* ECSnippetsDocument.m */, + ); + path = Document; + sourceTree = ""; + }; + 2AD4BB931E763131007A443C /* UI */ = { + isa = PBXGroup; + children = ( + 2AD4BB941E763131007A443C /* ECustomButton.h */, + 2AD4BB951E763131007A443C /* ECustomButton.m */, + 2AD4BB961E763131007A443C /* EEditorTableView.h */, + 2AD4BB971E763131007A443C /* EEditorTableView.m */, + 2AD4BB981E763131007A443C /* EVerticalScrollView.h */, + 2AD4BB991E763131007A443C /* EVerticalScrollView.m */, + 2A68099D1E7FAB1700750C23 /* EEditorTableMenu.h */, + 2A68099E1E7FAB1700750C23 /* EEditorTableMenu.m */, + 2A6809A01E7FC4DE00750C23 /* EEditorTableRowView.h */, + 2A6809A11E7FC4DE00750C23 /* EEditorTableRowView.m */, + ); + path = UI; + sourceTree = ""; + }; + 2AD4BB9D1E763238007A443C /* Utility */ = { + isa = PBXGroup; + children = ( + 2AD4BB9E1E763238007A443C /* ECSafeCast.h */, + 2AD4BB9F1E763238007A443C /* ECSafeCast.m */, + ); + path = Utility; + sourceTree = ""; + }; 670F2EC71DB2284400A1739F = { isa = PBXGroup; children = ( @@ -225,11 +309,19 @@ 670F2ED21DB2284400A1739F /* EasyCode */ = { isa = PBXGroup; children = ( + 676E320D1DB70B2000C9DC9B /* EasyCode.entitlements */, + 2A2DBB281E66A0F6008C78AF /* Additions */, + 2AD4BB931E763131007A443C /* UI */, + 2AD4BB9D1E763238007A443C /* Utility */, 6741CE5E1DB87FEC000408E7 /* MappingEditor */, 6741CE4C1DB8732D000408E7 /* SharedLogic */, - 676E320D1DB70B2000C9DC9B /* EasyCode.entitlements */, + 2AD25BCA1E67F6E7007AE3B8 /* Document */, + 2AD25BD01E6806AA007AE3B8 /* ECMainWindowController.h */, + 2AD25BD11E6806AA007AE3B8 /* ECMainWindowController.m */, + 2AD25BD21E6806AA007AE3B8 /* ECMainWindowController.xib */, 670F2ED31DB2284400A1739F /* AppDelegate.h */, 670F2ED41DB2284400A1739F /* AppDelegate.m */, + 2A1CD20A1E697AAA007A2700 /* easycode.pch */, 6741CE6D1DB89DFE000408E7 /* Resource */, 670F2ED91DB2284400A1739F /* Assets.xcassets */, 670F2EDB1DB2284400A1739F /* MainMenu.xib */, @@ -298,12 +390,15 @@ 6741CE4C1DB8732D000408E7 /* SharedLogic */ = { isa = PBXGroup; children = ( + 2AD4BB021E6E85B4007A443C /* ECDefine.h */, + 2AD4BAFE1E6E67E2007A443C /* ECSnippetHelper.h */, + 2AD4BAFF1E6E67E2007A443C /* ECSnippetHelper.m */, 6741CE4D1DB87340000408E7 /* ESharedUserDefault.h */, 6741CE4E1DB87340000408E7 /* ESharedUserDefault.m */, 6741CE501DB87BC2000408E7 /* ECMapping.h */, 6741CE511DB87BC2000408E7 /* ECMapping.m */, - 67AFF6901DB5B46000697135 /* Swift */, 67AFF68F1DB5B45A00697135 /* ObjectiveC */, + 67AFF6901DB5B46000697135 /* Swift */, ); path = SharedLogic; sourceTree = ""; @@ -311,18 +406,16 @@ 6741CE5E1DB87FEC000408E7 /* MappingEditor */ = { isa = PBXGroup; children = ( - 6741CE7A1DB8B987000408E7 /* DetailEditorController */, + 2AD4BAE11E6E5272007A443C /* ECSnippet.h */, + 2AD4BAE21E6E5272007A443C /* ECSnippet.m */, + 6741CE6A1DB89894000408E7 /* ECSnippetEntry.h */, + 6741CE6B1DB89894000408E7 /* ECSnippetEntry.m */, + 2AD4BB8E1E76310E007A443C /* DetailWindowController.h */, + 2AD4BB8F1E76310E007A443C /* DetailWindowController.m */, + 2AD4BB901E76310E007A443C /* DetailWindowController.xib */, 6741CE651DB884DD000408E7 /* EditorWindowController.h */, 6741CE661DB884DD000408E7 /* EditorWindowController.m */, 6741CE671DB884DD000408E7 /* EditorWindowController.xib */, - 6741CE6A1DB89894000408E7 /* EShortcutEntry.h */, - 6741CE6B1DB89894000408E7 /* EShortcutEntry.m */, - 6741CE741DB8A713000408E7 /* EVerticalScrollView.h */, - 6741CE751DB8A713000408E7 /* EVerticalScrollView.m */, - 6741CE771DB8B4DF000408E7 /* EEditorTableView.h */, - 6741CE781DB8B4DF000408E7 /* EEditorTableView.m */, - 67F73FAF1DCC9625000780C3 /* CustomButton.h */, - 67F73FB01DCC9625000780C3 /* CustomButton.m */, ); path = MappingEditor; sourceTree = ""; @@ -330,31 +423,11 @@ 6741CE6D1DB89DFE000408E7 /* Resource */ = { isa = PBXGroup; children = ( - 67F73FAB1DCC9278000780C3 /* btnguide.png */, - 67F73FAC1DCC9278000780C3 /* btnguide@2x.png */, - 67F73FA71DCC8E31000780C3 /* btnbg2.png */, - 67F73FA81DCC8E31000780C3 /* btnbg2@2x.png */, - 67F73FA31DCC8BF7000780C3 /* btnbg.png */, - 67F73FA41DCC8BF7000780C3 /* btnbg@2x.png */, - 67F73FA11DCC8ADF000780C3 /* mainbg@2x.png */, - 67F73F9D1DCC8A70000780C3 /* mainbg.png */, - 6741CE6E1DB8A04A000408E7 /* edit.png */, - 6741CE6F1DB8A04A000408E7 /* remove.png */, - 6741CE701DB8A04A000408E7 /* add.png */, + 2A2DBB161E6566E4008C78AF /* Localizable.strings */, ); path = Resource; sourceTree = ""; }; - 6741CE7A1DB8B987000408E7 /* DetailEditorController */ = { - isa = PBXGroup; - children = ( - 6741CE7B1DB8BA19000408E7 /* DetailWindowController.h */, - 6741CE7C1DB8BA19000408E7 /* DetailWindowController.m */, - 6741CE7D1DB8BA19000408E7 /* DetailWindowController.xib */, - ); - path = DetailEditorController; - sourceTree = ""; - }; 67AFF68F1DB5B45A00697135 /* ObjectiveC */ = { isa = PBXGroup; children = ( @@ -460,6 +533,7 @@ 670F2ECD1DB2284400A1739F /* Frameworks */, 670F2ECE1DB2284400A1739F /* Resources */, 670F2EFC1DB228DD00A1739F /* Embed App Extensions */, + 2AD4BB451E716B5B007A443C /* ShellScript */, ); buildRules = ( ); @@ -494,25 +568,31 @@ 670F2EC81DB2284400A1739F /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0800; + LastUpgradeCheck = 0820; ORGANIZATIONNAME = music4kid; TargetAttributes = { 670F2ECF1DB2284400A1739F = { CreatedOnToolsVersion = 8.0; - DevelopmentTeam = 2WQE6AU5PD; + DevelopmentTeam = JW95CV255J; ProvisioningStyle = Automatic; SystemCapabilities = { com.apple.ApplicationGroups.Mac = { enabled = 1; }; + com.apple.Push = { + enabled = 1; + }; com.apple.Sandbox = { enabled = 1; }; + com.apple.iCloud = { + enabled = 1; + }; }; }; 670F2EE71DB228DC00A1739F = { CreatedOnToolsVersion = 8.0; - DevelopmentTeam = 2WQE6AU5PD; + DevelopmentTeam = JW95CV255J; ProvisioningStyle = Automatic; SystemCapabilities = { com.apple.ApplicationGroups.Mac = { @@ -546,21 +626,12 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 670F2EDA1DB2284400A1739F /* Assets.xcassets in Resources */, - 6741CE711DB8A04A000408E7 /* edit.png in Resources */, - 6741CE7F1DB8BA19000408E7 /* DetailWindowController.xib in Resources */, - 67F73F9F1DCC8A70000780C3 /* mainbg.png in Resources */, - 67F73FA91DCC8E31000780C3 /* btnbg2.png in Resources */, 670F2EDD1DB2284400A1739F /* MainMenu.xib in Resources */, - 67F73FAE1DCC9278000780C3 /* btnguide@2x.png in Resources */, - 67F73FA21DCC8ADF000780C3 /* mainbg@2x.png in Resources */, - 67F73FAD1DCC9278000780C3 /* btnguide.png in Resources */, - 6741CE731DB8A04A000408E7 /* add.png in Resources */, - 67F73FA51DCC8BF7000780C3 /* btnbg.png in Resources */, - 67F73FAA1DCC8E31000780C3 /* btnbg2@2x.png in Resources */, + 2AD25BD41E6806AA007AE3B8 /* ECMainWindowController.xib in Resources */, 6741CE691DB884DD000408E7 /* EditorWindowController.xib in Resources */, - 6741CE721DB8A04A000408E7 /* remove.png in Resources */, - 67F73FA61DCC8BF7000780C3 /* btnbg@2x.png in Resources */, + 2A2DBB171E6566E4008C78AF /* Localizable.strings in Resources */, + 2AD4BB921E76310E007A443C /* DetailWindowController.xib in Resources */, + 2AD25BC71E67F2FE007AE3B8 /* Assets.xcassets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -580,27 +651,56 @@ }; /* End PBXResourcesBuildPhase section */ +/* Begin PBXShellScriptBuildPhase section */ + 2AD4BB451E716B5B007A443C /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "TAGS=\"TODO:|FIXME:\"\necho \"searching ${SRCROOT} for ${TAGS}\"\nfind \"${SRCROOT}\" \\( -name \"*.m\" \\) -print0 | xargs -0 egrep --with-filename --line-number --only-matching \"($TAGS).*\\$\" | perl -p -e \"s/($TAGS)/ warning: \\$1/\""; + }; +/* End PBXShellScriptBuildPhase section */ + /* Begin PBXSourcesBuildPhase section */ 670F2ECC1DB2284400A1739F /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 2A2DBB2E1E66A0F6008C78AF /* NSWindow+Additions.m in Sources */, + 2AD4BB001E6E67E2007A443C /* ECSnippetHelper.m in Sources */, + 2A6809A21E7FC4DE00750C23 /* EEditorTableRowView.m in Sources */, + 2AD4BB911E76310E007A443C /* DetailWindowController.m in Sources */, + 2AD4BB9C1E763131007A443C /* EVerticalScrollView.m in Sources */, 6741CE561DB87CE8000408E7 /* ECMapping.h in Sources */, 6741CE571DB87CE8000408E7 /* ECMapping.m in Sources */, - 6741CE7E1DB8BA19000408E7 /* DetailWindowController.m in Sources */, - 6741CE681DB884DD000408E7 /* EditorWindowController.m in Sources */, - 6741CE761DB8A713000408E7 /* EVerticalScrollView.m in Sources */, + 2A6809A51E7FCE1900750C23 /* NSAlert+Additions.m in Sources */, + 2AD25BCD1E67F6E7007AE3B8 /* ECSnippetsDocument.m in Sources */, + 2A2DBB311E66A133008C78AF /* NSFileManager+Additions.m in Sources */, + 0BEB36A81E671F760039FF67 /* EditorWindowController.m in Sources */, 6741CE581DB87CE8000408E7 /* ECMappingForSwift.h in Sources */, + 2AD4BAE31E6E5272007A443C /* ECSnippet.m in Sources */, 6741CE591DB87CE8000408E7 /* ECMappingForSwift.m in Sources */, 6741CE5A1DB87CE8000408E7 /* SwiftMapping.h in Sources */, - 6741CE6C1DB89894000408E7 /* EShortcutEntry.m in Sources */, + 6741CE6C1DB89894000408E7 /* ECSnippetEntry.m in Sources */, 6741CE5B1DB87CE8000408E7 /* ECMappingForObjectiveC.h in Sources */, - 6741CE791DB8B4DF000408E7 /* EEditorTableView.m in Sources */, - 6741CE5C1DB87CE8000408E7 /* ECMappingForObjectiveC.m in Sources */, + 2AD4BB9B1E763131007A443C /* EEditorTableView.m in Sources */, + 2AD4BAFC1E6E6183007A443C /* NSFileWrapper+Additions.m in Sources */, + 2A68099F1E7FAB1700750C23 /* EEditorTableMenu.m in Sources */, + 2A1CD1E41E68179A007A2700 /* NSWindowController+Additions.m in Sources */, + 2AD4BADD1E6E5195007A443C /* ECMappingForObjectiveC.m in Sources */, + 2AD4BBA01E763238007A443C /* ECSafeCast.m in Sources */, + 2AD25BD31E6806AA007AE3B8 /* ECMainWindowController.m in Sources */, + 2A2DBB2D1E66A0F6008C78AF /* NSString+Additions.m in Sources */, 6741CE5D1DB87CE8000408E7 /* OCMapping.h in Sources */, - 67F73FB11DCC9625000780C3 /* CustomButton.m in Sources */, 670F2ED81DB2284400A1739F /* main.m in Sources */, 6741CE4F1DB87340000408E7 /* ESharedUserDefault.m in Sources */, + 2AD4BB9A1E763131007A443C /* ECustomButton.m in Sources */, 670F2ED51DB2284400A1739F /* AppDelegate.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -610,6 +710,9 @@ buildActionMask = 2147483647; files = ( 6729B1BA1DB8CFA300885A9A /* ESharedUserDefault.h in Sources */, + 2AD4BBA11E7632DD007A443C /* ECSafeCast.m in Sources */, + 2AD4BB0A1E6EAD6F007A443C /* NSFileManager+Additions.m in Sources */, + 2AD4BB011E6E67E2007A443C /* ECSnippetHelper.m in Sources */, 6729B1BB1DB8CFA300885A9A /* ESharedUserDefault.m in Sources */, 67AFF6A01DB5C8A100697135 /* ECGenerateHelper.m in Sources */, 67AFF6931DB5B71200697135 /* ECMappingHelper.m in Sources */, @@ -617,10 +720,13 @@ 67AFF6F01DB5CC2E00697135 /* NSString+PDRegex.m in Sources */, 67AFF6E51DB5CBE000697135 /* FSExtensionProcessor.m in Sources */, 67AFF68E1DB5B45400697135 /* ECMappingForSwift.m in Sources */, + 2AD4BADF1E6E5205007A443C /* ECSnippetEntry.m in Sources */, + 2AD4BAE41E6E5272007A443C /* ECSnippet.m in Sources */, 670F2EF11DB228DD00A1739F /* SourceEditorExtension.m in Sources */, 67AFF6E31DB5CBE000697135 /* FSCategoryProcessor.m in Sources */, 67AFF6F31DB5CC5B00697135 /* FSElementProperty.m in Sources */, 67302B0D1DB23ACA0030C360 /* EasyCodeManager.m in Sources */, + 2AD4BAFD1E6E6183007A443C /* NSFileWrapper+Additions.m in Sources */, 6741CE521DB87BC2000408E7 /* ECMapping.m in Sources */, 670F2EF41DB228DD00A1739F /* SourceEditorCommand.m in Sources */, 67AFF6E41DB5CBE000697135 /* FSElementProcessor.m in Sources */, @@ -628,6 +734,7 @@ 67AFF6E71DB5CBE000697135 /* FSInterfaceProcessor.m in Sources */, 67AFF6E81DB5CBE000697135 /* FSProtocolProcessor.m in Sources */, 67AFF6E21DB5CBE000697135 /* FSElementCache.m in Sources */, + 2AD4BAE01E6E5210007A443C /* NSString+Additions.m in Sources */, 67AFF6EB1DB5CBF500697135 /* ECFileParser.m in Sources */, 67AFF6E61DB5CBE000697135 /* FSImpProcessor.m in Sources */, ); @@ -673,6 +780,7 @@ CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; @@ -720,6 +828,7 @@ CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; @@ -749,11 +858,14 @@ CODE_SIGN_ENTITLEMENTS = EasyCode/EasyCode.entitlements; CODE_SIGN_IDENTITY = "Mac Developer"; COMBINE_HIDPI_IMAGES = YES; - DEVELOPMENT_TEAM = 2WQE6AU5PD; + DEVELOPMENT_TEAM = JW95CV255J; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = EasyCode/easycode.pch; + HEADER_SEARCH_PATHS = "\"$(SRCROOT)/EasyCode/SharedLogic\""; INFOPLIST_FILE = EasyCode/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.11; - PRODUCT_BUNDLE_IDENTIFIER = com.music4kid.ec; + PRODUCT_BUNDLE_IDENTIFIER = com.sito.easycode; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; @@ -765,11 +877,14 @@ CODE_SIGN_ENTITLEMENTS = EasyCode/EasyCode.entitlements; CODE_SIGN_IDENTITY = "Mac Developer"; COMBINE_HIDPI_IMAGES = YES; - DEVELOPMENT_TEAM = 2WQE6AU5PD; + DEVELOPMENT_TEAM = JW95CV255J; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = EasyCode/easycode.pch; + HEADER_SEARCH_PATHS = "\"$(SRCROOT)/EasyCode/SharedLogic\""; INFOPLIST_FILE = EasyCode/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.11; - PRODUCT_BUNDLE_IDENTIFIER = com.music4kid.ec; + PRODUCT_BUNDLE_IDENTIFIER = com.sito.easycode; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; @@ -780,11 +895,12 @@ CODE_SIGN_ENTITLEMENTS = EC/EC.entitlements; CODE_SIGN_IDENTITY = "Mac Developer"; COMBINE_HIDPI_IMAGES = YES; - DEVELOPMENT_TEAM = 2WQE6AU5PD; + DEVELOPMENT_TEAM = JW95CV255J; + HEADER_SEARCH_PATHS = "\"$(SRCROOT)/EasyCode/SharedLogic\""; INFOPLIST_FILE = EC/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.11; - PRODUCT_BUNDLE_IDENTIFIER = com.music4kid.ec.ec; + PRODUCT_BUNDLE_IDENTIFIER = com.sito.easycode; PRODUCT_NAME = EC; SKIP_INSTALL = YES; }; @@ -796,11 +912,12 @@ CODE_SIGN_ENTITLEMENTS = EC/EC.entitlements; CODE_SIGN_IDENTITY = "Mac Developer"; COMBINE_HIDPI_IMAGES = YES; - DEVELOPMENT_TEAM = 2WQE6AU5PD; + DEVELOPMENT_TEAM = JW95CV255J; + HEADER_SEARCH_PATHS = "\"$(SRCROOT)/EasyCode/SharedLogic\""; INFOPLIST_FILE = EC/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.11; - PRODUCT_BUNDLE_IDENTIFIER = com.music4kid.ec.ec; + PRODUCT_BUNDLE_IDENTIFIER = com.sito.easycode; PRODUCT_NAME = EC; SKIP_INSTALL = YES; }; diff --git a/EasyCode.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/EasyCode.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/EasyCode.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/EasyCode/Additions/NSAlert+Additions.h b/EasyCode/Additions/NSAlert+Additions.h new file mode 100644 index 0000000..dd0c06d --- /dev/null +++ b/EasyCode/Additions/NSAlert+Additions.h @@ -0,0 +1,16 @@ +// +// NSAlert+Additions.h +// EasyCode +// +// Created by lijia on 20/03/2017. +// Copyright © 2017 music4kid. All rights reserved. +// + +#import + +@interface NSAlert (Additions) ++(instancetype)ec_alertWithStyle:(NSAlertStyle)alertStyle + messageText:(NSString *)message + informativeText:(NSString *)informative + buttonTitle:(NSString *)firstTitle,...; +@end diff --git a/EasyCode/Additions/NSAlert+Additions.m b/EasyCode/Additions/NSAlert+Additions.m new file mode 100644 index 0000000..135cbee --- /dev/null +++ b/EasyCode/Additions/NSAlert+Additions.m @@ -0,0 +1,29 @@ +// +// NSAlert+Additions.m +// EasyCode +// +// Created by lijia on 20/03/2017. +// Copyright © 2017 music4kid. All rights reserved. +// + +#import "NSAlert+Additions.h" + +@implementation NSAlert (Additions) ++(instancetype)ec_alertWithStyle:(NSAlertStyle)alertStyle + messageText:(NSString *)message + informativeText:(NSString *)informative + buttonTitle:(NSString *)firstTitle,... { + NSAlert *alert = [[NSAlert alloc] init]; + alert.messageText = message; + alert.informativeText = informative; + alert.alertStyle = alertStyle; + va_list args; + va_start(args, firstTitle); + for (NSString *arg = firstTitle; arg != nil; arg = va_arg(args, NSString*)) + { + [alert addButtonWithTitle:arg]; + } + va_end(args); + return alert; +} +@end diff --git a/EasyCode/Additions/NSFileManager+Additions.h b/EasyCode/Additions/NSFileManager+Additions.h new file mode 100644 index 0000000..1419f12 --- /dev/null +++ b/EasyCode/Additions/NSFileManager+Additions.h @@ -0,0 +1,32 @@ +// +// NSFileManager+Additions.h +// EasyCode +// +// Created by lijia on 01/03/2017. +// Copyright © 2017 music4kid. All rights reserved. +// + +#import +#import "ECDefine.h" + +extern NSString *const DirectoryLocationDomain; +extern NSString *const DirectoryUbiquityDocuments; +extern NSString *const DirectoryOCName; +extern NSString *const DirectorySwiftName; +extern NSString *const SnippetFileName; +extern NSString *const VersionFileName; + +@interface NSFileManager (Additions) +-(NSURL*)ec_localURL; +-(NSURL*)ec_localSnippetsURLWithFilename:(NSString*)filename; +-(NSURL*)ec_ubiquityURL; +-(NSURL*)ec_ubiquitySnippetsURLWithFilename:(NSString*)filename; + +-(NSURL*)ec_detectURLForSourceType:(ECSourceType)sourceType; + +-(NSString *)ec_findOrCreateDirectory:(NSSearchPathDirectory)searchPathDirectory + inDomain:(NSSearchPathDomainMask)domainMask + appendPathComponent:(NSString *)appendComponent + error:(NSError **)errorOut; +-(NSString*)ec_supportDocumentDirectory; +@end diff --git a/EasyCode/Additions/NSFileManager+Additions.m b/EasyCode/Additions/NSFileManager+Additions.m new file mode 100644 index 0000000..27bb3ac --- /dev/null +++ b/EasyCode/Additions/NSFileManager+Additions.m @@ -0,0 +1,140 @@ +// +// NSFileManager+Additions.m +// EasyCode +// +// Created by lijia on 01/03/2017. +// Copyright © 2017 music4kid. All rights reserved. +// + +#import "NSFileManager+Additions.h" +#import "ESharedUserDefault.h" + +enum { + DirectoryLocationErrorNoPathFound, + DirectoryLocationErrorFileExistsAtLocation +}; +NSString *const DirectoryLocationDomain = @"DirectoryLocationDomain"; +NSString *const DirectoryDocuments = @"Documents"; +NSString *const DirectoryOCName = @"objective-c"; +NSString *const DirectorySwiftName = @"swift"; +NSString *const SnippetFileName = @"snippets.dat"; +NSString *const VersionFileName = @"version.dat"; + +@implementation NSFileManager (Additions) +-(NSURL*)ec_localURL +{ + NSString* supportPath = [self ec_supportDocumentDirectory]; + NSURL* url = [NSURL fileURLWithPath:supportPath]; + return url; +} + +-(NSURL*)ec_localSnippetsURLWithFilename:(NSString*)filename +{ + NSURL* ec_localURL = [self ec_localURL]; + NSURL* url = [ec_localURL URLByAppendingPathComponent:filename]; + + NSError *error = nil; + BOOL success = [self createDirectoryAtURL:url withIntermediateDirectories:YES attributes:nil error:&error]; + if (!success) { + NSLog(@"create local directory error :%@",[error localizedDescription]); + } + + return url; +} + +-(NSURL*)ec_ubiquityURL +{ + NSURL* ubiURL = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil]; + ubiURL = [ubiURL URLByAppendingPathComponent:DirectoryDocuments]; + return ubiURL; +} + +-(NSURL*)ec_ubiquitySnippetsURLWithFilename:(NSString*)filename +{ + NSURL* ubiURL = [self ec_ubiquityURL]; + NSURL* url = [ubiURL URLByAppendingPathComponent:filename]; + + NSError *error = nil; + BOOL success = [self createDirectoryAtURL:url withIntermediateDirectories:YES attributes:nil error:&error]; + if (!success) { + NSLog(@"create ubiquity directory error :%@",[error localizedDescription]); + } + + return url; +} + +-(NSURL*)ec_detectURLForSourceType:(ECSourceType)sourceType +{ + NSString* dirname = DirectoryOCName; + if (sourceType == ECSourceTypeSwift) { + dirname = DirectorySwiftName; + } + + NSURL* fileURL = [[NSFileManager defaultManager] ec_localSnippetsURLWithFilename:dirname];; + BOOL useiCloud = [ESharedUserDefault boolForKey:kUseiCloudSync]; + if (useiCloud) { + id ubiq = [[NSFileManager defaultManager] ubiquityIdentityToken]; + if (ubiq) { + fileURL = [[NSFileManager defaultManager] ec_ubiquitySnippetsURLWithFilename:dirname]; + } + } + + return fileURL; +} + +- (NSString *)ec_findOrCreateDirectory:(NSSearchPathDirectory)searchPathDirectory + inDomain:(NSSearchPathDomainMask)domainMask + appendPathComponent:(NSString *)appendComponent + error:(NSError **)errorOut { + + NSArray *paths = NSSearchPathForDirectoriesInDomains(searchPathDirectory, domainMask, YES); + if ([paths count] == 0) { + if (errorOut) { + NSDictionary *userInfo = @{NSLocalizedDescriptionKey : @"No path found for directory in domain.", + @"NSSearchPathDirectory" : @(searchPathDirectory), + @"NSSearchPathDomainMask" : @(domainMask) }; + + *errorOut = [NSError errorWithDomain:DirectoryLocationDomain + code:DirectoryLocationErrorNoPathFound + userInfo:userInfo]; + } + return nil; + } + + NSString *resolvedPath = [paths objectAtIndex:0]; + if (appendComponent) { + resolvedPath = [resolvedPath stringByAppendingPathComponent:appendComponent]; + } + + NSError *error = nil; + BOOL success = [self createDirectoryAtPath:resolvedPath + withIntermediateDirectories:YES + attributes:nil + error:&error]; + if (!success) { + if (errorOut) { + *errorOut = error; + } + return nil; + } + + if (errorOut) { + *errorOut = nil; + } + return resolvedPath; +} + +-(NSString*)ec_supportDocumentDirectory { + NSString* appName = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleExecutable"]; + NSString *documentPath = [appName stringByAppendingPathComponent:DirectoryDocuments]; + NSError *error = nil; + NSString *result = [self ec_findOrCreateDirectory:NSApplicationSupportDirectory + inDomain:NSUserDomainMask + appendPathComponent:documentPath + error:&error]; + if (!result) { + NSLog(@"Unable to find or create application support directory:\n%@", error); + } + return result; +} +@end diff --git a/EasyCode/Additions/NSFileWrapper+Additions.h b/EasyCode/Additions/NSFileWrapper+Additions.h new file mode 100644 index 0000000..5947f58 --- /dev/null +++ b/EasyCode/Additions/NSFileWrapper+Additions.h @@ -0,0 +1,13 @@ +// +// NSFileWrapper+Additions.h +// EasyCode +// +// Created by lijia on 07/03/2017. +// Copyright © 2017 music4kid. All rights reserved. +// + +#import + +@interface NSFileWrapper (Additions) +-(void)ec_replaceFileWrapper:(NSFileWrapper*)child forKey:(NSString*)filename; +@end diff --git a/EasyCode/Additions/NSFileWrapper+Additions.m b/EasyCode/Additions/NSFileWrapper+Additions.m new file mode 100644 index 0000000..3bb5a7d --- /dev/null +++ b/EasyCode/Additions/NSFileWrapper+Additions.m @@ -0,0 +1,23 @@ +// +// NSFileWrapper+Additions.m +// EasyCode +// +// Created by lijia on 07/03/2017. +// Copyright © 2017 music4kid. All rights reserved. +// + +#import "NSFileWrapper+Additions.h" +#import "NSString+Additions.h" + +@implementation NSFileWrapper (Additions) +-(void)ec_replaceFileWrapper:(NSFileWrapper*)child forKey:(NSString*)filename { + if ([filename ec_isNotEmpty] == NO) { + return; + } + NSFileWrapper* oldChild = [[self fileWrappers] objectForKey:filename]; + if (oldChild) { + [self removeFileWrapper:oldChild]; + } + [self addFileWrapper:child]; +} +@end diff --git a/EasyCode/Additions/NSString+Additions.h b/EasyCode/Additions/NSString+Additions.h new file mode 100644 index 0000000..2764a0d --- /dev/null +++ b/EasyCode/Additions/NSString+Additions.h @@ -0,0 +1,14 @@ +// +// NSString+Additions.h +// EasyCode +// +// Created by lijia on 09/02/2017. +// Copyright © 2017 music4kid. All rights reserved. +// + +#import + +@interface NSString (Additions) +-(NSString*)ec_trimWhiteSpace; +-(BOOL)ec_isNotEmpty; +@end diff --git a/EasyCode/Additions/NSString+Additions.m b/EasyCode/Additions/NSString+Additions.m new file mode 100644 index 0000000..69a75c8 --- /dev/null +++ b/EasyCode/Additions/NSString+Additions.m @@ -0,0 +1,20 @@ +// +// NSString+Additions.m +// EasyCode +// +// Created by lijia on 09/02/2017. +// Copyright © 2017 music4kid. All rights reserved. +// + +#import "NSString+Additions.h" + +@implementation NSString (Additions) +-(NSString*)ec_trimWhiteSpace { + return [self stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; +} + +-(BOOL)ec_isNotEmpty { + NSString* trimStr = [self ec_trimWhiteSpace]; + return (trimStr != nil && trimStr.length > 0); +} +@end diff --git a/EasyCode/Additions/NSWindow+Additions.h b/EasyCode/Additions/NSWindow+Additions.h new file mode 100644 index 0000000..f76d526 --- /dev/null +++ b/EasyCode/Additions/NSWindow+Additions.h @@ -0,0 +1,15 @@ +// +// NSWindow+Additions.h +// EasyCode +// +// Created by lijia on 08/02/2017. +// Copyright © 2017 music4kid. All rights reserved. +// + +#import + +@interface NSWindow (Additions) +- (void)ec_setCornRadius:(CGFloat)raduis; +- (void)ec_fadeInAnimated:(BOOL)animated; +- (void)ec_fadeOutAnimated:(BOOL)animated afterDelay:(NSTimeInterval)delay; +@end diff --git a/EasyCode/Additions/NSWindow+Additions.m b/EasyCode/Additions/NSWindow+Additions.m new file mode 100644 index 0000000..534e88b --- /dev/null +++ b/EasyCode/Additions/NSWindow+Additions.m @@ -0,0 +1,55 @@ +// +// NSWindow+Additions.m +// EasyCode +// +// Created by lijia on 08/02/2017. +// Copyright © 2017 music4kid. All rights reserved. +// + +#import "NSWindow+Additions.h" + +@implementation NSWindow (Additions) +- (void)ec_setCornRadius:(CGFloat)raduis { + self.contentView.wantsLayer = YES; + self.contentView.layer.cornerRadius = raduis; + self.contentView.layer.masksToBounds = YES; +} + +- (void)ec_fadeInAnimated:(BOOL)animated { + [self makeKeyAndOrderFront:nil]; + [self.contentView setNeedsDisplay:YES]; + self.contentView.hidden = NO; + if (animated) { + [[NSAnimationContext currentContext] setDuration:0.3]; + [NSAnimationContext runAnimationGroup:^(NSAnimationContext * _Nonnull context) { + [[self.contentView animator] setAlphaValue:1.0]; + } completionHandler:nil]; + } else { + self.contentView.alphaValue = 1.0; + } +} + +- (void)hideDone { + self.contentView.alphaValue = 0.f; + self.contentView.hidden = YES; + [self orderOut:nil]; +} + +- (void)hideDelayed:(NSNumber*)animated { + if ([animated boolValue]) { + [[NSAnimationContext currentContext] setDuration:0.3]; + [NSAnimationContext runAnimationGroup:^(NSAnimationContext * _Nonnull context) { + [[self.contentView animator] setAlphaValue:0.02]; + } completionHandler:^{ + [self hideDone]; + }]; + } else { + [self hideDone]; + } +} + +- (void)ec_fadeOutAnimated:(BOOL)animated afterDelay:(NSTimeInterval)delay { + [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(hideDelayed:) object:@(animated)]; + [self performSelector:@selector(hideDelayed:) withObject:@(animated) afterDelay:delay]; +} +@end diff --git a/EasyCode/Additions/NSWindowController+Additions.h b/EasyCode/Additions/NSWindowController+Additions.h new file mode 100644 index 0000000..905d1e6 --- /dev/null +++ b/EasyCode/Additions/NSWindowController+Additions.h @@ -0,0 +1,13 @@ +// +// NSWindowController+Additions.h +// EasyCode +// +// Created by lijia on 02/03/2017. +// Copyright © 2017 music4kid. All rights reserved. +// + +#import + +@interface NSWindowController (Additions) +-(void)ec_makeWindowFront; +@end diff --git a/EasyCode/Additions/NSWindowController+Additions.m b/EasyCode/Additions/NSWindowController+Additions.m new file mode 100644 index 0000000..fb404bd --- /dev/null +++ b/EasyCode/Additions/NSWindowController+Additions.m @@ -0,0 +1,15 @@ +// +// NSWindowController+Additions.m +// EasyCode +// +// Created by lijia on 02/03/2017. +// Copyright © 2017 music4kid. All rights reserved. +// + +#import "NSWindowController+Additions.h" + +@implementation NSWindowController (Additions) +-(void)ec_makeWindowFront { + [self.window makeKeyAndOrderFront:nil]; +} +@end diff --git a/EasyCode/AppDelegate.h b/EasyCode/AppDelegate.h index 2bae03b..e94d446 100644 --- a/EasyCode/AppDelegate.h +++ b/EasyCode/AppDelegate.h @@ -7,12 +7,12 @@ // #import - +@class ECMainWindowController; @interface AppDelegate : NSObject - -- (IBAction)showEditorWindowForOC:(id)sender; -- (IBAction)showEditorWindowForSwift:(id)sender; -- (IBAction)showHowToUse:(id)sender; - +//icloud +@property (nonatomic, strong) id ubiquityToken; +@property (nonatomic, strong) NSURL *ubiquityURL; +@property (nonatomic, strong) ECMainWindowController* mainController; ++(instancetype)sharedInstance; @end diff --git a/EasyCode/AppDelegate.m b/EasyCode/AppDelegate.m index 6b4bf5c..031dcff 100644 --- a/EasyCode/AppDelegate.m +++ b/EasyCode/AppDelegate.m @@ -7,59 +7,93 @@ // #import "AppDelegate.h" -#import "EditorWindowController.h" +#import "ECMainWindowController.h" +#import "NSWindowController+Additions.h" @interface AppDelegate () - -@property (weak) IBOutlet NSWindow *window; -@property (nonatomic, strong) EditorWindowController* editorOC; -@property (nonatomic, strong) EditorWindowController* editorSwift; - +@property (nonatomic, strong) NSStatusItem *statusItem; @end @implementation AppDelegate -- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { - // Insert code here to initialize your application ++(instancetype)sharedInstance { + AppDelegate* appDelegate = [NSApplication sharedApplication].delegate; + return appDelegate; } - -- (void)applicationWillTerminate:(NSNotification *)aNotification { - // Insert code here to tear down your application +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; } -- (IBAction)showEditorWindowForOC:(id)sender +- (void)ubiquityIdentityChanged:(NSNotification *)notification { - if (self.editorOC == nil) { - self.editorOC = [[EditorWindowController alloc] initWithWindowNibName:@"EditorWindowController"]; - [_editorOC initEditorWindow:EditorTypeOC]; + id token = [[NSFileManager defaultManager] ubiquityIdentityToken]; + if (token == nil) { + NSAlert *warningAlert = [NSAlert ec_alertWithStyle:NSWarningAlertStyle + messageText:NSLocalizedString(@"Logged_Out_Message", nil) + informativeText:NSLocalizedString(@"Logged_Out_Message_Explain", nil) + buttonTitle:NSLocalizedString(@"Button_OK_Title", nil), + nil]; + [warningAlert runModal]; + } else { + if ([self.ubiquityToken isEqual:token]) { + NSLog(@"user has stayed logged in with same account"); + } else { + NSLog(@"user logged in with a new account"); + } + self.ubiquityToken = token; } - [_editorOC showWindow:self]; } -- (void)showEditorWindowForSwift:(id)sender +- (IBAction)clickStatusBarItem:(id)sender { + NSString* quoteText = @"Never put off until tomorrow what you can do the day after tomorrow."; + NSString* quoteAuthor = @"Mark Twain"; + NSLog(@"%@ - %@",quoteText,quoteAuthor); +} + +- (void)setupStatusItem { + _statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength]; + _statusItem.image = [NSImage imageNamed:@"StatusBarImage"]; + _statusItem.action = @selector(clickStatusBarItem:); +} + +- (void)setupUbiquityURL { + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + _ubiquityURL = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil]; + }); + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(ubiquityIdentityChanged:) + name:NSUbiquityIdentityDidChangeNotification + object:nil]; +} + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { - if (self.editorSwift == nil) { - self.editorSwift = [[EditorWindowController alloc] initWithWindowNibName:@"EditorWindowController"]; - [_editorSwift initEditorWindow:EditorTypeSwift]; - } - [_editorSwift showWindow:self]; + [self setupUbiquityURL]; + [self setupStatusItem]; + _mainController = [[ECMainWindowController alloc] initWithWindowNibName:@"ECMainWindowController"]; + [_mainController ec_makeWindowFront]; +} + +- (void)applicationDidBecomeActive:(NSNotification *)notification +{ + _ubiquityToken = [[NSFileManager defaultManager] ubiquityIdentityToken]; + +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification +{ + // Insert code here to tear down your application } -- (IBAction)showHowToUse:(id)sender { - [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString: @"https://github.com/music4kid/EasyCode-Xcode"]]; +- (BOOL)applicationShouldOpenUntitledFile:(NSApplication *)sender { + return NO; } - (BOOL)applicationShouldHandleReopen:(NSApplication *)theApplication hasVisibleWindows:(BOOL)flag { - if (flag) { - return NO; - } - else - { - [self.window makeKeyAndOrderFront:self]; - return YES; - } + return YES; } @end diff --git a/EasyCode/Assets.xcassets/AppIcon.appiconset/Artboard-128.png b/EasyCode/Assets.xcassets/AppIcon.appiconset/Artboard-128.png deleted file mode 100644 index 2dce2d7..0000000 Binary files a/EasyCode/Assets.xcassets/AppIcon.appiconset/Artboard-128.png and /dev/null differ diff --git a/EasyCode/Assets.xcassets/AppIcon.appiconset/Artboard-257.png b/EasyCode/Assets.xcassets/AppIcon.appiconset/Artboard-257.png new file mode 100644 index 0000000..7a40673 Binary files /dev/null and b/EasyCode/Assets.xcassets/AppIcon.appiconset/Artboard-257.png differ diff --git a/EasyCode/Assets.xcassets/AppIcon.appiconset/Contents.json b/EasyCode/Assets.xcassets/AppIcon.appiconset/Contents.json index 1713f77..c3d7de7 100644 --- a/EasyCode/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/EasyCode/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -39,7 +39,7 @@ { "size" : "256x256", "idiom" : "mac", - "filename" : "Artboard-128.png", + "filename" : "Artboard-257.png", "scale" : "1x" }, { diff --git a/EasyCode/Assets.xcassets/Contents.json b/EasyCode/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/EasyCode/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/EasyCode/Assets.xcassets/EasyCode/Contents.json b/EasyCode/Assets.xcassets/EasyCode/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/EasyCode/Assets.xcassets/EasyCode/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/EasyCode/Assets.xcassets/EasyCode/StatusBarImage.imageset/Contents.json b/EasyCode/Assets.xcassets/EasyCode/StatusBarImage.imageset/Contents.json new file mode 100644 index 0000000..4cbb0d5 --- /dev/null +++ b/EasyCode/Assets.xcassets/EasyCode/StatusBarImage.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "StatusBarImage@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/EasyCode/Assets.xcassets/EasyCode/StatusBarImage.imageset/StatusBarImage@2x.png b/EasyCode/Assets.xcassets/EasyCode/StatusBarImage.imageset/StatusBarImage@2x.png new file mode 100644 index 0000000..c385d2c Binary files /dev/null and b/EasyCode/Assets.xcassets/EasyCode/StatusBarImage.imageset/StatusBarImage@2x.png differ diff --git a/EasyCode/Assets.xcassets/EasyCode/add.imageset/Contents.json b/EasyCode/Assets.xcassets/EasyCode/add.imageset/Contents.json new file mode 100644 index 0000000..a625689 --- /dev/null +++ b/EasyCode/Assets.xcassets/EasyCode/add.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "add.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/EasyCode/Resource/add.png b/EasyCode/Assets.xcassets/EasyCode/add.imageset/add.png similarity index 100% rename from EasyCode/Resource/add.png rename to EasyCode/Assets.xcassets/EasyCode/add.imageset/add.png diff --git a/EasyCode/Assets.xcassets/EasyCode/btnbg.imageset/Contents.json b/EasyCode/Assets.xcassets/EasyCode/btnbg.imageset/Contents.json new file mode 100644 index 0000000..9c155c9 --- /dev/null +++ b/EasyCode/Assets.xcassets/EasyCode/btnbg.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "btnbg.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "btnbg@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/EasyCode/Resource/btnbg.png b/EasyCode/Assets.xcassets/EasyCode/btnbg.imageset/btnbg.png similarity index 100% rename from EasyCode/Resource/btnbg.png rename to EasyCode/Assets.xcassets/EasyCode/btnbg.imageset/btnbg.png diff --git a/EasyCode/Resource/btnbg@2x.png b/EasyCode/Assets.xcassets/EasyCode/btnbg.imageset/btnbg@2x.png similarity index 100% rename from EasyCode/Resource/btnbg@2x.png rename to EasyCode/Assets.xcassets/EasyCode/btnbg.imageset/btnbg@2x.png diff --git a/EasyCode/Assets.xcassets/EasyCode/btnbg2.imageset/Contents.json b/EasyCode/Assets.xcassets/EasyCode/btnbg2.imageset/Contents.json new file mode 100644 index 0000000..dfa1ba5 --- /dev/null +++ b/EasyCode/Assets.xcassets/EasyCode/btnbg2.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "btnbg2.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "btnbg2@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/EasyCode/Resource/btnbg2.png b/EasyCode/Assets.xcassets/EasyCode/btnbg2.imageset/btnbg2.png similarity index 100% rename from EasyCode/Resource/btnbg2.png rename to EasyCode/Assets.xcassets/EasyCode/btnbg2.imageset/btnbg2.png diff --git a/EasyCode/Resource/btnbg2@2x.png b/EasyCode/Assets.xcassets/EasyCode/btnbg2.imageset/btnbg2@2x.png similarity index 100% rename from EasyCode/Resource/btnbg2@2x.png rename to EasyCode/Assets.xcassets/EasyCode/btnbg2.imageset/btnbg2@2x.png diff --git a/EasyCode/Assets.xcassets/EasyCode/btnguide.imageset/Contents.json b/EasyCode/Assets.xcassets/EasyCode/btnguide.imageset/Contents.json new file mode 100644 index 0000000..feb9c6f --- /dev/null +++ b/EasyCode/Assets.xcassets/EasyCode/btnguide.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "btnguide.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "btnguide@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/EasyCode/Resource/btnguide.png b/EasyCode/Assets.xcassets/EasyCode/btnguide.imageset/btnguide.png similarity index 100% rename from EasyCode/Resource/btnguide.png rename to EasyCode/Assets.xcassets/EasyCode/btnguide.imageset/btnguide.png diff --git a/EasyCode/Resource/btnguide@2x.png b/EasyCode/Assets.xcassets/EasyCode/btnguide.imageset/btnguide@2x.png similarity index 100% rename from EasyCode/Resource/btnguide@2x.png rename to EasyCode/Assets.xcassets/EasyCode/btnguide.imageset/btnguide@2x.png diff --git a/EasyCode/Assets.xcassets/EasyCode/edit.imageset/Contents.json b/EasyCode/Assets.xcassets/EasyCode/edit.imageset/Contents.json new file mode 100644 index 0000000..3f753a7 --- /dev/null +++ b/EasyCode/Assets.xcassets/EasyCode/edit.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "edit.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/EasyCode/Resource/edit.png b/EasyCode/Assets.xcassets/EasyCode/edit.imageset/edit.png similarity index 100% rename from EasyCode/Resource/edit.png rename to EasyCode/Assets.xcassets/EasyCode/edit.imageset/edit.png diff --git a/EasyCode/Assets.xcassets/EasyCode/mainbg.imageset/Contents.json b/EasyCode/Assets.xcassets/EasyCode/mainbg.imageset/Contents.json new file mode 100644 index 0000000..a0773f8 --- /dev/null +++ b/EasyCode/Assets.xcassets/EasyCode/mainbg.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "mainbg.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "mainbg@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/EasyCode/Resource/mainbg.png b/EasyCode/Assets.xcassets/EasyCode/mainbg.imageset/mainbg.png similarity index 100% rename from EasyCode/Resource/mainbg.png rename to EasyCode/Assets.xcassets/EasyCode/mainbg.imageset/mainbg.png diff --git a/EasyCode/Resource/mainbg@2x.png b/EasyCode/Assets.xcassets/EasyCode/mainbg.imageset/mainbg@2x.png similarity index 100% rename from EasyCode/Resource/mainbg@2x.png rename to EasyCode/Assets.xcassets/EasyCode/mainbg.imageset/mainbg@2x.png diff --git a/EasyCode/Assets.xcassets/EasyCode/remove.imageset/Contents.json b/EasyCode/Assets.xcassets/EasyCode/remove.imageset/Contents.json new file mode 100644 index 0000000..d7238fe --- /dev/null +++ b/EasyCode/Assets.xcassets/EasyCode/remove.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "remove.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/EasyCode/Resource/remove.png b/EasyCode/Assets.xcassets/EasyCode/remove.imageset/remove.png similarity index 100% rename from EasyCode/Resource/remove.png rename to EasyCode/Assets.xcassets/EasyCode/remove.imageset/remove.png diff --git a/EasyCode/Base.lproj/Document.xib b/EasyCode/Base.lproj/Document.xib new file mode 100644 index 0000000..94beef9 --- /dev/null +++ b/EasyCode/Base.lproj/Document.xib @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/EasyCode/Base.lproj/MainMenu.xib b/EasyCode/Base.lproj/MainMenu.xib index 1756928..ace583b 100644 --- a/EasyCode/Base.lproj/MainMenu.xib +++ b/EasyCode/Base.lproj/MainMenu.xib @@ -1,9 +1,8 @@ - + - - + @@ -13,11 +12,7 @@ - - - - - + @@ -69,50 +64,17 @@ - - - - - - - - - - - - - - - - - - - - - - - - + - + - - - - - - - - - - @@ -680,61 +642,5 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/EasyCode/Document/ECSnippetsDocument.h b/EasyCode/Document/ECSnippetsDocument.h new file mode 100644 index 0000000..e31ad04 --- /dev/null +++ b/EasyCode/Document/ECSnippetsDocument.h @@ -0,0 +1,48 @@ +// +// ECSnippetDocument.h +// AirCode +// +// Created by lijia on 2017/3/1. +// Copyright © 2017年 music4kid. All rights reserved. +// + +#import +#import "EditorWindowController.h" +#import "ECSnippet.h" +@protocol ECSnippetEntrysDocumentDelegate; + +EC_EXTERN NSString *const ECDocumentLoadedNotificationOC; +EC_EXTERN NSString *const ECDocumentLoadedNotificationSwift; + +typedef NS_ENUM(NSInteger,ECSnippetEntryActionType) { + ECSnippetEntryActionTypeCreate, + ECSnippetEntryActionTypeRetrieve, + ECSnippetEntryActionTypeUpdate, + ECSnippetEntryActionTypeDelete +}; + +@interface ECSnippetDocument : NSDocument +@property (nonatomic, assign) ECSourceType sourceType; +@property (nonatomic, copy,readonly) ECSnippet* snippet; +@property (nonatomic, weak) id delegate; + +-(instancetype)initWithFileURL:(NSURL*)itemURL sourceType:(ECSourceType)type; +//条目数量 +-(NSInteger)snippetEntryCount; +//根据键查找片段 +-(ECSnippetEntry*)snippetEntryForKey:(NSString*)key; +//插入片段 +-(void)addSnippetEntry:(ECSnippetEntry*)snippet; +//根据键删除片段 +-(void)removeSnippetEntryForKey:(NSString*)key; +//根据键更新片段 +-(void)updateSnippetEntry:(ECSnippetEntry*)snippet; +//保存文档 +-(void)saveDocumentCompletionHandler:(void (^)(void))handler; +@end + +@protocol ECSnippetEntrysDocumentDelegate +-(void)snippetsDocument:(ECSnippetDocument*)document performActionWithType:(ECSnippetEntryActionType)actionType withEntry:(ECSnippetEntry*)snippet; +@end + + diff --git a/EasyCode/Document/ECSnippetsDocument.m b/EasyCode/Document/ECSnippetsDocument.m new file mode 100644 index 0000000..5899ae8 --- /dev/null +++ b/EasyCode/Document/ECSnippetsDocument.m @@ -0,0 +1,165 @@ +// +// ECSnippetDocument.m +// AirCode +// +// Created by lijia on 2017/3/1. +// Copyright © 2017年 music4kid. All rights reserved. +// + +#import "ECSnippetsDocument.h" +#import "NSWindowController+Additions.h" +#import "ECSnippetEntry.h" +#import "ECMappingForObjectiveC.h" +#import "ECMappingForSwift.h" +#import "NSFileWrapper+Additions.h" +#import "ECSnippetHelper.h" + +NSString *const ECDocumentLoadedNotificationOC = @"ECDocumentLoadedNotificationOC"; +NSString *const ECDocumentLoadedNotificationSwift = @"ECDocumentLoadedNotificationSwift"; + +@interface ECSnippetDocument () +@property (nonatomic, strong) NSFileWrapper *fileWrapper; +@property (nonatomic, assign,getter=hasSavedAlready) BOOL savedAlready; +@end + +@implementation ECSnippetDocument +-(instancetype)initWithFileURL:(NSURL *)itemURL sourceType:(ECSourceType)type { + if (type == ECSourceTypeOC) { + self = [super initWithContentsOfURL:itemURL ofType:DirectoryOCName error:nil]; + } else { + self = [super initWithContentsOfURL:itemURL ofType:DirectorySwiftName error:nil];; + } + + if (self) { + _sourceType = type; + _savedAlready = NO; + } + return self; +} + +-(void)sortedSnippets { + [_snippet sortedEntry]; +} + +-(NSInteger)snippetEntryCount { + return [_snippet entryCount]; +} + +-(ECSnippetEntry*)snippetEntryForKey:(NSString*)key { + return [_snippet entryForKey:key]; +} + +-(void)addSnippetEntry:(ECSnippetEntry*)entry { + if ([entry.key ec_isNotEmpty] == NO) { + return; + } + [_snippet addEntry:entry]; + [self saveDocumentCompletionHandler:^{ + if ([_delegate respondsToSelector:@selector(snippetsDocument:performActionWithType:withEntry:)]) { + [_delegate snippetsDocument:self performActionWithType:ECSnippetEntryActionTypeCreate withEntry:entry]; + } + }]; +} + +-(void)removeSnippetEntryForKey:(NSString*)key { + ECSnippetEntry* hitEntry = [_snippet removeEntryForKey:key]; + [self saveDocumentCompletionHandler:^{ + if ([_delegate respondsToSelector:@selector(snippetsDocument:performActionWithType:withEntry:)]) { + [_delegate snippetsDocument:self performActionWithType:ECSnippetEntryActionTypeDelete withEntry:hitEntry]; + } + }]; +} + +-(void)updateSnippetEntry:(ECSnippetEntry*)entry { + ECSnippetEntry* hitEntry = entry; + [_snippet updateEntry:hitEntry]; + [self saveDocumentCompletionHandler:^{ + if ([_delegate respondsToSelector:@selector(snippetsDocument:performActionWithType:withEntry:)]) { + [_delegate snippetsDocument:self performActionWithType:ECSnippetEntryActionTypeUpdate withEntry:hitEntry]; + } + }]; +} + +-(void)saveDocumentCompletionHandler:(void (^)(void))handler { + NSInteger version = [ECSnippetHelper versionForSourceType:_sourceType]; + if (version == _snippet.version.integerValue && [self hasSavedAlready]) { + if (handler) { + handler(); + } + return; + } + [self sortedSnippets]; + + NSString *typeName = DirectoryOCName; + if (_sourceType == ECSourceTypeOC) { + typeName = DirectoryOCName; + } else { + typeName = DirectorySwiftName; + } + + [self saveToURL:self.fileURL ofType:typeName forSaveOperation:NSSaveOperation completionHandler:^(NSError * _Nullable errorOrNil) { + if (errorOrNil) { + NSLog(@"Save Document Error :%@",[errorOrNil localizedDescription]); + } else { + _savedAlready = YES; + + NSString* dirnameKey = [ECSnippetHelper directoryForSourceType:_sourceType]; + NSData* snippetData = [_snippet snippetData]; + + NSNumber* versionNum = _snippet.version; + NSString* versionKey = [NSString stringWithFormat:kVersionFormat,dirnameKey]; + [ESharedUserDefault setObjects:@[snippetData,versionNum] forKeys:@[dirnameKey,versionKey]]; + } + + if (handler) { + handler(); + } + }]; +} + +#pragma mark - Override Documents +-(NSString *)displayName { + return @"Code Snippet"; +} + ++ (BOOL)autosavesInPlace { + return NO; +} + +- (NSFileWrapper *)fileWrapperOfType:(NSString *)typeName error:(NSError **)outError { + //snippet data + NSData* snippetData = [NSKeyedArchiver archivedDataWithRootObject:_snippet]; + NSFileWrapper* snippetWrapper = [[NSFileWrapper alloc] initRegularFileWithContents:snippetData]; + snippetWrapper.preferredFilename = SnippetFileName; + //version data + NSData* verData = [_snippet.version.stringValue dataUsingEncoding:NSUTF8StringEncoding]; + NSFileWrapper* verWrapper = [[NSFileWrapper alloc] initRegularFileWithContents:verData]; + verWrapper.preferredFilename = VersionFileName; + if (_fileWrapper == nil) { + NSDictionary* fileWrappers = @{ SnippetFileName:snippetWrapper, + VersionFileName:verWrapper }; + _fileWrapper = [[NSFileWrapper alloc] initDirectoryWithFileWrappers:fileWrappers]; + } else { + [_fileWrapper ec_replaceFileWrapper:snippetWrapper forKey:SnippetFileName]; + [_fileWrapper ec_replaceFileWrapper:verWrapper forKey:VersionFileName]; + } + + return _fileWrapper; +} + +- (BOOL)readFromFileWrapper:(NSFileWrapper *)fileWrapper ofType:(NSString *)typeName error:(NSError * _Nullable *)outError { + _snippet = [ECSnippetHelper snippetWithFileWrapper:fileWrapper]; + + if (typeName == DirectoryOCName) { + [[NSNotificationCenter defaultCenter] postNotificationName:ECDocumentLoadedNotificationOC + object:self]; + } else { + [[NSNotificationCenter defaultCenter] postNotificationName:ECDocumentLoadedNotificationSwift + object:self]; + } + + + return YES; +} + +@end diff --git a/EasyCode/ECMainWindowController.h b/EasyCode/ECMainWindowController.h new file mode 100644 index 0000000..b5c4e36 --- /dev/null +++ b/EasyCode/ECMainWindowController.h @@ -0,0 +1,13 @@ +// +// ECMainWindowController.h +// EasyCode +// +// Created by lijia on 02/03/2017. +// Copyright © 2017 music4kid. All rights reserved. +// + +#import +EC_EXTERN NSString* const ECiCloudSyncChangedNotification; +@interface ECMainWindowController : NSWindowController + +@end diff --git a/EasyCode/ECMainWindowController.m b/EasyCode/ECMainWindowController.m new file mode 100644 index 0000000..051f909 --- /dev/null +++ b/EasyCode/ECMainWindowController.m @@ -0,0 +1,80 @@ +// +// ECMainWindowController.m +// EasyCode +// +// Created by lijia on 02/03/2017. +// Copyright © 2017 music4kid. All rights reserved. +// + +#import "ECMainWindowController.h" +#import "EditorWindowController.h" + +NSString *const ECiCloudSyncChangedNotification = @"ECiCloudSyncChangedNotification"; + +@interface ECMainWindowController () +@property (nonatomic, weak) IBOutlet NSButton *useicloudBtn; +@property (nonatomic, strong) EditorWindowController* editorOC; +@property (nonatomic, strong) EditorWindowController* editorSwift; +@end + +@implementation ECMainWindowController + +- (void)windowDidLoad { + [super windowDidLoad]; + _useicloudBtn.state = [ESharedUserDefault boolForKey:kUseiCloudSync]; +} + +- (IBAction)showEditorWindowForOC:(id)sender { + if (self.editorOC == nil) { + self.editorOC = [[EditorWindowController alloc] initEditorWindowForType:ECSourceTypeOC]; + } + [_editorOC showWindow:self]; +} + +- (IBAction)showEditorWindowForSwift:(id)sender { + if (self.editorSwift == nil) { + self.editorSwift = [[EditorWindowController alloc] initEditorWindowForType:ECSourceTypeSwift]; + } + [_editorSwift showWindow:self]; +} + +- (IBAction)useiCloudCheck:(NSButton*)sender { + BOOL useiCloud = (sender.state == NSOnState); + if (useiCloud) { + id ubiq = [[NSFileManager defaultManager] ubiquityIdentityToken]; + if (ubiq) { + [ESharedUserDefault setBool:YES forKey:kUseiCloudSync]; + [[NSNotificationCenter defaultCenter] postNotificationName:ECiCloudSyncChangedNotification object:nil]; + } else { + [ESharedUserDefault setBool:NO forKey:kUseiCloudSync]; + sender.state = NSOffState; + //Alert Note + } + } else { + id ubiq = [[NSFileManager defaultManager] ubiquityIdentityToken]; + if (ubiq) { + NSAlert *warningAlert = [NSAlert ec_alertWithStyle:NSWarningAlertStyle + messageText:NSLocalizedString(@"iCloud_Attention", nil) + informativeText:NSLocalizedString(@"iCloud_Attention_Message", nil) + buttonTitle:NSLocalizedString(@"Button_OK_Title",nil), + NSLocalizedString(@"Button_Cancel_Title", nil), + nil]; + + [warningAlert beginSheetModalForWindow:self.window completionHandler:^(NSModalResponse returnCode) { + if (returnCode == NSAlertFirstButtonReturn) { //OK + [ESharedUserDefault setBool:NO forKey:kUseiCloudSync]; + [[NSNotificationCenter defaultCenter] postNotificationName:ECiCloudSyncChangedNotification object:nil]; + } + }]; + } else { + [ESharedUserDefault setBool:NO forKey:kUseiCloudSync]; + } + } +} + +- (IBAction)showHowToUse:(id)sender { + [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString: @"https://github.com/music4kid/EasyCode-Xcode"]]; +} + + +@end diff --git a/EasyCode/ECMainWindowController.xib b/EasyCode/ECMainWindowController.xib new file mode 100644 index 0000000..9b2cb9b --- /dev/null +++ b/EasyCode/ECMainWindowController.xib @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/EasyCode/EasyCode.entitlements b/EasyCode/EasyCode.entitlements index 60c1f0a..34b7dfb 100644 --- a/EasyCode/EasyCode.entitlements +++ b/EasyCode/EasyCode.entitlements @@ -2,11 +2,27 @@ + com.apple.developer.aps-environment + development + com.apple.developer.icloud-container-identifiers + + iCloud.$(CFBundleIdentifier) + + com.apple.developer.icloud-services + + CloudDocuments + + com.apple.developer.ubiquity-container-identifiers + + iCloud.$(CFBundleIdentifier) + + com.apple.developer.ubiquity-kvstore-identifier + $(TeamIdentifierPrefix)$(CFBundleIdentifier) com.apple.security.app-sandbox com.apple.security.application-groups - 2WQE6AU5PD.group.com.music4kid.easycode + $(TeamIdentifierPrefix)group.com.sito.easycode diff --git a/EasyCode/Info.plist b/EasyCode/Info.plist index f19d1eb..a8f59f8 100644 --- a/EasyCode/Info.plist +++ b/EasyCode/Info.plist @@ -4,6 +4,35 @@ CFBundleDevelopmentRegion en + CFBundleDisplayName + + CFBundleDocumentTypes + + + CFBundleTypeExtensions + + ec + + CFBundleTypeIconFile + + CFBundleTypeName + Snippets Document + CFBundleTypeOSTypes + + ???? + + CFBundleTypeRole + Editor + LSItemContentTypes + + com.yingxiang.easycode.ec + + LSTypeIsPackage + 1 + NSDocumentClass + ECSnippetDocument + + CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIconFile @@ -24,11 +53,29 @@ public.app-category.developer-tools LSMinimumSystemVersion $(MACOSX_DEPLOYMENT_TARGET) + LSUIElement + NSHumanReadableCopyright Copyright © 2016年 music4kid. All rights reserved. NSMainNibFile MainMenu NSPrincipalClass NSApplication + UTExportedTypeDeclarations + + + UTTypeDescription + Snippets Document package + UTTypeIdentifier + com.yingxiang.easycode.ec + UTTypeTagSpecification + + public.filename-extension + + ec + + + + diff --git a/EasyCode/MappingEditor/DetailEditorController/DetailWindowController.h b/EasyCode/MappingEditor/DetailWindowController.h similarity index 74% rename from EasyCode/MappingEditor/DetailEditorController/DetailWindowController.h rename to EasyCode/MappingEditor/DetailWindowController.h index 7e54728..08088cf 100644 --- a/EasyCode/MappingEditor/DetailEditorController/DetailWindowController.h +++ b/EasyCode/MappingEditor/DetailWindowController.h @@ -7,7 +7,7 @@ // #import -#import "EShortcutEntry.h" +#import "ECSnippetEntry.h" typedef enum : NSUInteger { DetailEditorModeUpdate, @@ -15,21 +15,18 @@ typedef enum : NSUInteger { } DetailEditorMode; @protocol DetailWindowEditorDelegate - -- (void)onEntryUpdated:(EShortcutEntry*)entry; -- (void)onEntryInserted:(EShortcutEntry*)entry; - +- (void)onSnippetUpdated:(ECSnippetEntry*)snippet; +- (void)onSnippetInserted:(ECSnippetEntry*)snippet; @end @interface DetailWindowController : NSWindowController +@property (nonatomic, readonly,getter=hasEdited) BOOL edited; -- (void)initWithMappingEntry:(EShortcutEntry*)entry; +- (void)initWithEntry:(ECSnippetEntry*)entry; @property (nonatomic, weak) id delegate; @property (nonatomic, assign) DetailEditorMode editMode; - - @property (nonatomic, strong) IBOutlet NSTextField* txtKey; @property (nonatomic, strong) IBOutlet NSTextField* txtCode; diff --git a/EasyCode/MappingEditor/DetailEditorController/DetailWindowController.m b/EasyCode/MappingEditor/DetailWindowController.m similarity index 71% rename from EasyCode/MappingEditor/DetailEditorController/DetailWindowController.m rename to EasyCode/MappingEditor/DetailWindowController.m index d20d251..7167af6 100644 --- a/EasyCode/MappingEditor/DetailEditorController/DetailWindowController.m +++ b/EasyCode/MappingEditor/DetailWindowController.m @@ -9,38 +9,37 @@ #import "DetailWindowController.h" @interface DetailWindowController () -@property (nonatomic, strong) EShortcutEntry* curEntry; - +@property (nonatomic, strong) ECSnippetEntry* curEntry; @end @implementation DetailWindowController - (void)windowDidLoad { [super windowDidLoad]; + _edited = NO; [self updateEntryDisplay]; - self.window.delegate = self; - + [self.window center]; } - (void)windowWillClose:(NSNotification *)notification { if (_delegate) { if (_editMode == DetailEditorModeUpdate) { - [_delegate onEntryUpdated:_curEntry]; + [_delegate onSnippetUpdated:_curEntry]; } else if(_editMode == DetailEditorModeInsert) { - [_delegate onEntryInserted:_curEntry]; + [_delegate onSnippetInserted:_curEntry]; } } + _edited = NO; } -- (void)initWithMappingEntry:(EShortcutEntry*)entry +- (void)initWithEntry:(ECSnippetEntry*)entry { self.curEntry = entry; - [self updateEntryDisplay]; } @@ -71,10 +70,18 @@ - (void)controlTextDidChange:(NSNotification *)notification { NSTextField *textField = [notification object]; if (textField == _txtKey) { - _curEntry.key = [textField stringValue]; + NSString* changedValue = [textField stringValue]; + if ([_curEntry.key isEqualToString:changedValue] == NO) { + _edited = YES; + } + _curEntry.key = changedValue; } else if(textField == _txtCode) { + NSString* changedValue = [textField stringValue]; + if ([_curEntry.code isEqualToString:changedValue] == NO) { + _edited = YES; + } _curEntry.code = [textField stringValue]; } } @@ -99,4 +106,12 @@ - (BOOL)control:(NSControl*)control textView:(NSTextView*)textView doCommandBySe return result; } +- (void)setEditMode:(DetailEditorMode)editMode { + _editMode = editMode; + if (_editMode == DetailEditorModeUpdate) { + [_txtCode becomeFirstResponder]; + } else { + [_txtKey becomeFirstResponder]; + } +} @end diff --git a/EasyCode/MappingEditor/DetailEditorController/DetailWindowController.xib b/EasyCode/MappingEditor/DetailWindowController.xib similarity index 100% rename from EasyCode/MappingEditor/DetailEditorController/DetailWindowController.xib rename to EasyCode/MappingEditor/DetailWindowController.xib diff --git a/EasyCode/MappingEditor/ECSnippet.h b/EasyCode/MappingEditor/ECSnippet.h new file mode 100644 index 0000000..1f3d0fa --- /dev/null +++ b/EasyCode/MappingEditor/ECSnippet.h @@ -0,0 +1,34 @@ +// +// ECSnippet.h +// EasyCode +// +// Created by lijia on 07/03/2017. +// Copyright © 2017 music4kid. All rights reserved. +// + +#import +#import "ECSnippetEntry.h" +#import "ECDefine.h" + +@interface ECSnippet : NSObject +@property (nonatomic, copy) NSNumber* version; +@property (nonatomic, copy) NSNumber* type; +@property (nonatomic, copy) NSArray* entries; + +-(instancetype)initWithSourceType:(ECSourceType)sourceType entries:(NSArray*)entries; + +//sort entry +-(void)sortedEntry; +//count entry +-(NSInteger)entryCount; +//search entry +-(ECSnippetEntry*)entryForKey:(NSString*)key; +//insert entry +-(void)addEntry:(ECSnippetEntry*)entry; +//delete entry +-(ECSnippetEntry*)removeEntryForKey:(NSString*)key; +//update entry +-(void)updateEntry:(ECSnippetEntry*)entry; +//use for store +-(NSData*)snippetData; +@end diff --git a/EasyCode/MappingEditor/ECSnippet.m b/EasyCode/MappingEditor/ECSnippet.m new file mode 100644 index 0000000..bc0e80e --- /dev/null +++ b/EasyCode/MappingEditor/ECSnippet.m @@ -0,0 +1,121 @@ +// +// ECSnippet.m +// EasyCode +// +// Created by lijia on 07/03/2017. +// Copyright © 2017 music4kid. All rights reserved. +// + +#import "ECSnippet.h" +#import "NSString+Additions.h" + + +@interface ECSnippet () { + NSMutableArray* _entryList; +} +@end + + +@implementation ECSnippet +-(instancetype)initWithSourceType:(ECSourceType)sourceType entries:(NSArray*)entries { + self = [super init]; + if (self) { + _type = @(sourceType); + _entryList = [entries mutableCopy]; + _version = @(1); + } + return self; +} + +- (instancetype)initWithCoder:(NSCoder *)decoder { + self.version = [decoder decodeObjectForKey:@"version"]; + self.entries = [decoder decodeObjectForKey:@"entries"]; + self.type = [decoder decodeObjectForKey:@"type"]; + return self; +} + +- (void)encodeWithCoder:(NSCoder *)encoder { + [encoder encodeObject:_version forKey:@"version"]; + [encoder encodeObject:[self entries] forKey:@"entries"]; + [encoder encodeObject:_type forKey:@"type"]; +} + +- (id)copyWithZone:(NSZone *)zone { + ECSnippet* snippet = [[[self class] allocWithZone:zone] init]; + snippet.version = _version; + snippet.entries = [_entryList copy]; + snippet.type = _type; + return snippet; +} + +-(NSArray *)entries { + return [_entryList copy]; +} + +-(void)setEntries:(NSArray *)entries { + _entryList = [entries mutableCopy]; +} + +//排序 +-(void)sortedEntry { + [_entryList sortUsingComparator:^NSComparisonResult(ECSnippetEntry* _Nonnull e1, ECSnippetEntry* _Nonnull e2) { + return [e1.key compare:e2.key]; + }]; +} + +//条目数量 +-(NSInteger)entryCount { + return _entryList.count; +} + +-(ECSnippetEntry*)entryForKey:(NSString*)key { + NSString* trimKey = [key ec_trimWhiteSpace]; + NSArray* entryList = [self entries]; + NSUInteger index = [entryList indexOfObjectWithOptions:NSEnumerationConcurrent passingTest:^BOOL(ECSnippetEntry* _Nonnull snippet, NSUInteger idx, BOOL * _Nonnull stop) { + BOOL result = [snippet.key isEqualToString:trimKey]; + if (result) { + *stop = YES; + } + return result; + }]; + if (index != NSNotFound) { + return entryList[index]; + } + return nil; +} + +-(void)addEntry:(ECSnippetEntry*)entry { + if ([entry.key ec_isNotEmpty] == NO) { + return; + } + ECSnippetEntry* hitEntry = [self entryForKey:entry.key]; + if (hitEntry == nil) { //add + [_entryList addObject:entry]; + } else { + [self updateEntry:entry]; + } + _version = @([_NUMBER(_version) unsignedIntegerValue] + 1); +} + +-(ECSnippetEntry*)removeEntryForKey:(NSString*)key { + ECSnippetEntry* hitEntry = [self entryForKey:key]; + if (hitEntry) { + [_entryList removeObject:hitEntry]; + _version = @([_NUMBER(_version) unsignedIntegerValue] + 1); + } + return hitEntry; +} + +-(void)updateEntry:(ECSnippetEntry*)entry { + ECSnippetEntry* hitEntry = [self entryForKey:entry.key]; + [hitEntry updateBySnippet:hitEntry]; + _version = @([_NUMBER(_version) unsignedIntegerValue] + 1); +} + +-(NSData*)snippetData { + NSData* data = [NSKeyedArchiver archivedDataWithRootObject:self]; + return data; +} + + +@end diff --git a/EasyCode/MappingEditor/ECSnippetEntry.h b/EasyCode/MappingEditor/ECSnippetEntry.h new file mode 100644 index 0000000..8d1597b --- /dev/null +++ b/EasyCode/MappingEditor/ECSnippetEntry.h @@ -0,0 +1,19 @@ +// +// ECSnippetEntry.h +// EasyCode +// +// Created by lijia on 07/03/2017. +// Copyright © 2016年 music4kid. All rights reserved. +// + +#import + +@interface ECSnippetEntry : NSObject +@property (nonatomic, copy) NSString* key; +@property (nonatomic, copy) NSString* code; +@property (nonatomic, copy) NSString* createAt; + ++(instancetype)snippetWithKey:(NSString*)key code:(NSString*)code; + +-(void)updateBySnippet:(ECSnippetEntry*)snippet; +@end diff --git a/EasyCode/MappingEditor/ECSnippetEntry.m b/EasyCode/MappingEditor/ECSnippetEntry.m new file mode 100644 index 0000000..7ace6fa --- /dev/null +++ b/EasyCode/MappingEditor/ECSnippetEntry.m @@ -0,0 +1,61 @@ +// +// ECSnippetEntry.m +// EasyCode +// +// Created by gao feng on 2016/10/20. +// Copyright © 2016年 music4kid. All rights reserved. +// + +#import "ECSnippetEntry.h" +#import "NSString+Additions.h" + +static NSDateFormatter* formatter = nil; + +@implementation ECSnippetEntry ++ (void)initialize { + if (self == [ECSnippetEntry class]) { + formatter = [[NSDateFormatter alloc] init]; + [formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"]; + } +} + ++(instancetype)snippetWithKey:(NSString*)key code:(NSString*)code { + ECSnippetEntry* snippet = [[[self class] alloc] init]; + snippet.key = key; + snippet.code = code; + snippet.createAt = [formatter stringFromDate:[NSDate date]]; + return snippet; +} + +- (instancetype)initWithCoder:(NSCoder *)decoder { + self.key = [decoder decodeObjectForKey:@"key"]; + self.code = [decoder decodeObjectForKey:@"code"]; + self.createAt = [decoder decodeObjectForKey:@"createAt"]; + return self; +} + +- (void)encodeWithCoder:(NSCoder *)encoder { + [encoder encodeObject:_key forKey:@"key"]; + [encoder encodeObject:_code forKey:@"code"]; + [encoder encodeObject:_createAt forKey:@"createAt"]; +} + +- (id)copyWithZone:(NSZone *)zone { + ECSnippetEntry* snippet = [[[self class] allocWithZone:zone] init]; + snippet.key = _key; + snippet.code = _code; + snippet.createAt = _createAt; + return snippet; +} + +- (void)setKey:(NSString *)key { + _key = [key ec_trimWhiteSpace]; +} + +-(void)updateBySnippet:(ECSnippetEntry*)snippet { + if ([self.key isEqualToString:snippet.key]) { + self.code = snippet.code; + } +} + +@end diff --git a/EasyCode/MappingEditor/EEditorTableView.m b/EasyCode/MappingEditor/EEditorTableView.m deleted file mode 100644 index ca893f4..0000000 --- a/EasyCode/MappingEditor/EEditorTableView.m +++ /dev/null @@ -1,14 +0,0 @@ -// -// EEditorTableView.m -// EasyCode -// -// Created by gao feng on 2016/10/20. -// Copyright © 2016年 music4kid. All rights reserved. -// - -#import "EEditorTableView.h" - -@implementation EEditorTableView - - -@end diff --git a/EasyCode/MappingEditor/EShortcutEntry.h b/EasyCode/MappingEditor/EShortcutEntry.h deleted file mode 100644 index b21f819..0000000 --- a/EasyCode/MappingEditor/EShortcutEntry.h +++ /dev/null @@ -1,14 +0,0 @@ -// -// EShortcutEntry.h -// EasyCode -// -// Created by gao feng on 2016/10/20. -// Copyright © 2016年 music4kid. All rights reserved. -// - -#import - -@interface EShortcutEntry : NSObject -@property (nonatomic, strong) NSString* key; -@property (nonatomic, strong) NSString* code; -@end diff --git a/EasyCode/MappingEditor/EShortcutEntry.m b/EasyCode/MappingEditor/EShortcutEntry.m deleted file mode 100644 index caaa8ef..0000000 --- a/EasyCode/MappingEditor/EShortcutEntry.m +++ /dev/null @@ -1,13 +0,0 @@ -// -// EShortcutEntry.m -// EasyCode -// -// Created by gao feng on 2016/10/20. -// Copyright © 2016年 music4kid. All rights reserved. -// - -#import "EShortcutEntry.h" - -@implementation EShortcutEntry - -@end diff --git a/EasyCode/MappingEditor/EditorWindowController.h b/EasyCode/MappingEditor/EditorWindowController.h index 8e8b5c8..8332332 100644 --- a/EasyCode/MappingEditor/EditorWindowController.h +++ b/EasyCode/MappingEditor/EditorWindowController.h @@ -8,15 +8,6 @@ #import -typedef enum : NSUInteger { - EditorTypeOC, - EditorTypeSwift, -} EditorType; - @interface EditorWindowController : NSWindowController - -@property (nonatomic, strong) IBOutlet NSTableView* tableView; - -- (void)initEditorWindow:(EditorType)editorType; - +- (instancetype)initEditorWindowForType:(ECSourceType)sourceType; @end diff --git a/EasyCode/MappingEditor/EditorWindowController.m b/EasyCode/MappingEditor/EditorWindowController.m index 46beeeb..ea8eac6 100644 --- a/EasyCode/MappingEditor/EditorWindowController.m +++ b/EasyCode/MappingEditor/EditorWindowController.m @@ -7,90 +7,288 @@ // #import "EditorWindowController.h" -#import "ESharedUserDefault.h" -#import "EShortcutEntry.h" +#import "ECMainWindowController.h" #import "DetailWindowController.h" +#import "ESharedUserDefault.h" +#import "ECSnippetEntry.h" +#import "ECSnippetsDocument.h" +#import "NSWindow+Additions.h" +#import "NSString+Additions.h" +#import "NSFileManager+Additions.h" +#import "ECSnippetHelper.h" +#import "EEditorTableMenu.h" +#import "EEditorTableRowView.h" -@interface EditorWindowController () -@property (nonatomic, strong) NSMutableDictionary* mappingDic; -@property (nonatomic, strong) NSMutableArray* mappingList; -@property (nonatomic, assign) EditorType editorType; - -@property (nonatomic, strong) NSImage* imgEdit; -@property (nonatomic, strong) NSImage* imgAdd; -@property (nonatomic, strong) NSImage* imgRemove; +@interface EditorWindowController () +@property (nonatomic, weak) IBOutlet NSWindow *toastPanel; +@property (nonatomic, weak) IBOutlet NSTextField *toastText; +@property (nonatomic, weak) IBOutlet NSScrollView *scrollView; +@property (nonatomic, weak) IBOutlet NSTableView *tableView; +@property (nonatomic, weak) IBOutlet NSTableColumn *filterColumn; +@property (nonatomic, weak) IBOutlet NSSearchField *searchField; +@property (nonatomic, strong) EEditorTableMenu *tableMenu; +@property (nonatomic, strong) NSImage *imgEdit; +@property (nonatomic, strong) NSImage *imgAdd; +@property (nonatomic, strong) NSImage *imgRemove; -@property (nonatomic, strong) DetailWindowController* detailEditor; +@property (nonatomic, assign) ECSourceType sourceType; +@property (nonatomic, strong) NSArray *filteringList; +@property (nonatomic, strong) NSArray *matchingList; +@property (nonatomic, strong) DetailWindowController *detailEditor; +@property (nonatomic, strong) ECSnippetDocument *snippetDoc; +@property (nonatomic, copy) NSString *searchKey; +@property (nonatomic, copy) NSString *dirname; +@property (nonatomic, strong) NSMetadataQuery *query; +@property (nonatomic, strong) NSMetadataItem *dataItem; @end @implementation EditorWindowController +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +- (instancetype)initEditorWindowForType:(ECSourceType)sourceType { + self = [super initWithWindowNibName:@"EditorWindowController"]; + if (self) { + _sourceType = sourceType; + } + return self; +} -- (void)initEditorWindow:(EditorType)editorType { - self.editorType = editorType; +- (void)setupData { + self.dirname = [ECSnippetHelper directoryForSourceType:_sourceType]; + self.window.title = self.dirname; self.imgEdit = [NSImage imageNamed:@"edit"]; self.imgAdd = [NSImage imageNamed:@"add"]; self.imgRemove = [NSImage imageNamed:@"remove"]; - self.mappingList = @[].mutableCopy; - if (_editorType == EditorTypeOC) { - self.mappingDic = [_UD readMappingForOC].mutableCopy; - self.window.title = @"Objective-C"; + if (_sourceType == ECSourceTypeOC) { + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(onDocumentLoaded:) + name:ECDocumentLoadedNotificationOC + object:nil]; } - else if(_editorType == EditorTypeSwift) - { - self.mappingDic = [_UD readMappingForSwift].mutableCopy; - self.window.title = @"Swift"; + else{ + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(onDocumentLoaded:) + name:ECDocumentLoadedNotificationSwift + object:nil]; } - NSArray* keys = self.mappingDic.allKeys; - keys = [keys sortedArrayUsingComparator:^NSComparisonResult(id _Nonnull obj1, id _Nonnull obj2) { - NSString* str1 = obj1; - NSString* str2 = obj2; - return [str1 compare:str2]; - }]; - for (NSString* key in keys) { - EShortcutEntry* entry = [EShortcutEntry new]; - entry.key = key; - entry.code = _mappingDic[key]; - [_mappingList addObject:entry]; - } - [self sortMappingList]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(onUbiquityIdentityChanged:) + name:NSUbiquityIdentityDidChangeNotification + object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(oniCloudSyncChanged:) + name:ECiCloudSyncChangedNotification + object:nil]; +} + +- (void)setupView { + _tableMenu = [[EEditorTableMenu alloc] initWithTitle:@"Menu"]; + _tableMenu.editorDelegate = self; + [_tableView setMenu:_tableMenu]; + [_tableView setDoubleAction:@selector(onHandleDoubleClick:)]; + [_tableView setSelectionHighlightStyle:NSTableViewSelectionHighlightStyleRegular]; + + _searchField.delegate = self; + _toastPanel.backgroundColor = [NSColor colorWithWhite:0 alpha:0.5]; + [_toastPanel ec_setCornRadius:12]; + [_toastPanel orderOut:self]; + + self.window.delegate = self; + [self.window center]; } + - (void)windowDidLoad { [super windowDidLoad]; - - [_tableView setSelectionHighlightStyle:NSTableViewSelectionHighlightStyleNone]; + [self setupData]; + [self setupView]; + [self loadDocument]; +} + +- (void)reloadData { dispatch_async(dispatch_get_main_queue(), ^{ [_tableView reloadData]; }); +} + +- (void)onDocumentLoaded:(NSNotification*)notification { + _snippetDoc = [notification object]; + _snippetDoc.delegate = self; + [_snippetDoc saveDocumentCompletionHandler:^{ + [self reloadData]; + }]; +} + +- (void)onUbiquityIdentityChanged:(NSNotification*)notification { + [self loadDocument]; +} + +- (void)oniCloudSyncChanged:(NSNotification*)notification { + BOOL useiCloud = [ESharedUserDefault boolForKey:kUseiCloudSync]; + NSURL* baseURL = [[NSFileManager defaultManager] ec_localURL]; + if (useiCloud) { + baseURL = [[NSFileManager defaultManager] ec_ubiquityURL]; + } + NSURL* destURL = [baseURL URLByAppendingPathComponent:_dirname]; + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + NSError* error = nil; + BOOL success = [[NSFileManager defaultManager] setUbiquitous:useiCloud itemAtURL:_snippetDoc.fileURL destinationURL:destURL error:&error]; + if (!success) { + NSLog(@"ubiquitous move error :%@",[error localizedDescription]); + } + [self loadDocument]; + }); +} + +- (void)queryDidFinishGathering:(NSNotification *)notification { + NSMetadataQuery *query = [notification object]; + [query disableUpdates]; + [query stopQuery]; + + [[NSNotificationCenter defaultCenter] removeObserver:self + name:NSMetadataQueryDidFinishGatheringNotification + object:nil]; + [self loadDataWithQuery:query]; + _query = nil; +} + +- (void)loadDocument { + id ubiq = [[NSFileManager defaultManager] ubiquityIdentityToken]; + BOOL useiCloud = [ESharedUserDefault boolForKey:kUseiCloudSync]; + if (ubiq && useiCloud) { //iCloud Enabled and Checked + _query = [[NSMetadataQuery alloc] init]; + _query.searchScopes = @[NSMetadataQueryUbiquitousDocumentsScope]; + NSPredicate *pred = [NSPredicate predicateWithFormat:@"%K == %@", NSMetadataItemFSNameKey,_dirname]; + [_query setPredicate:pred]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(queryDidFinishGathering:) + name:NSMetadataQueryDidFinishGatheringNotification + object:_query]; + [_query startQuery]; + } else { //iCloud Disabled + [self loadDataWithQuery:nil]; + } +} + +- (void)loadDataWithQuery:(NSMetadataQuery*)query { + NSURL* fileURL = [[NSFileManager defaultManager] ec_localSnippetsURLWithFilename:_dirname]; + if (query) { + //load from remote + if ([query resultCount] >= 1) { + _dataItem = [query resultAtIndex:0]; + fileURL = [_dataItem valueForAttribute:NSMetadataItemURLKey]; + } else { + fileURL = [[NSFileManager defaultManager] ec_ubiquitySnippetsURLWithFilename:_dirname]; + } + } + _snippetDoc = [[ECSnippetDocument alloc] initWithFileURL:fileURL sourceType:_sourceType]; + _snippetDoc.delegate = self; +} + +- (void)onFireSearchRequest { + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + NSArray* cloneList = _snippetDoc.snippet.entries; + if (_searchKey.length > 0) { + NSPredicate *predicate = [NSPredicate predicateWithFormat:@"key contains[cd] %@", _searchKey]; + cloneList = [cloneList filteredArrayUsingPredicate:predicate]; + } + _filteringList = cloneList; + [self reloadData]; + }); +} + +- (void)onQueueSearchRequest { + _searchKey = [_searchField.stringValue ec_trimWhiteSpace]; + [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(onFireSearchRequest) object:nil]; + [self performSelector:@selector(onFireSearchRequest) withObject:nil afterDelay:0.2f]; +} + +- (void)controlTextDidChange:(NSNotification *)notification { + [self onQueueSearchRequest]; +} + +- (BOOL)control:(NSControl *)control textView:(NSTextView *)textView doCommandBySelector:(SEL)commandSelector { + if (commandSelector == @selector(insertNewline:)) { //pressed enter + [self onQueueSearchRequest]; + } + return NO; +} + +- (void)focusSearchField:(id)sender { + [_searchField selectText:self]; + [[_searchField currentEditor] setSelectedRange:NSMakeRange(_searchField.stringValue.length, 0)]; +} + +- (void)keyDown:(NSEvent *)event { + if (([event modifierFlags] & NSCommandKeyMask) == NSCommandKeyMask){ + if ([event keyCode] == 3) { //Command + F + [self focusSearchField:nil]; + } + } +} + +- (void)pasteShortcutWithEntry:(ECSnippetEntry*)snippet { + NSPasteboard *pasteboard = [NSPasteboard generalPasteboard]; + [pasteboard clearContents]; + BOOL success = [pasteboard writeObjects:@[snippet.key]]; + if (success) { + _toastText.stringValue = snippet.key; + [_toastPanel ec_fadeInAnimated:NO]; + [_toastPanel ec_fadeOutAnimated:YES afterDelay:3]; + } +} + +- (void)onHandleDoubleClick:(id)sender { + if (_tableView.clickedColumn > 1) { + return; + } - self.window.delegate = self; + ECSnippetEntry* snippet = _matchingList[_tableView.clickedRow]; + if (_tableView.clickedColumn == 0) { //clicked shortcut key + [self pasteShortcutWithEntry:snippet]; + } else { + [self presentDetailEditorWithEntry:snippet]; + } } +#pragma mark NSTableViewDelegate - (void)tableViewSelectionDidChange:(NSNotification *)aNotification { - NSInteger selectedRow = [_tableView selectedRow]; - NSTableRowView *myRowView = [_tableView rowViewAtRow:selectedRow makeIfNecessary:NO]; - [myRowView setEmphasized:NO]; +// NSInteger selectedRow = [_tableView selectedRow]; +// NSTableRowView *myRowView = [_tableView rowViewAtRow:selectedRow makeIfNecessary:NO]; +// [myRowView setEmphasized:NO]; +} + +- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView { + if ([_searchKey ec_isNotEmpty]) { + _matchingList = _filteringList; + } else { + _matchingList = _snippetDoc.snippet.entries; + } + return [_matchingList count]; } - (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row { - // Get a new ViewCell NSTableCellView *cellView = [tableView makeViewWithIdentifier:tableColumn.identifier owner:self]; - EShortcutEntry* entry = _mappingList[row]; + ECSnippetEntry* snippet = _matchingList[row]; if( [tableColumn.identifier isEqualToString:@"cShortcut"] ) { - cellView.textField.stringValue = entry.key; + cellView.textField.stringValue = snippet.key; return cellView; } if( [tableColumn.identifier isEqualToString:@"cCode"] ) { - cellView.textField.stringValue = entry.code; + cellView.textField.stringValue = _STR(snippet.code); cellView.textField.textColor = [NSColor colorWithWhite:0.5 alpha:1]; return cellView; } @@ -122,27 +320,45 @@ - (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn return cellView; } +- (NSTableRowView *)tableView:(NSTableView *)tableView rowViewForRow:(NSInteger)row { + EEditorTableRowView* rowView = [[EEditorTableRowView alloc] initWithFrame:CGRectZero]; + return rowView; +} -- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView { - return [self.mappingList count]; +#pragma mark EEditorMenuDelegate +-(void)menu:(EEditorTableMenu*)menu didSelectedItemWithTag:(NSInteger)tag { + if (_tableView.selectedRow == -1) { + return; + } + + if (tag == 0) { //Edit + ECSnippetEntry* snippet = _matchingList[_tableView.selectedRow]; + [self presentDetailEditorWithEntry:snippet]; + } +} + +- (void)presentDetailEditorWithEntry:(ECSnippetEntry*)snippet { + if (snippet == nil) { + return; + } + + [self.detailEditor initWithEntry:snippet]; + self.detailEditor.editMode = DetailEditorModeUpdate; + [self.detailEditor showWindow:self]; } - (void)onEditCodeClick:(id)sender { NSButton* btn = sender; NSInteger row = [_tableView rowForView:btn]; - EShortcutEntry* entry = _mappingList[row]; - if (entry) { - [self.detailEditor initWithMappingEntry:entry]; - self.detailEditor.editMode = DetailEditorModeUpdate; - [self.detailEditor showWindow:self]; - } + ECSnippetEntry* snippet = _matchingList[row]; + [self presentDetailEditorWithEntry:snippet]; } - (void)onAddEntryClick:(id)sender { - EShortcutEntry* entry = [EShortcutEntry new]; - [self.detailEditor initWithMappingEntry:entry]; + ECSnippetEntry* entry = [ECSnippetEntry new]; + [self.detailEditor initWithEntry:entry]; self.detailEditor.editMode = DetailEditorModeInsert; [self.detailEditor showWindow:self]; } @@ -151,79 +367,53 @@ - (void)onRemoveEntryClick:(id)sender { NSButton* btn = sender; NSInteger row = [_tableView rowForView:btn]; - EShortcutEntry* entry = _mappingList[row]; - if (entry) { - [_mappingList removeObject:entry]; - [self sortMappingList]; - [_tableView reloadData]; - - [self saveMapping]; - } + + NSAlert* alert = [NSAlert ec_alertWithStyle:NSAlertStyleWarning + messageText:NSLocalizedString(@"Entry_Delete_Message",nil) + informativeText:NSLocalizedString(@"Entry_Delete_Message_Explain",nil) + buttonTitle:NSLocalizedString(@"Button_OK_Title",nil), + NSLocalizedString(@"Button_Cancel_Title",nil), + nil]; + [alert beginSheetModalForWindow:self.window completionHandler:^(NSModalResponse returnCode) { + if (returnCode == NSAlertFirstButtonReturn) { //OK + ECSnippetEntry* snippet = _matchingList[row]; + [self onEntryRemoved:snippet]; + } + }]; + } - (DetailWindowController*)detailEditor { if (_detailEditor == nil) { - self.detailEditor = [[DetailWindowController alloc] initWithWindowNibName:@"DetailWindowController"]; + _detailEditor = [[DetailWindowController alloc] initWithWindowNibName:@"DetailWindowController"]; _detailEditor.delegate = self; } return _detailEditor; } #pragma mark - DetailWindowEditorDelegate -- (void)onEntryInserted:(EShortcutEntry*)entry { - if (entry.key.length > 0 && entry.code.length > 0) { - [_mappingList addObject:entry]; - [self sortMappingList]; - [_tableView reloadData]; - - [self saveMapping]; - } +- (void)snippetsDocument:(ECSnippetDocument*)document performActionWithType:(ECSnippetEntryActionType)actionType withEntry:(ECSnippetEntry*)entry { + [self reloadData]; } -- (void)onEntryUpdated:(EShortcutEntry*)entry { - [self sortMappingList]; - [_tableView reloadData]; - - [self saveMapping]; +#pragma mark - DetailWindowEditorDelegate +- (void)onSnippetInserted:(ECSnippetEntry*)entry { + [_snippetDoc addSnippetEntry:entry]; } -- (void)windowWillClose:(NSNotification *)notification -{ - [self saveMapping]; +- (void)onEntryRemoved:(ECSnippetEntry*)snippet { + [_snippetDoc removeSnippetEntryForKey:snippet.key]; } -#pragma mark - Other -- (void)saveMapping -{ - NSMutableDictionary* newMapping = @{}.mutableCopy; - for (EShortcutEntry* entry in _mappingList) { - [newMapping setObject:entry.code forKey:entry.key]; - } - - if (_editorType == EditorTypeOC) { - [_UD saveMappingForOC:newMapping]; - } - else if(_editorType == EditorTypeSwift) - { - [_UD saveMappingForSwift:newMapping]; +- (void)onSnippetUpdated:(ECSnippetEntry*)snippet { + if ([_detailEditor hasEdited]) { + [_snippetDoc updateSnippetEntry:snippet]; } } -- (void)sortMappingList -{ - if (_mappingList.count == 0) { - EShortcutEntry* testEntry = [EShortcutEntry new]; - testEntry.key = @"key"; - testEntry.code = @"code"; - [_mappingList addObject:testEntry]; - } - - [_mappingList sortUsingComparator:^NSComparisonResult(id _Nonnull obj1, id _Nonnull obj2) { - EShortcutEntry* entry1 = obj1; - EShortcutEntry* entry2 = obj2; - return [entry1.key compare:entry2.key]; - }]; +- (void)windowWillClose:(NSNotification *)notification { + [_snippetDoc saveDocumentCompletionHandler:NULL]; } @end diff --git a/EasyCode/MappingEditor/EditorWindowController.xib b/EasyCode/MappingEditor/EditorWindowController.xib index e2c9945..958b6ef 100644 --- a/EasyCode/MappingEditor/EditorWindowController.xib +++ b/EasyCode/MappingEditor/EditorWindowController.xib @@ -1,14 +1,19 @@ - + - + + + + + + @@ -17,33 +22,31 @@ - - + + - + - - - + + - - - + + - + - - + + - - + + @@ -56,13 +59,13 @@ - + - - + + - + @@ -75,8 +78,8 @@ - - + + @@ -89,13 +92,13 @@ - + - - + + - + @@ -108,8 +111,8 @@ - - + + @@ -122,7 +125,7 @@ - - + + @@ -145,7 +148,7 @@ - - + + @@ -168,7 +171,7 @@ + + + + + + + + + + + + + - - + + @@ -191,15 +207,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/EasyCode/Resource/Localizable.strings b/EasyCode/Resource/Localizable.strings new file mode 100755 index 0000000..7913f5c --- /dev/null +++ b/EasyCode/Resource/Localizable.strings @@ -0,0 +1,13 @@ +// errors +"Search_Failed" = "Failed to start the search for documents in iCloud."; + +// log out alert +"Logged_Out_Message" = "You have been using iCloud, but it has now become unavailable."; +"Logged_Out_Message_Explain" = "Please check your network connection and make sure you are signed in."; +"Button_OK_Title" = "OK"; +"Button_Cancel_Title" = "Cancel"; +"iCloud_Attention" = "Attention"; +"iCloud_Attention_Message" = "This will delete notes from your iCloud account. Are you sure?"; + +"Entry_Delete_Message" = "Delete Entry"; +"Entry_Delete_Message_Explain" = "This will delete entry from your snippets lab. Are you sure?"; diff --git a/EasyCode/SharedLogic/ECDefine.h b/EasyCode/SharedLogic/ECDefine.h new file mode 100644 index 0000000..3180228 --- /dev/null +++ b/EasyCode/SharedLogic/ECDefine.h @@ -0,0 +1,61 @@ +// +// ECDefine.h +// EasyCode +// +// Created by lijia on 07/03/2017. +// Copyright © 2017 music4kid. All rights reserved. +// + +#import +#import "ECSafeCast.h" + +#ifndef ECDefine_H +#define ECDefine_H + +#define kUseiCloudSync @"kUseiCloudSync" +#define kVersionFormat @"%@-version" + +typedef NS_ENUM(NSInteger,ECSourceType) { + ECSourceTypeOC, + ECSourceTypeSwift +}; + +#define _STR(s) [ECSafeCast parseToString:s] +#define _INT(s) [ECSafeCast parseToIntValue:s] +#define _LONG(s) [ECSafeCast parseTolongValue:s] +#define _BOOL(s) [ECSafeCast parseToBOOLValue:s] +#define _FLOAT(s) [ECSafeCast parseToFloatValue:s] +#define _NUMBER(s) [ECSafeCast parseToNumValue:s] +#define _INTEGER(s) [ECSafeCast parseToIntegerValue:s] +#define _LONGLONG(s) [ECSafeCast parseTolongLongValue:s] +#define _DOUBLE(s) [ECSafeCast parseToDoubleValue:s] +#define _ARRAY(s) [ECSafeCast parseToArray:s] +#define _DIC(s) [ECSafeCast parseToDictionary:s] + +#define APP_OBJ [NSApplication sharedApplication] +#define APP_DELEGATE ((AppDelegate *)[APP_OBJ delegate]) + +#ifndef dispatch_main_sync_safe +#define dispatch_main_sync_safe(block)\ +if ([NSThread isMainThread]) {\ +if(block){\ +block();\ +}\ +}\ +else {\ +if(block){\ +dispatch_sync(dispatch_get_main_queue(), block);\ +}\ +} +#endif + +#ifndef dispatch_async_safe +#define dispatch_async_safe(block) \ +dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), block) +#endif + + + +#endif /* ECDefine_H */ + + diff --git a/EasyCode/SharedLogic/ECSnippetHelper.h b/EasyCode/SharedLogic/ECSnippetHelper.h new file mode 100644 index 0000000..14bb8a8 --- /dev/null +++ b/EasyCode/SharedLogic/ECSnippetHelper.h @@ -0,0 +1,20 @@ +// +// ECSnippetHelper.h +// EasyCode +// +// Created by lijia on 07/03/2017. +// Copyright © 2017 music4kid. All rights reserved. +// + +#import +#import "ECSnippet.h" +#import "ECDefine.h" + +@interface ECSnippetHelper : NSObject ++(ECSnippet*)snippetWithFileWrapper:(NSFileWrapper*)fileWrapper; ++(ECSnippet*)snippetWithSourceType:(ECSourceType)sourceType; ++(NSInteger)versionForSourceType:(ECSourceType)sourceType; ++(NSString*)directoryForSourceType:(ECSourceType)sourceType; ++(ECSourceType)sourceTypeForContentUTI:(NSString*)contentUTI; ++(ECSourceType)sourceTypeForDirectory:(NSString*)filename; +@end diff --git a/EasyCode/SharedLogic/ECSnippetHelper.m b/EasyCode/SharedLogic/ECSnippetHelper.m new file mode 100644 index 0000000..f2f3b1d --- /dev/null +++ b/EasyCode/SharedLogic/ECSnippetHelper.m @@ -0,0 +1,100 @@ +// +// ECSnippetHelper.m +// EasyCode +// +// Created by lijia on 07/03/2017. +// Copyright © 2017 music4kid. All rights reserved. +// + +#import "ECSnippetHelper.h" +#import "NSFileManager+Additions.h" +#import "ECMappingForObjectiveC.h" +#import "ECMappingForSwift.h" + +@implementation ECSnippetHelper + ++(ECSourceType)sourceTypeForContentUTI:(NSString*)contentUTI { + if ([contentUTI isEqualToString:@"public.swift-source"]) { + return ECSourceTypeSwift; + } else { + return ECSourceTypeOC; + } +} + ++(NSString*)directoryForSourceType:(ECSourceType)sourceType { + if (sourceType == ECSourceTypeOC) { + return DirectoryOCName; + } else { + return DirectorySwiftName; + } +} + ++(ECSourceType)sourceTypeForDirectory:(NSString*)filename { + if ([filename isEqualToString:DirectoryOCName]) { + return ECSourceTypeOC; + } else { + return ECSourceTypeSwift; + } +} + ++(ECSnippet*)snippetWithFileWrapper:(NSFileWrapper*)fileWrapper { + NSString* filename = [fileWrapper filename]; + NSDictionary *fileWrappers = [fileWrapper fileWrappers]; + NSFileWrapper *snippetWrapper = [fileWrappers objectForKey:SnippetFileName]; + if (snippetWrapper == nil) { //switch ubiquity to local + NSURL* fileURL = [[NSFileManager defaultManager] ec_localSnippetsURLWithFilename:filename]; + fileWrapper = [[NSFileWrapper alloc] initWithURL:fileURL options:NSFileWrapperReadingWithoutMapping error:nil]; + fileWrappers = [fileWrapper fileWrappers]; + snippetWrapper = [fileWrappers objectForKey:SnippetFileName]; + } + NSData* data = [snippetWrapper regularFileContents]; + ECSnippet* snippet = nil; + if ([data length] > 0) { + snippet = [NSKeyedUnarchiver unarchiveObjectWithData:data]; + if(snippet.entries.count==0){ + NSArray* entries = nil; + if ([[fileWrapper filename] isEqualToString:DirectoryOCName]) { + entries = [ECMappingForObjectiveC defaultEntries]; + } else { + entries = [ECMappingForSwift defaultEntries]; + } + ECSourceType sourceType = [self sourceTypeForDirectory:filename]; + snippet = [[ECSnippet alloc] initWithSourceType:sourceType entries:entries]; + } + + } else { //create from memory if local not exist + NSArray* entries = nil; + if ([[fileWrapper filename] isEqualToString:DirectoryOCName]) { + entries = [ECMappingForObjectiveC defaultEntries]; + } else { + entries = [ECMappingForSwift defaultEntries]; + } + ECSourceType sourceType = [self sourceTypeForDirectory:filename]; + snippet = [[ECSnippet alloc] initWithSourceType:sourceType entries:entries]; + } + return snippet; +} + ++(ECSnippet*)snippetWithSourceType:(ECSourceType)sourceType { + NSURL* fileURL = [[NSFileManager defaultManager] ec_detectURLForSourceType:sourceType]; + NSFileWrapper* fileWrapper = [[NSFileWrapper alloc] initWithURL:fileURL + options:NSFileWrapperReadingWithoutMapping + error:nil]; + ECSnippet* snippet = [self snippetWithFileWrapper:fileWrapper]; + return snippet; +} + ++(NSInteger)versionForSourceType:(ECSourceType)sourceType { + NSURL* url = [[NSFileManager defaultManager] ec_detectURLForSourceType:sourceType]; + NSFileWrapper* fileWrapper = [[NSFileWrapper alloc] initWithURL:url options:NSFileWrapperReadingWithoutMapping error:nil]; + NSDictionary *fileWrappers = [fileWrapper fileWrappers]; + NSFileWrapper *versionWrapper = [fileWrappers objectForKey:VersionFileName]; + NSData* data = [versionWrapper regularFileContents]; + NSInteger version = 0; + if ([data length] > 0) { + NSString* verStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + version = [verStr integerValue]; + } + return version; +} +@end diff --git a/EasyCode/SharedLogic/ESharedUserDefault.h b/EasyCode/SharedLogic/ESharedUserDefault.h index 1a4e75b..2f0749f 100644 --- a/EasyCode/SharedLogic/ESharedUserDefault.h +++ b/EasyCode/SharedLogic/ESharedUserDefault.h @@ -8,18 +8,13 @@ #import -#define _UD [ESharedUserDefault sharedInstance] - @interface ESharedUserDefault : NSObject - -+ (instancetype)sharedInstance; - -- (NSDictionary*)readMappingForOC; -- (void)saveMappingForOC:(NSDictionary*)mapping; - -- (NSDictionary*)readMappingForSwift; -- (void)saveMappingForSwift:(NSDictionary*)mapping; - -- (void)clearMapping; - ++ (BOOL)boolForKey:(NSString*)key; ++ (id)objectForKey:(NSString*)key; ++ (id)dataForKey:(NSString*)key; ++ (id)stringForKey:(NSString*)key; + ++ (void)setBool:(BOOL)value forKey:(NSString*)key; ++ (void)setObject:(NSObject*)value forKey:(NSString*)key; ++ (void)setObjects:(NSArray*)values forKeys:(NSArray*)keys; @end diff --git a/EasyCode/SharedLogic/ESharedUserDefault.m b/EasyCode/SharedLogic/ESharedUserDefault.m index cc45970..a1b5126 100644 --- a/EasyCode/SharedLogic/ESharedUserDefault.m +++ b/EasyCode/SharedLogic/ESharedUserDefault.m @@ -10,23 +10,12 @@ #import "ECMappingForObjectiveC.h" #import "ECMappingForSwift.h" -#define KeySharedContainerGroup @"2WQE6AU5PD.group.com.music4kid.easycode" - -#define KeyCodeShortcutForObjectiveC @"KeyCodeShortcutForObjectiveC" -#define KeyCodeShortcutForSwift @"KeyCodeShortcutForSwift" - -#define KeyCurrentUDVersion @"KeyCurrentUDVersion" -#define ValueCurrentUDVersion @"1" +#define KeySharedContainerGroup @"JW95CV255J.group.com.sito.easycode" +#define KeyCurrentUDVersion @"KeyCurrentUDVersion" +#define ValueCurrentUDVersion @"1" @interface ESharedUserDefault () @property (nonatomic, strong) NSUserDefaults* sharedUD; - -@property (nonatomic, strong) NSDictionary* ocMappingDefault; -@property (nonatomic, strong) NSDictionary* swiftMappingDefault; - -@property (nonatomic, strong) NSMutableDictionary* ocMapping; -@property (nonatomic, strong) NSMutableDictionary* swiftMapping; - @end @implementation ESharedUserDefault @@ -37,7 +26,7 @@ + (instancetype)sharedInstance static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ - instance = [ESharedUserDefault new]; + instance = [[ESharedUserDefault alloc] init]; }); return instance; @@ -47,7 +36,6 @@ - (instancetype)init { self = [super init]; if (self) { - [self initSharedUD]; } return self; @@ -55,91 +43,62 @@ - (instancetype)init - (void)initSharedUD { - self.sharedUD = [[NSUserDefaults alloc] initWithSuiteName:KeySharedContainerGroup]; - if ([_sharedUD objectForKey:KeyCurrentUDVersion] == nil) { + _sharedUD = [[NSUserDefaults alloc] initWithSuiteName:KeySharedContainerGroup]; + NSString* UIVersion = [_sharedUD objectForKey:KeyCurrentUDVersion]; + if (UIVersion == nil) { [_sharedUD setObject:ValueCurrentUDVersion forKey:KeyCurrentUDVersion]; } } -- (void)clearMapping ++ (BOOL)boolForKey:(NSString*)key { - _ocMapping = nil; - _swiftMapping = nil; + NSUserDefaults* shareUD = [[ESharedUserDefault sharedInstance] sharedUD]; + return [shareUD boolForKey:key]; } -#pragma mark - Objective-C - -- (NSDictionary*)readMappingForOC ++ (id)objectForKey:(NSString*)key { - if (_ocMapping == nil) { - _ocMapping = [_sharedUD dictionaryForKey:KeyCodeShortcutForObjectiveC].mutableCopy; - - BOOL isMappingEmpty = false; - if (_ocMapping == nil || (_ocMapping.allKeys.count == 1 && [_ocMapping[@"key"] isEqualToString:@"code"])) { - isMappingEmpty = true; - } - - if (isMappingEmpty == true) { - _ocMapping = self.ocMappingDefault.mutableCopy; - [self saveMappingForOC:self.ocMappingDefault]; - } - } - - return _ocMapping; + NSUserDefaults* shareUD = [[ESharedUserDefault sharedInstance] sharedUD]; + return [shareUD objectForKey:key]; } -- (void)saveMappingForOC:(NSDictionary*)mapping -{ - if (mapping.allKeys.count == 0 || mapping.allKeys.count == 1) { - return; - } - self.ocMapping = mapping.mutableCopy; - [_sharedUD setObject:mapping forKey:KeyCodeShortcutForObjectiveC]; - [_sharedUD synchronize]; ++ (id)dataForKey:(NSString*)key { + NSUserDefaults* shareUD = [[ESharedUserDefault sharedInstance] sharedUD]; + return [shareUD dataForKey:key]; } -- (NSDictionary*)ocMappingDefault -{ - if (_ocMappingDefault == nil) { - _ocMappingDefault = [[ECMappingForObjectiveC new] provideMapping]; - } - return _ocMappingDefault; ++ (id)stringForKey:(NSString*)key { + NSUserDefaults* shareUD = [[ESharedUserDefault sharedInstance] sharedUD]; + return [shareUD stringForKey:key]; } -#pragma mark - Swift - -- (NSDictionary*)readMappingForSwift ++ (void)setBool:(BOOL)value forKey:(NSString*)key { - if (_swiftMapping == nil) { - _swiftMapping = [_sharedUD dictionaryForKey:KeyCodeShortcutForSwift].mutableCopy; - - BOOL isMappingEmpty = false; - if (_ocMapping == nil || (_ocMapping.allKeys.count == 1 && [_ocMapping[@"key"] isEqualToString:@"code"])) { - isMappingEmpty = true; - } - - if (isMappingEmpty) { - _swiftMapping = self.swiftMappingDefault.mutableCopy; - [self saveMappingForOC:self.swiftMappingDefault]; - } - } - - return _swiftMapping; + NSUserDefaults* shareUD = [[ESharedUserDefault sharedInstance] sharedUD]; + [shareUD setBool:value forKey:key]; + [shareUD synchronize]; } -- (void)saveMappingForSwift:(NSDictionary*)mapping ++ (void)setObject:(NSObject*)value forKey:(NSString*)key { - self.swiftMapping = mapping.mutableCopy; - [_sharedUD setObject:mapping forKey:KeyCodeShortcutForSwift]; - [_sharedUD synchronize]; + NSUserDefaults* shareUD = [[ESharedUserDefault sharedInstance] sharedUD]; + [shareUD setObject:value forKey:key]; + [shareUD synchronize]; } -- (NSDictionary*)swiftMappingDefault ++ (void)setObjects:(NSArray*)values forKeys:(NSArray*)keys { - if (_swiftMappingDefault == nil) { - _swiftMappingDefault = [[ECMappingForSwift new] provideMapping]; + if (keys.count != values.count) { + return; } - return _swiftMappingDefault; -} + NSUserDefaults* shareUD = [[ESharedUserDefault sharedInstance] sharedUD]; + [keys enumerateObjectsUsingBlock:^(NSString* _Nonnull key, NSUInteger idx, BOOL * _Nonnull stop) { + [shareUD setObject:values[idx] forKey:key]; + }]; + BOOL success = [shareUD synchronize]; + if (!success) { + NSLog(@"synchronize error"); + } +} @end diff --git a/EasyCode/MappingEditor/CustomButton.h b/EasyCode/UI/ECustomButton.h similarity index 72% rename from EasyCode/MappingEditor/CustomButton.h rename to EasyCode/UI/ECustomButton.h index 09b7dc8..7ae26b5 100644 --- a/EasyCode/MappingEditor/CustomButton.h +++ b/EasyCode/UI/ECustomButton.h @@ -1,5 +1,5 @@ // -// CustomButton.h +// ECustomButton.h // EasyCode // // Created by gao feng on 2016/11/4. @@ -8,6 +8,6 @@ #import -@interface CustomButton : NSButton +@interface ECustomButton : NSButton @end diff --git a/EasyCode/MappingEditor/CustomButton.m b/EasyCode/UI/ECustomButton.m similarity index 65% rename from EasyCode/MappingEditor/CustomButton.m rename to EasyCode/UI/ECustomButton.m index c7cf9b6..19da4f8 100644 --- a/EasyCode/MappingEditor/CustomButton.m +++ b/EasyCode/UI/ECustomButton.m @@ -1,19 +1,17 @@ // -// CustomButton.m +// ECustomButton.m // EasyCode // // Created by gao feng on 2016/11/4. // Copyright © 2016年 music4kid. All rights reserved. // -#import "CustomButton.h" +#import "ECustomButton.h" -@implementation CustomButton +@implementation ECustomButton - (void)drawRect:(NSRect)dirtyRect { [super drawRect:dirtyRect]; - - // Drawing code here. } @end diff --git a/EasyCode/UI/EEditorTableMenu.h b/EasyCode/UI/EEditorTableMenu.h new file mode 100644 index 0000000..1b08755 --- /dev/null +++ b/EasyCode/UI/EEditorTableMenu.h @@ -0,0 +1,19 @@ +// +// EEditorTableMenu.h +// EasyCode +// +// Created by lijia on 20/03/2017. +// Copyright © 2017 music4kid. All rights reserved. +// + +#import +@protocol EEditorMenuDelegate; + +@interface EEditorTableMenu : NSMenu +@property (nonatomic, weak) id editorDelegate; +@property (nonatomic, readonly,copy) NSArray* itemsTitle; +@end + +@protocol EEditorMenuDelegate +-(void)menu:(EEditorTableMenu*)menu didSelectedItemWithTag:(NSInteger)tag; +@end diff --git a/EasyCode/UI/EEditorTableMenu.m b/EasyCode/UI/EEditorTableMenu.m new file mode 100644 index 0000000..c276fd7 --- /dev/null +++ b/EasyCode/UI/EEditorTableMenu.m @@ -0,0 +1,41 @@ +// +// EEditorTableMenu.m +// EasyCode +// +// Created by lijia on 20/03/2017. +// Copyright © 2017 music4kid. All rights reserved. +// + +#import "EEditorTableMenu.h" +@interface EEditorTableMenu () + +@end + + +@implementation EEditorTableMenu + +- (instancetype)initWithTitle:(NSString*)title +{ + self = [super initWithTitle:title]; + if (self) { + _itemsTitle = @[@"Edit "]; + NSInteger index = 0; + for (NSString* itemTitle in _itemsTitle) { + NSMenuItem* item = [self addItemWithTitle:itemTitle action:@selector(onMenuItemSelected:) keyEquivalent:@""]; + item.target = self; + item.tag = index++; + } + [self addItem:[NSMenuItem separatorItem]]; + } + return self; +} + +- (void)onMenuItemSelected:(NSMenuItem*)item { + if (_editorDelegate) { + if ([_editorDelegate respondsToSelector:@selector(menu:didSelectedItemWithTag:)]) { + [_editorDelegate menu:self didSelectedItemWithTag:item.tag]; + } + } +} + +@end diff --git a/EasyCode/UI/EEditorTableRowView.h b/EasyCode/UI/EEditorTableRowView.h new file mode 100644 index 0000000..dec4511 --- /dev/null +++ b/EasyCode/UI/EEditorTableRowView.h @@ -0,0 +1,13 @@ +// +// EEditorTableRowView.h +// EasyCode +// +// Created by lijia on 20/03/2017. +// Copyright © 2017 music4kid. All rights reserved. +// + +#import + +@interface EEditorTableRowView : NSTableRowView + +@end diff --git a/EasyCode/UI/EEditorTableRowView.m b/EasyCode/UI/EEditorTableRowView.m new file mode 100644 index 0000000..5d1b151 --- /dev/null +++ b/EasyCode/UI/EEditorTableRowView.m @@ -0,0 +1,22 @@ +// +// EEditorTableRowView.m +// EasyCode +// +// Created by lijia on 20/03/2017. +// Copyright © 2017 music4kid. All rights reserved. +// + +#import "EEditorTableRowView.h" + +@implementation EEditorTableRowView +- (void)drawSelectionInRect:(NSRect)dirtyRect { + if (self.selectionHighlightStyle != NSTableViewSelectionHighlightStyleNone) { + NSRect selectionRect = NSInsetRect(self.bounds, 0, 0); +// [[NSColor colorWithCalibratedWhite:.65 alpha:1.0] setStroke]; + [[NSColor lightGrayColor] setFill]; + NSBezierPath *selectionPath = [NSBezierPath bezierPathWithRoundedRect:selectionRect xRadius:0 yRadius:0]; + [selectionPath fill]; + [selectionPath stroke]; + } +} +@end diff --git a/EasyCode/MappingEditor/EEditorTableView.h b/EasyCode/UI/EEditorTableView.h similarity index 100% rename from EasyCode/MappingEditor/EEditorTableView.h rename to EasyCode/UI/EEditorTableView.h diff --git a/EasyCode/UI/EEditorTableView.m b/EasyCode/UI/EEditorTableView.m new file mode 100644 index 0000000..e176c64 --- /dev/null +++ b/EasyCode/UI/EEditorTableView.m @@ -0,0 +1,27 @@ +// +// EEditorTableView.m +// EasyCode +// +// Created by gao feng on 2016/10/20. +// Copyright © 2016年 music4kid. All rights reserved. +// + +#import "EEditorTableView.h" +#import "EEditorTableMenu.h" + +@implementation EEditorTableView +-(NSMenu*)menuForEvent:(NSEvent*)event { + [[self window] makeFirstResponder:self]; + NSPoint menuPoint = [self convertPoint:[event locationInWindow] fromView:nil]; + NSInteger row = [self rowAtPoint:menuPoint]; + if (row != -1) { + NSIndexSet* indexSet = [NSIndexSet indexSetWithIndex:row]; + [self selectRowIndexes:indexSet byExtendingSelection:NO]; + return [self menu]; + } else { + return [super menu]; + } +} + + +@end diff --git a/EasyCode/MappingEditor/EVerticalScrollView.h b/EasyCode/UI/EVerticalScrollView.h similarity index 100% rename from EasyCode/MappingEditor/EVerticalScrollView.h rename to EasyCode/UI/EVerticalScrollView.h diff --git a/EasyCode/MappingEditor/EVerticalScrollView.m b/EasyCode/UI/EVerticalScrollView.m similarity index 100% rename from EasyCode/MappingEditor/EVerticalScrollView.m rename to EasyCode/UI/EVerticalScrollView.m diff --git a/EasyCode/Utility/ECSafeCast.h b/EasyCode/Utility/ECSafeCast.h new file mode 100644 index 0000000..4fea369 --- /dev/null +++ b/EasyCode/Utility/ECSafeCast.h @@ -0,0 +1,28 @@ +// +// ECSafeCast.h +// EasyCode +// +// Created by li on 10/8/15. +// Copyright © 2015 hh.changhong.com. All rights reserved. +// + +#import + +@interface ECSafeCast : NSObject + ++ (NSString *)parseToString:(id)parse; ++ (float)parseToFloatValue:(id)parse; + ++ (int)parseToIntValue:(id)parse; ++ (long long)parseTolongLongValue:(id)parse; ++ (long)parseTolongValue:(id)parse; ++ (NSInteger)parseToIntegerValue:(id)parse; + ++ (BOOL)parseToBOOLValue:(id)parse; ++ (double)parseToDoubleValue:(id)parse; ++ (NSNumber *)parseToNumValue:(id)parse; ++ (NSArray *)parseToArray:(id)parse; ++ (NSDictionary *)parseToDictionary:(id)parse; + + +@end diff --git a/EasyCode/Utility/ECSafeCast.m b/EasyCode/Utility/ECSafeCast.m new file mode 100644 index 0000000..fb2cfa3 --- /dev/null +++ b/EasyCode/Utility/ECSafeCast.m @@ -0,0 +1,180 @@ +// +// ECSafeCast.m +// testImage +// +// Created by li on 10/8/15. +// Copyright © 2015 hh.changhong.com. All rights reserved. +// + +#import "ECSafeCast.h" + +@implementation ECSafeCast + ++ (NSString *)parseToString:(id)parse +{ + if (!parse) { + return @""; + } + if ([parse isKindOfClass:[NSString class]]) { + return parse; + } + else if([parse isKindOfClass:[NSNumber class]]) + { + return [NSString stringWithFormat:@"%@",parse]; + } + else + return [NSString stringWithFormat:@"%@",parse]; + +} + ++ (NSNumber *)parseToNumValue:(id)parse +{ + if (!parse) { + return @(0); + } + if ([parse isKindOfClass:[NSString class]]) { + return [NSNumber numberWithDouble:[parse doubleValue]]; + } + else if([parse isKindOfClass:[NSNumber class]]) + { + return parse; + } + else + return @(0); +} + + ++ (double)parseToDoubleValue:(id)parse +{ + if (!parse) { + return 0; + } + if ([parse isKindOfClass:[NSString class]]) { + return [(NSString*)parse doubleValue]; + } + else if([parse isKindOfClass:[NSNumber class]]) + { + return [(NSNumber*)parse doubleValue]; + } + else + return 0; +} + + ++ (BOOL)parseToBOOLValue:(id)parse +{ + if (!parse) { + return false; + } + if ([parse isKindOfClass:[NSString class]]) { + return [(NSString*)parse boolValue]; + } + else if([parse isKindOfClass:[NSNumber class]]) + { + return [(NSNumber*)parse boolValue]; + } + else + return false; +} + ++ (NSInteger)parseToIntegerValue:(id)parse +{ + if (!parse) { + return 0; + } + if ([parse isKindOfClass:[NSString class]]) { + return [(NSString*)parse integerValue]; + } + else if([parse isKindOfClass:[NSNumber class]]) + { + return [(NSNumber*)parse integerValue]; + } + else + return 0; +} + ++ (long long)parseTolongLongValue:(id)parse +{ + if (!parse) { + return 0; + } + if ([parse isKindOfClass:[NSString class]]) { + return [(NSString*)parse longLongValue]; + } + else if([parse isKindOfClass:[NSNumber class]]) + { + return [(NSNumber*)parse longLongValue]; + } + else + return 0; +} + ++ (long)parseTolongValue:(id)parse +{ + if (!parse) { + return 0; + } + if ([parse isKindOfClass:[NSString class]]) { + return (long)[(NSString*)parse longLongValue]; + } + else if([parse isKindOfClass:[NSNumber class]]) + { + return [(NSNumber*)parse longValue]; + } + else + return 0; +} + ++ (float)parseToFloatValue:(id)parse +{ + if (!parse) { + return 0; + } + if ([parse isKindOfClass:[NSString class]]) { + return [(NSString*)parse floatValue]; + } + else if([parse isKindOfClass:[NSNumber class]]) + { + return [(NSNumber*)parse floatValue]; + } + else + return 0; +} + ++ (int)parseToIntValue:(id)parse +{ + if (!parse) { + return 0; + } + if ([parse isKindOfClass:[NSString class]]) { + return [(NSString*)parse intValue]; + } + else if([parse isKindOfClass:[NSNumber class]]) + { + return [(NSNumber*)parse intValue]; + } + else + return 0; +} + ++ (NSArray *)parseToArray:(id)parse; +{ + if (!parse) { + return @[]; + } + if ([parse isKindOfClass:[NSArray class]]) { + return parse; + } + else + return @[]; +} + ++ (NSDictionary *)parseToDictionary:(id)parse +{ + if (parse && [parse isKindOfClass:[NSDictionary class]]) { + return parse; + } + return @{}; +} + +@end diff --git a/EasyCode/easycode.pch b/EasyCode/easycode.pch new file mode 100644 index 0000000..1eba6f4 --- /dev/null +++ b/EasyCode/easycode.pch @@ -0,0 +1,20 @@ +// +// easycode.h +// EasyCode +// +// Created by lijia on 03/03/2017. +// Copyright © 2017 music4kid. All rights reserved. +// + +#if defined(__cplusplus) +#define EC_EXTERN extern "C" +#else +#define EC_EXTERN extern +#endif + +#import "ECDefine.h" +#import "AppDelegate.h" +#import "NSString+Additions.h" +#import "NSFileManager+Additions.h" +#import "NSAlert+Additions.h" +#import "ESharedUserDefault.h"