PageRenderTime 42ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/Libraries/cocoascriptmenu/src/CSMScriptMenu.m

https://code.google.com/p/niceplayer/
Objective C | 294 lines | 192 code | 56 blank | 46 comment | 32 complexity | 3da4fcd18dc5abc1b519ddcce6ba256e MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception
  1. /* ***** BEGIN LICENSE BLOCK *****
  2. * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3. *
  4. * The contents of this file are subject to the Mozilla Public License Version
  5. * 1.1 (the "License"); you may not use this file except in compliance with
  6. * the License. You may obtain a copy of the License at
  7. * http://www.mozilla.org/MPL/
  8. *
  9. * Software distributed under the License is distributed on an "AS IS" basis,
  10. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  11. * for the specific language governing rights and limitations under the
  12. * License.
  13. *
  14. * The Original Code is CocoaScriptMenu.
  15. *
  16. * The Initial Developer of the Original Code is
  17. * James Tuley.
  18. * Portions created by the Initial Developer are Copyright (C) 2004-2005
  19. * the Initial Developer. All Rights Reserved.
  20. *
  21. * Contributor(s):
  22. * James Tuley <jay+csm@tuley.name> (Original Author)
  23. * Wil Shipley (Changed way script path is generated - 1/1/07)
  24. *
  25. * Alternatively, the contents of this file may be used under the terms of
  26. * either the GNU General Public License Version 2 or later (the "GPL"), or
  27. * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  28. * in which case the provisions of the GPL or the LGPL are applicable instead
  29. * of those above. If you wish to allow use of your version of this file only
  30. * under the terms of either the GPL or the LGPL, and not to allow others to
  31. * use your version of this file under the terms of the MPL, indicate your
  32. * decision by deleting the provisions above and replace them with the notice
  33. * and other provisions required by the GPL or the LGPL. If you do not delete
  34. * the provisions above, a recipient may use your version of this file under
  35. * the terms of any one of the MPL, the GPL or the LGPL.
  36. *
  37. * ***** END LICENSE BLOCK ***** */
  38. //
  39. // CSMScriptMenu.m
  40. // CocoaScriptMenu
  41. //
  42. // Created by James Tuley on 9/18/05.
  43. // Copyright 2005 James Tuley. All rights reserved.
  44. //
  45. #import "CSMScriptMenu.h"
  46. #import "CSMCommand.h"
  47. #import "CSMFileSubscription.h"
  48. #import "TenThreeCompatibility.h"
  49. void CSMUpdateMenuHandle(FNMessage message,OptionBits flags,void * refcon,FNSubscriptionRef subscription){
  50. if(message == kFNDirectoryModifiedMessage){
  51. [[CSMScriptMenu sharedMenuGenerator] updateScriptMenu];
  52. }
  53. }
  54. @implementation CSMScriptMenu
  55. -(id)init{
  56. if(self = [super init]){
  57. theDelegate = nil;
  58. theMainScriptMenuItem = nil;
  59. thePathSubscriptions = [[NSMutableDictionary alloc] init];
  60. } return self;
  61. }
  62. -(void)setDelagate:(id)aDelegate{
  63. [theDelegate release];
  64. theDelegate = [aDelegate retain];
  65. }
  66. -(id)delegate{
  67. return theDelegate;
  68. }
  69. +(CSMScriptMenu*)sharedMenuGenerator{
  70. static CSMScriptMenu* theSharedMenuGenerator = nil;
  71. if(theSharedMenuGenerator == nil){
  72. theSharedMenuGenerator = [[CSMScriptMenu alloc] init];
  73. }return theSharedMenuGenerator;
  74. }
  75. +(NSMenuItem*)typicalScriptMenuItem{
  76. id tMenuItem = [[NSMenuItem alloc] initWithTitle:@"S" action:NULL keyEquivalent:@""];
  77. [tMenuItem setImage:[[[NSImage alloc] initWithContentsOfFile:[[NSBundle bundleForClass:[self class]] pathForImageResource:@"scripticon"]] autorelease]];
  78. [tMenuItem setSubmenu:[[[NSMenu alloc] init] autorelease]];
  79. return [tMenuItem autorelease];
  80. }
  81. +(void)refreshMenu:(NSMenu*) aMenu withMenuItems:(NSArray*)aMenuItems{
  82. NSEnumerator* tEnum = [[aMenu itemArray] objectEnumerator];
  83. id tItem = nil;
  84. while(tItem = [tEnum nextObject]){
  85. [aMenu removeItem:tItem];
  86. }
  87. tEnum = [aMenuItems objectEnumerator];
  88. tItem = nil;
  89. while(tItem = [tEnum nextObject]){
  90. [aMenu addItem:tItem];
  91. }
  92. }
  93. +(NSArray*)menuItemsForPath:(NSString*)aPath{
  94. NSEnumerator* tEnum = [[[NSFileManager defaultManager] directoryContentsAtPath:aPath] objectEnumerator];
  95. id tPath =nil;
  96. NSMutableArray* tCommandItems = [NSMutableArray array];
  97. while(tPath =[tEnum nextObject]){
  98. if(![tPath hasPrefix:@"."]){
  99. [tCommandItems addObject:[CSMCommand commandWithScriptPath:[aPath stringByAppendingPathComponent:tPath]]];
  100. }
  101. }
  102. [tCommandItems sortUsingSelector:@selector(compare:)];
  103. tEnum = [tCommandItems objectEnumerator];
  104. id tCommand =nil;
  105. NSMutableArray* tMenuItems = [NSMutableArray array];
  106. while(tCommand = [tEnum nextObject]){
  107. [tMenuItems addObject:[tCommand menuItem]];
  108. }
  109. return tMenuItems;
  110. }
  111. -(unsigned int)countOfScripts{
  112. NSArray* tArray = [self scriptLocations];
  113. NSEnumerator* tLocEnum = [tArray objectEnumerator];
  114. NSString* tLoc;
  115. unsigned int tCount = 0;
  116. while(tLoc = [tLocEnum nextObject]){
  117. NSEnumerator* tEnum = [[[NSFileManager defaultManager] subpathsAtPath:tLoc] objectEnumerator];
  118. id tPath =nil;
  119. while(tPath =[tEnum nextObject]){
  120. BOOL tIsDir =NO;
  121. [[NSFileManager defaultManager] fileExistsAtPath:[tLoc stringByAppendingPathComponent:tPath ] isDirectory:&tIsDir];
  122. if(!([[tPath lastPathComponent] hasPrefix:@"."] || tIsDir) ){
  123. tCount++;
  124. }
  125. }
  126. }
  127. return tCount;
  128. }
  129. -(void)updateMenuForScripts:(NSMenu*)aMenu{
  130. NSMutableArray* tTotalMenus = [NSMutableArray array];
  131. [tTotalMenus addObject:[self showScriptFolderMenuItem]];
  132. NSMenuItem* tUpdateMenu = [[[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Update Scripts Menu",@"Update Scripts Menu") action:@selector(updateScriptMenu:) keyEquivalent:@""] autorelease];
  133. [tUpdateMenu setKeyEquivalentModifierMask:NSAlternateKeyMask];
  134. [tUpdateMenu setAlternate:YES];
  135. [tUpdateMenu setTarget:self];
  136. [tTotalMenus addObject:tUpdateMenu];
  137. NSEnumerator* tEnum = [[self scriptLocations] objectEnumerator];
  138. id tPath = nil;
  139. while (tPath = [tEnum nextObject]){
  140. [self createFileSystemSubscriptionForPath:tPath];
  141. NSArray* tDomainItems = [CSMScriptMenu menuItemsForPath:tPath];
  142. if([tDomainItems count] > 0){
  143. [tTotalMenus addObject:[NSMenuItem separatorItem]];
  144. [tTotalMenus addObjectsFromArray:tDomainItems];
  145. }
  146. }
  147. [CSMScriptMenu refreshMenu:aMenu withMenuItems:tTotalMenus];
  148. }
  149. -(IBAction)showScriptsFolder:(id)sender{
  150. [[NSWorkspace sharedWorkspace] openFile:[[self scriptLocations] objectAtIndex:0]];
  151. }
  152. -(IBAction)updateScriptMenu:(id)sender{
  153. [self updateScriptMenu];
  154. }
  155. -(void)createFileSystemSubscriptionForPath:(NSString*)aPath{
  156. if([thePathSubscriptions objectForKey:aPath] == nil){
  157. [thePathSubscriptions setObject:[CSMFileSubscription createForPath:aPath withCallback:CSMUpdateMenuHandle andContext:NULL] forKey:aPath];
  158. }
  159. }
  160. -(void)updateScriptMenu{
  161. id tScriptItems =[self scriptMenuItemOrItems];
  162. if(![tScriptItems isKindOfClass:[NSArray class]])
  163. tScriptItems = [NSArray arrayWithObject:tScriptItems];
  164. NSEnumerator* tEnumerator = [tScriptItems objectEnumerator];
  165. id tScriptItem = nil;
  166. while(tScriptItem = [tEnumerator nextObject]){
  167. if(tScriptItem != nil){
  168. if([tScriptItem respondsToSelector:@selector(submenu)]){
  169. [self updateMenuForScripts:[tScriptItem submenu]];
  170. }else if([tScriptItem respondsToSelector:@selector(menu)]) {
  171. [self updateMenuForScripts:[tScriptItem menu]];
  172. }
  173. }
  174. }
  175. }
  176. -(NSArray*)standardScriptLocations{
  177. NSArray* tAppSupUserPaths= TTCSearchPathForDirectoriesInDomains(TTCApplicationSupportDirectory, NSUserDomainMask,YES);
  178. NSArray* tAppSupPaths= TTCSearchPathForDirectoriesInDomains(TTCApplicationSupportDirectory,NSAllDomainsMask ^ NSUserDomainMask,YES);
  179. NSMutableArray* tGuarenteedUserFirstArray = [NSMutableArray array];
  180. NSString * tASUserPath = [tAppSupUserPaths objectAtIndex:0];
  181. //Wil Shipley change to use process name instead of app name from the bundle, it's certainly more readable and apparently more reliable
  182. tASUserPath = [tASUserPath stringByAppendingPathComponent:[[NSProcessInfo processInfo] processName]];
  183. BOOL tIsDir = NO;
  184. if(![[NSFileManager defaultManager] fileExistsAtPath:tASUserPath isDirectory:&tIsDir]){
  185. [[NSFileManager defaultManager] createDirectoryAtPath:tASUserPath attributes:nil];
  186. }
  187. tASUserPath = [tASUserPath stringByAppendingPathComponent:@"Scripts"];
  188. tIsDir = NO;
  189. if(![[NSFileManager defaultManager] fileExistsAtPath:tASUserPath isDirectory:&tIsDir]){
  190. [[NSFileManager defaultManager] createDirectoryAtPath:tASUserPath attributes:nil];
  191. }
  192. [tGuarenteedUserFirstArray addObjectsFromArray:tAppSupPaths];
  193. NSEnumerator* tEnumerator = [tGuarenteedUserFirstArray objectEnumerator];
  194. id tItem = nil;
  195. NSMutableArray* tPathsThatExist = [NSMutableArray array];
  196. [tPathsThatExist addObject:tASUserPath];
  197. while(tItem = [tEnumerator nextObject]){
  198. //Wil Shipley change to use process name instead of app name from the bundle, it's certainly more readable and apparently more reliable
  199. NSString* tScriptPath = [(NSString*)tItem stringByAppendingPathComponent:[[NSProcessInfo processInfo] processName]];
  200. tScriptPath = [tScriptPath stringByAppendingPathComponent:@"Scripts"];
  201. tIsDir = NO;
  202. if([[NSFileManager defaultManager] fileExistsAtPath:tScriptPath isDirectory:&tIsDir] && tIsDir){
  203. [tPathsThatExist addObject:tScriptPath];
  204. }
  205. }
  206. return tPathsThatExist;
  207. }
  208. -(NSMenuItem*)showScriptFolderMenuItem{
  209. if ( [self delegate] !=nil && [[self delegate] respondsToSelector:@selector(showScriptFolderMenuItem)] )
  210. return [[self delegate] showScriptFolderMenuItem];
  211. NSMenuItem* tMenuItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Open Scripts Folder",@"Open Scripts Folder") action:@selector(showScriptsFolder:) keyEquivalent:@""];
  212. [tMenuItem setTarget:self];
  213. return [tMenuItem autorelease];
  214. }
  215. -(NSArray*)argumentsForShellScripts{
  216. if ( [self delegate] !=nil && [[self delegate] respondsToSelector:@selector(argumentsForShellScripts)] )
  217. return [[self delegate] argumentsForShellScripts];
  218. return nil;
  219. }
  220. -(NSArray*)scriptLocations{
  221. if ( [self delegate] !=nil && [[self delegate] respondsToSelector:@selector(scriptLocations)] )
  222. return [[self delegate] scriptLocations];
  223. return [self standardScriptLocations];
  224. }
  225. -(id)scriptMenuItemOrItems{
  226. if ( [self delegate] !=nil && [[self delegate] respondsToSelector:@selector(scriptMenuItemOrItems)] )
  227. return [[self delegate] scriptMenuItemOrItems];
  228. if(theMainScriptMenuItem == nil){
  229. theMainScriptMenuItem = [[CSMScriptMenu typicalScriptMenuItem] retain];
  230. int tIndex =[[NSApp mainMenu] indexOfItemWithTitle:NSLocalizedString(@"Help",@"Help")];
  231. if(tIndex < 0)
  232. [[NSApp mainMenu] addItem:theMainScriptMenuItem];
  233. else
  234. [[NSApp mainMenu] insertItem:theMainScriptMenuItem atIndex:tIndex];
  235. }
  236. return theMainScriptMenuItem;
  237. }
  238. @end