You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

176 lines
7.0 KiB

//
// SRCommon.m
// ShortcutRecorder
//
// Copyright 2006-2012 Contributors. All rights reserved.
//
// License: BSD
//
// Contributors:
// David Dauer
// Jesper
// Jamie Kirkpatrick
// Andy Kim
// Ilya Kulakov
#import "SRCommon.h"
#import "SRKeyCodeTransformer.h"
NSBundle *SRBundle()
{
static dispatch_once_t onceToken;
static NSBundle *Bundle = nil;
dispatch_once(&onceToken, ^{
Bundle = [NSBundle bundleWithIdentifier:@"com.kulakov.ShortcutRecorder"];
if (!Bundle)
{
// Could be a CocoaPods framework with embedded resources bundle.
// Look up "use_frameworks!" and "resources_bundle" in CocoaPods documentation.
Bundle = [NSBundle bundleWithIdentifier:@"org.cocoapods.ShortcutRecorder"];
if (!Bundle)
{
Class c = NSClassFromString(@"SRRecorderControl");
if (c)
{
Bundle = [NSBundle bundleForClass:c];
}
}
if (Bundle)
{
Bundle = [NSBundle bundleWithPath:[Bundle pathForResource:@"ShortcutRecorder" ofType:@"bundle"]];
}
}
});
if (!Bundle)
{
@throw [NSException exceptionWithName:NSInternalInconsistencyException
reason:@"Unable to find bundle with resources."
userInfo:nil];
}
else
{
return Bundle;
}
}
NSString *SRLoc(NSString *aKey)
{
return NSLocalizedStringFromTableInBundle(aKey, @"ShortcutRecorder", SRBundle(), nil);
}
NSImage *SRImage(NSString *anImageName)
{
if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_6)
return [[NSImage alloc] initByReferencingURL:[SRBundle() URLForImageResource:anImageName]];
else
return [SRBundle() imageForResource:anImageName];
}
NSString *SRReadableStringForCocoaModifierFlagsAndKeyCode(NSEventModifierFlags aModifierFlags, unsigned short aKeyCode)
{
SRKeyCodeTransformer *t = [SRKeyCodeTransformer sharedPlainTransformer];
NSString *c = [t transformedValue:@(aKeyCode)];
return [NSString stringWithFormat:@"%@%@%@%@%@",
(aModifierFlags & NSCommandKeyMask ? SRLoc(@"Command-") : @""),
(aModifierFlags & NSAlternateKeyMask ? SRLoc(@"Option-") : @""),
(aModifierFlags & NSControlKeyMask ? SRLoc(@"Control-") : @""),
(aModifierFlags & NSShiftKeyMask ? SRLoc(@"Shift-") : @""),
c];
}
NSString *SRReadableASCIIStringForCocoaModifierFlagsAndKeyCode(NSEventModifierFlags aModifierFlags, unsigned short aKeyCode)
{
SRKeyCodeTransformer *t = [SRKeyCodeTransformer sharedPlainASCIITransformer];
NSString *c = [t transformedValue:@(aKeyCode)];
return [NSString stringWithFormat:@"%@%@%@%@%@",
(aModifierFlags & NSCommandKeyMask ? SRLoc(@"Command-") : @""),
(aModifierFlags & NSAlternateKeyMask ? SRLoc(@"Option-") : @""),
(aModifierFlags & NSControlKeyMask ? SRLoc(@"Control-") : @""),
(aModifierFlags & NSShiftKeyMask ? SRLoc(@"Shift-") : @""),
c];
}
static BOOL _SRKeyCodeWithFlagsEqualToKeyEquivalentWithFlags(unsigned short aKeyCode,
NSEventModifierFlags aKeyCodeFlags,
NSString *aKeyEquivalent,
NSEventModifierFlags aKeyEquivalentModifierFlags,
SRKeyCodeTransformer *aTransformer)
{
if (!aKeyEquivalent)
return NO;
aKeyCodeFlags &= SRCocoaModifierFlagsMask;
aKeyEquivalentModifierFlags &= SRCocoaModifierFlagsMask;
if (aKeyCodeFlags == aKeyEquivalentModifierFlags)
{
NSString *keyCodeRepresentation = [aTransformer transformedValue:@(aKeyCode)
withImplicitModifierFlags:nil
explicitModifierFlags:@(aKeyCodeFlags)];
return [keyCodeRepresentation isEqual:aKeyEquivalent];
}
else if (!aKeyEquivalentModifierFlags ||
(aKeyCodeFlags & aKeyEquivalentModifierFlags) == aKeyEquivalentModifierFlags)
{
// Some key equivalent modifier flags can be implicitly set by using special unicode characters. E.g. <EFBFBD> insetead of opt-a.
// However all modifier flags explictily set in key equivalent MUST be also set in key code flags.
// E.g. ctrl-<EFBFBD>/ctrl-opt-a and <EFBFBD>/opt-a match this condition, but cmd-<EFBFBD>/ctrl-opt-a doesn't.
NSString *keyCodeRepresentation = [aTransformer transformedValue:@(aKeyCode)
withImplicitModifierFlags:nil
explicitModifierFlags:@(aKeyCodeFlags)];
if ([keyCodeRepresentation isEqual:aKeyEquivalent])
{
// Key code and key equivalent are not equal key code representation matches key equivalent, but modifier flags are not.
return NO;
}
else
{
NSEventModifierFlags possiblyImplicitFlags = aKeyCodeFlags & ~aKeyEquivalentModifierFlags;
keyCodeRepresentation = [aTransformer transformedValue:@(aKeyCode)
withImplicitModifierFlags:@(possiblyImplicitFlags)
explicitModifierFlags:@(aKeyEquivalentModifierFlags)];
return [keyCodeRepresentation isEqual:aKeyEquivalent];
}
}
else
return NO;
}
BOOL SRKeyCodeWithFlagsEqualToKeyEquivalentWithFlags(unsigned short aKeyCode,
NSEventModifierFlags aKeyCodeFlags,
NSString *aKeyEquivalent,
NSEventModifierFlags aKeyEquivalentModifierFlags)
{
BOOL isEqual = _SRKeyCodeWithFlagsEqualToKeyEquivalentWithFlags(aKeyCode,
aKeyCodeFlags,
aKeyEquivalent,
aKeyEquivalentModifierFlags,
[SRKeyCodeTransformer sharedASCIITransformer]);
if (!isEqual)
{
isEqual = _SRKeyCodeWithFlagsEqualToKeyEquivalentWithFlags(aKeyCode,
aKeyCodeFlags,
aKeyEquivalent,
aKeyEquivalentModifierFlags,
[SRKeyCodeTransformer sharedTransformer]);
}
return isEqual;
}