mirror of
https://github.com/textmate/textmate.git
synced 2026-02-14 16:34:57 -05:00
131 lines
4.3 KiB
Plaintext
131 lines
4.3 KiB
Plaintext
#import "OakOpenWithMenu.h"
|
|
#import "NSMenuItem Additions.h"
|
|
#import "NSMenu Additions.h"
|
|
#import <OakFoundation/NSString Additions.h>
|
|
#import <oak/oak.h>
|
|
#import <oak/CocoaSTL.h>
|
|
#import <text/ctype.h>
|
|
#import <io/path.h>
|
|
|
|
static std::vector< std::pair<NSString*, NSURL*> > ApplicationURLsForPaths (NSSet* paths)
|
|
{
|
|
std::vector< std::pair<NSString*, NSURL*> > res;
|
|
NSMutableSet* defaultApplicationURLs = [NSMutableSet set];
|
|
NSMutableSet* allApplicationURLs = [NSMutableSet set];
|
|
|
|
for(NSString* path in paths)
|
|
{
|
|
NSURL* fileURL = [NSURL fileURLWithPath:path];
|
|
NSArray* applicationURLs = [(NSArray*)LSCopyApplicationURLsForURL((CFURLRef)fileURL, kLSRolesAll) autorelease];
|
|
NSURL* defaultApplicationURL = nil;
|
|
if(noErr == LSGetApplicationForURL((CFURLRef)fileURL, kLSRolesAll, NULL, (CFURLRef*)&defaultApplicationURL))
|
|
{
|
|
if(![applicationURLs containsObject:defaultApplicationURL])
|
|
applicationURLs = [applicationURLs arrayByAddingObject:defaultApplicationURL];
|
|
[defaultApplicationURLs addObject:defaultApplicationURL];
|
|
}
|
|
if(allApplicationURLs.count == 0)
|
|
[allApplicationURLs setSet:[NSSet setWithArray:applicationURLs]];
|
|
else [allApplicationURLs intersectSet:[NSSet setWithArray:applicationURLs]];
|
|
}
|
|
|
|
if(allApplicationURLs.count == 0)
|
|
return res;
|
|
|
|
std::map<std::string, std::map<std::string, NSURL*>, text::less_t> apps;
|
|
for(NSURL* appURL in allApplicationURLs)
|
|
{
|
|
std::string const& appName = path::display_name(appURL.path.UTF8String);
|
|
NSBundle* appBundle = [NSBundle bundleWithPath:appURL.path];
|
|
NSString* appVersion = [appBundle objectForInfoDictionaryKey:@"CFBundleShortVersionString"] ?: ([appBundle objectForInfoDictionaryKey:@"CFBundleVersion"] ?: @"???");
|
|
apps[appName][appVersion.UTF8String] = appURL;
|
|
}
|
|
|
|
NSURL* defaultApplicationURL = defaultApplicationURLs.count == 1 ? defaultApplicationURLs.anyObject : nil;
|
|
iterate(appIter, apps)
|
|
{
|
|
riterate(versIter, appIter->second)
|
|
{
|
|
NSString* appName = [NSString stringWithCxxString:appIter->first];
|
|
NSURL* appURL = versIter->second;
|
|
|
|
if([defaultApplicationURL isEqual:appURL])
|
|
appName = [NSString stringWithFormat:@"%@ (default)", appName];
|
|
|
|
if(appIter->second.size() > 1) // we have more than one version
|
|
appName = [NSString stringWithFormat:@"%@ (%@)", appName, [NSString stringWithCxxString:versIter->first]];
|
|
|
|
res.insert(([defaultApplicationURL isEqual:appURL] ? res.begin() : res.end()), std::make_pair(appName, appURL));
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
|
|
static OakOpenWithMenu* SharedInstance;
|
|
|
|
@implementation OakOpenWithMenu
|
|
+ (id)sharedInstance
|
|
{
|
|
return SharedInstance ?: [[self new] autorelease];
|
|
}
|
|
|
|
- (id)init
|
|
{
|
|
if(SharedInstance)
|
|
[self release];
|
|
else self = SharedInstance = [[super init] retain];
|
|
return SharedInstance;
|
|
}
|
|
|
|
+ (void)addOpenWithMenuForPaths:(NSSet*)paths toMenuItem:(NSMenuItem*)item
|
|
{
|
|
NSMenu* submenu = [[NSMenu new] autorelease];
|
|
[submenu setAutoenablesItems:NO];
|
|
[submenu setDelegate:[OakOpenWithMenu sharedInstance]];
|
|
|
|
[item setRepresentedObject:paths];
|
|
[item setSubmenu:submenu];
|
|
}
|
|
|
|
- (void)menuNeedsUpdate:(NSMenu*)menu
|
|
{
|
|
NSMenuItem* superItem = [menu parentMenuItem];
|
|
if(menu.numberOfItems > 0 || !superItem)
|
|
return;
|
|
|
|
std::vector< std::pair<NSString*, NSURL*> > appURLs = ApplicationURLsForPaths(superItem.representedObject);
|
|
|
|
if(appURLs.empty())
|
|
{
|
|
[[menu addItemWithTitle:@"No Suitable Applications Found" action:@selector(dummy:) keyEquivalent:@""] setEnabled:NO];
|
|
return;
|
|
}
|
|
|
|
iterate(app, appURLs)
|
|
{
|
|
NSMenuItem* menuItem = [menu addItemWithTitle:app->first action:@selector(openWith:) keyEquivalent:@""];
|
|
[menuItem setIconForFile:[app->second path]];
|
|
[menuItem setTarget:self];
|
|
[menuItem setRepresentedObject:app->second];
|
|
}
|
|
|
|
if(appURLs.size() > 1)
|
|
[menu insertItem:[NSMenuItem separatorItem] atIndex:1];
|
|
}
|
|
|
|
- (void)openWith:(id)sender
|
|
{
|
|
NSURL* applicationURL = [sender representedObject];
|
|
NSSet* filePaths = [[[sender menu] parentMenuItem] representedObject];
|
|
|
|
NSMutableArray* fileURLs = [NSMutableArray arrayWithCapacity:filePaths.count];
|
|
for(NSString* filePath in filePaths)
|
|
[fileURLs addObject:[NSURL fileURLWithPath:filePath]];
|
|
[[NSWorkspace sharedWorkspace] openURLs:fileURLs
|
|
withAppBundleIdentifier:[[NSBundle bundleWithPath:applicationURL.path] bundleIdentifier]
|
|
options:0
|
|
additionalEventParamDescriptor:NULL
|
|
launchIdentifiers:NULL];
|
|
}
|
|
@end
|