├── .gitignore ├── Classes ├── OMColorFrameView.h ├── OMColorFrameView.m ├── OMColorHelper.h ├── OMColorHelper.m ├── OMPlainColorWell.h └── OMPlainColorWell.m ├── Info.plist ├── OMColorSense.xcodeproj └── project.pbxproj └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | *.xcodeproj/*.pbxuser 3 | *.xcodeproj/*.perspectivev3 4 | *.xcodeproj/xcuserdata 5 | .DS_Store 6 | .swp 7 | ~.nib 8 | .pbxuser 9 | .perspective 10 | *.perspectivev3 11 | *.mode1v3 12 | *.xcworkspacedata 13 | *.xcuserstate 14 | *xcuserdata* 15 | *.xccheckout -------------------------------------------------------------------------------- /Classes/OMColorFrameView.h: -------------------------------------------------------------------------------- 1 | // 2 | // OMColorFrameView.h 3 | // OMColorHelper 4 | // 5 | // Created by Ole Zorn on 09/07/12. 6 | // 7 | // 8 | 9 | #import 10 | 11 | @interface OMColorFrameView : NSView { 12 | 13 | NSColor *_color; 14 | } 15 | 16 | @property (nonatomic, strong) NSColor *color; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /Classes/OMColorFrameView.m: -------------------------------------------------------------------------------- 1 | // 2 | // OMColorFrameView.m 3 | // OMColorHelper 4 | // 5 | // Created by Ole Zorn on 09/07/12. 6 | // 7 | // 8 | 9 | #import "OMColorFrameView.h" 10 | 11 | @implementation OMColorFrameView 12 | 13 | @synthesize color=_color; 14 | 15 | - (void)drawRect:(NSRect)dirtyRect 16 | { 17 | [self.color setStroke]; 18 | [NSBezierPath strokeRect:NSInsetRect(self.bounds, 0.5, 0.5)]; 19 | } 20 | 21 | - (void)setColor:(NSColor *)color 22 | { 23 | if (color != _color) { 24 | _color = color; 25 | [self setNeedsDisplay:YES]; 26 | } 27 | } 28 | 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /Classes/OMColorHelper.h: -------------------------------------------------------------------------------- 1 | // 2 | // OMColorHelper.h 3 | // OMColorHelper 4 | // 5 | // Created by Ole Zorn on 09/07/12. 6 | // 7 | // 8 | 9 | #import 10 | #import 11 | 12 | typedef enum OMColorType { 13 | OMColorTypeNone = 0, 14 | 15 | OMColorTypeUIRGBA, //[UIColor colorWithRed:1.0 green:0.0 blue:0.0 alpha:1.0] 16 | OMColorTypeUIRGBAInit, //[[UIColor alloc] initWithRed:1.0 green:0.0 blue:0.0 alpha:1.0] 17 | OMColorTypeUIWhite, //[UIColor colorWithWhite:0.5 alpha:1.0] 18 | OMColorTypeUIWhiteInit, //[[UIColor alloc] initWithWhite:0.5 alpha:1.0] 19 | OMColorTypeUIConstant, //[UIColor redColor] 20 | 21 | OMColorTypeNSRGBACalibrated, //[NSColor colorWithCalibratedRed:1.0 green:0.0 blue:0.0 alpha:1.0] 22 | OMColorTypeNSRGBADevice, //[NSColor colorWithDeviceRed:1.0 green:0.0 blue:0.0 alpha:1.0] 23 | OMColorTypeNSWhiteCalibrated, //[NSColor colorWithCalibratedWhite:0.5 alpha:1.0] 24 | OMColorTypeNSWhiteDevice, //[NSColor colorWithDeviceWhite:0.5 alpha:1.0] 25 | OMColorTypeNSConstant, //[NSColor redColor] 26 | 27 | } OMColorType; 28 | 29 | BOOL OMColorTypeIsNSColor(OMColorType colorType) { return colorType >= OMColorTypeNSRGBACalibrated; } 30 | 31 | //TODO: Maybe support HSB and CMYK color types... 32 | 33 | @class OMColorFrameView, OMPlainColorWell; 34 | 35 | @interface OMColorHelper : NSObject { 36 | 37 | OMPlainColorWell *_colorWell; 38 | OMColorFrameView *_colorFrameView; 39 | NSRange _selectedColorRange; 40 | OMColorType _selectedColorType; 41 | NSTextView *_textView; 42 | NSDictionary *_constantColorsByName; 43 | 44 | NSRegularExpression *_rgbaUIColorRegex; 45 | NSRegularExpression *_rgbaNSColorRegex; 46 | NSRegularExpression *_whiteNSColorRegex; 47 | NSRegularExpression *_whiteUIColorRegex; 48 | NSRegularExpression *_constantColorRegex; 49 | } 50 | 51 | @property (nonatomic, strong) OMPlainColorWell *colorWell; 52 | @property (nonatomic, strong) OMColorFrameView *colorFrameView; 53 | @property (nonatomic, strong) NSTextView *textView; 54 | @property (nonatomic, assign) NSRange selectedColorRange; 55 | @property (nonatomic, assign) OMColorType selectedColorType; 56 | 57 | - (void)dismissColorWell; 58 | - (void)activateColorHighlighting; 59 | - (void)deactivateColorHighlighting; 60 | - (NSColor *)colorInText:(NSString *)text selectedRange:(NSRange)selectedRange type:(OMColorType *)type matchedRange:(NSRangePointer)matchedRange; 61 | - (NSString *)colorStringForColor:(NSColor *)color withType:(OMColorType)colorType; 62 | - (double)dividedValue:(double)value withDivisorRange:(NSRange)divisorRange inString:(NSString *)text; 63 | 64 | @end 65 | -------------------------------------------------------------------------------- /Classes/OMColorHelper.m: -------------------------------------------------------------------------------- 1 | // 2 | // OMColorHelper.m 3 | // OMColorHelper 4 | // 5 | // Created by Ole Zorn on 09/07/12. 6 | // 7 | // 8 | 9 | #import "OMColorHelper.h" 10 | #import "OMPlainColorWell.h" 11 | #import "OMColorFrameView.h" 12 | 13 | #define kOMColorHelperHighlightingDisabled @"OMColorHelperHighlightingDisabled" 14 | #define kOMColorHelperInsertionMode @"OMColorHelperInsertionMode" 15 | 16 | @implementation OMColorHelper 17 | 18 | @synthesize colorWell=_colorWell, colorFrameView=_colorFrameView, textView=_textView, selectedColorRange=_selectedColorRange, selectedColorType=_selectedColorType; 19 | 20 | #pragma mark - Plugin Initialization 21 | 22 | + (void)pluginDidLoad:(NSBundle *)plugin 23 | { 24 | static id sharedPlugin = nil; 25 | static dispatch_once_t onceToken; 26 | dispatch_once(&onceToken, ^{ 27 | sharedPlugin = [[self alloc] init]; 28 | }); 29 | } 30 | 31 | - (id)init 32 | { 33 | if (self = [super init]) { 34 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidFinishLaunching:) name:NSApplicationDidFinishLaunchingNotification object:nil]; 35 | _selectedColorRange = NSMakeRange(NSNotFound, 0); 36 | _constantColorsByName = [[NSDictionary alloc] initWithObjectsAndKeys: 37 | [[NSColor blackColor] colorUsingColorSpace:[NSColorSpace genericRGBColorSpace]], @"black", 38 | [NSColor darkGrayColor], @"darkGray", 39 | [NSColor lightGrayColor], @"lightGray", 40 | [[NSColor whiteColor] colorUsingColorSpace:[NSColorSpace genericRGBColorSpace]], @"white", 41 | [NSColor grayColor], @"gray", 42 | [NSColor redColor], @"red", 43 | [NSColor greenColor], @"green", 44 | [NSColor blueColor], @"blue", 45 | [NSColor cyanColor], @"cyan", 46 | [NSColor yellowColor], @"yellow", 47 | [NSColor magentaColor], @"magenta", 48 | [NSColor orangeColor], @"orange", 49 | [NSColor purpleColor], @"purple", 50 | [NSColor brownColor], @"brown", 51 | [[NSColor clearColor] colorUsingColorSpace:[NSColorSpace genericRGBColorSpace]], @"clear", nil]; 52 | 53 | _rgbaUIColorRegex = [NSRegularExpression regularExpressionWithPattern:@"(\\[\\s*UIColor\\s+colorWith|\\[\\s*\\[\\s*UIColor\\s+alloc\\]\\s*initWith)Red:\\s*([0-9]*\\.?[0-9]*f?)\\s*(\\/\\s*[0-9]*\\.?[0-9]*f?)?\\s+green:\\s*([0-9]*\\.?[0-9]*f?)\\s*(\\/\\s*[0-9]*\\.?[0-9]*f?)?\\s+blue:\\s*([0-9]*\\.?[0-9]*f?)\\s*(\\/\\s*[0-9]*\\.?[0-9]*f?)?\\s*alpha:\\s*([0-9]*\\.?[0-9]*f?)\\s*(\\/\\s*[0-9]*\\.?[0-9]*f?)?\\s*\\]" options:0 error:NULL]; 54 | _whiteUIColorRegex = [NSRegularExpression regularExpressionWithPattern:@"(\\[\\s*UIColor\\s+colorWith|\\[\\s*\\[\\s*UIColor\\s+alloc\\]\\s*initWith)White:\\s*([0-9]*\\.?[0-9]*f?)\\s*(\\/\\s*[0-9]*\\.?[0-9]*f?)?\\s+alpha:\\s*([0-9]*\\.?[0-9]*f?)\\s*(\\/\\s*[0-9]*\\.?[0-9]*f?)?\\s*\\]" options:0 error:NULL]; 55 | _rgbaNSColorRegex = [NSRegularExpression regularExpressionWithPattern:@"\\[\\s*NSColor\\s+colorWith(Calibrated|Device)Red:\\s*([0-9]*\\.?[0-9]*f?)\\s*(\\/\\s*[0-9]*\\.?[0-9]*f?)?\\s+green:\\s*([0-9]*\\.?[0-9]*f?)\\s*(\\/\\s*[0-9]*\\.?[0-9]*f?)?\\s+blue:\\s*([0-9]*\\.?[0-9]*f?)\\s*(\\/\\s*[0-9]*\\.?[0-9]*f?)?\\s+alpha:\\s*([0-9]*\\.?[0-9]*f?)\\s*(\\/\\s*[0-9]*\\.?[0-9]*f?)?\\s*\\]" options:0 error:NULL]; 56 | _whiteNSColorRegex = [NSRegularExpression regularExpressionWithPattern:@"\\[\\s*NSColor\\s+colorWith(Calibrated|Device)White:\\s*([0-9]*\\.?[0-9]*f?)\\s*(\\/\\s*[0-9]*\\.?[0-9]*f?)?\\s+alpha:\\s*([0-9]*\\.?[0-9]*f?)\\s*(\\/\\s*[0-9]*\\.?[0-9]*f?)?\\s*\\]" options:0 error:NULL]; 57 | _constantColorRegex = [NSRegularExpression regularExpressionWithPattern:@"\\[\\s*(UI|NS)Color\\s+(black|darkGray|lightGray|white|gray|red|green|blue|cyan|yellow|magenta|orange|purple|brown|clear)Color\\s*\\]" options:0 error:NULL]; 58 | } 59 | return self; 60 | } 61 | 62 | - (void)applicationDidFinishLaunching:(NSNotification *)notification 63 | { 64 | NSMenuItem *editMenuItem = [[NSApp mainMenu] itemWithTitle:@"Edit"]; 65 | if (editMenuItem) { 66 | [[editMenuItem submenu] addItem:[NSMenuItem separatorItem]]; 67 | 68 | NSMenuItem *toggleColorHighlightingMenuItem = [[NSMenuItem alloc] initWithTitle:@"Show Colors Under Caret" action:@selector(toggleColorHighlightingEnabled:) keyEquivalent:@""]; 69 | [toggleColorHighlightingMenuItem setTarget:self]; 70 | [[editMenuItem submenu] addItem:toggleColorHighlightingMenuItem]; 71 | 72 | NSMenuItem *colorInsertionModeItem = [[NSMenuItem alloc] initWithTitle:@"Color Insertion Mode" action:nil keyEquivalent:@""]; 73 | NSMenuItem *colorInsertionModeNSItem = [[NSMenuItem alloc] initWithTitle:@"NSColor" action:@selector(selectNSColorInsertionMode:) keyEquivalent:@""]; 74 | [colorInsertionModeNSItem setTarget:self]; 75 | NSMenuItem *colorInsertionModeUIItem = [[NSMenuItem alloc] initWithTitle:@"UIColor" action:@selector(selectUIColorInsertionMode:) keyEquivalent:@""]; 76 | [colorInsertionModeUIItem setTarget:self]; 77 | 78 | NSMenu *colorInsertionModeMenu = [[NSMenu alloc] initWithTitle:@"Color Insertion Mode"]; 79 | [colorInsertionModeItem setSubmenu:colorInsertionModeMenu]; 80 | [[colorInsertionModeItem submenu] addItem:colorInsertionModeUIItem]; 81 | [[colorInsertionModeItem submenu] addItem:colorInsertionModeNSItem]; 82 | [[editMenuItem submenu] addItem:colorInsertionModeItem]; 83 | 84 | NSMenuItem *insertColorMenuItem = [[NSMenuItem alloc] initWithTitle:@"Insert Color..." action:@selector(insertColor:) keyEquivalent:@""]; 85 | [insertColorMenuItem setTarget:self]; 86 | [[editMenuItem submenu] addItem:insertColorMenuItem]; 87 | } 88 | 89 | BOOL highlightingEnabled = ![[NSUserDefaults standardUserDefaults] boolForKey:kOMColorHelperHighlightingDisabled]; 90 | if (highlightingEnabled) { 91 | [self activateColorHighlighting]; 92 | } 93 | } 94 | 95 | #pragma mark - Preferences 96 | 97 | - (BOOL)validateMenuItem:(NSMenuItem *)menuItem 98 | { 99 | if ([menuItem action] == @selector(insertColor:)) { 100 | NSResponder *firstResponder = [[NSApp keyWindow] firstResponder]; 101 | return ([firstResponder isKindOfClass:NSClassFromString(@"DVTSourceTextView")] && [firstResponder isKindOfClass:[NSTextView class]]); 102 | } else if ([menuItem action] == @selector(toggleColorHighlightingEnabled:)) { 103 | BOOL enabled = [[NSUserDefaults standardUserDefaults] boolForKey:kOMColorHelperHighlightingDisabled]; 104 | [menuItem setState:enabled ? NSOffState : NSOnState]; 105 | return YES; 106 | } else if ([menuItem action] == @selector(selectNSColorInsertionMode:)) { 107 | [menuItem setState:[[NSUserDefaults standardUserDefaults] integerForKey:kOMColorHelperInsertionMode] == 1 ? NSOnState : NSOffState]; 108 | } else if ([menuItem action] == @selector(selectUIColorInsertionMode:)) { 109 | [menuItem setState:[[NSUserDefaults standardUserDefaults] integerForKey:kOMColorHelperInsertionMode] == 0 ? NSOnState : NSOffState]; 110 | } 111 | return YES; 112 | } 113 | 114 | - (void)selectNSColorInsertionMode:(id)sender 115 | { 116 | [[NSUserDefaults standardUserDefaults] setInteger:1 forKey:kOMColorHelperInsertionMode]; 117 | } 118 | 119 | - (void)selectUIColorInsertionMode:(id)sender 120 | { 121 | [[NSUserDefaults standardUserDefaults] setInteger:0 forKey:kOMColorHelperInsertionMode]; 122 | } 123 | 124 | - (void)toggleColorHighlightingEnabled:(id)sender 125 | { 126 | BOOL enabled = [[NSUserDefaults standardUserDefaults] boolForKey:kOMColorHelperHighlightingDisabled]; 127 | [[NSUserDefaults standardUserDefaults] setBool:!enabled forKey:kOMColorHelperHighlightingDisabled]; 128 | if (enabled) { 129 | [self activateColorHighlighting]; 130 | } else { 131 | [self deactivateColorHighlighting]; 132 | } 133 | } 134 | 135 | - (void)activateColorHighlighting 136 | { 137 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(selectionDidChange:) name:NSTextViewDidChangeSelectionNotification object:nil]; 138 | if (!self.textView) { 139 | NSResponder *firstResponder = [[NSApp keyWindow] firstResponder]; 140 | if ([firstResponder isKindOfClass:NSClassFromString(@"DVTSourceTextView")] && [firstResponder isKindOfClass:[NSTextView class]]) { 141 | self.textView = (NSTextView *)firstResponder; 142 | } 143 | } 144 | if (self.textView) { 145 | NSNotification *notification = [NSNotification notificationWithName:NSTextViewDidChangeSelectionNotification object:self.textView]; 146 | [self selectionDidChange:notification]; 147 | 148 | } 149 | } 150 | 151 | - (void)deactivateColorHighlighting 152 | { 153 | [[NSNotificationCenter defaultCenter] removeObserver:self name:NSTextViewDidChangeSelectionNotification object:nil]; 154 | [self dismissColorWell]; 155 | //self.textView = nil; 156 | } 157 | 158 | #pragma mark - Color Insertion 159 | 160 | - (void)insertColor:(id)sender 161 | { 162 | if (!self.textView) { 163 | NSResponder *firstResponder = [[NSApp keyWindow] firstResponder]; 164 | if ([firstResponder isKindOfClass:NSClassFromString(@"DVTSourceTextView")] && [firstResponder isKindOfClass:[NSTextView class]]) { 165 | self.textView = (NSTextView *)firstResponder; 166 | } else { 167 | NSBeep(); 168 | return; 169 | } 170 | } 171 | if ([[NSUserDefaults standardUserDefaults] boolForKey:kOMColorHelperHighlightingDisabled]) { 172 | //Inserting a color implicitly activates color highlighting: 173 | [[NSUserDefaults standardUserDefaults] setBool:NO forKey:kOMColorHelperHighlightingDisabled]; 174 | [self activateColorHighlighting]; 175 | } 176 | [self.textView.undoManager beginUndoGrouping]; 177 | NSInteger insertionMode = [[NSUserDefaults standardUserDefaults] integerForKey:kOMColorHelperInsertionMode]; 178 | if (insertionMode == 0) { 179 | [self.textView insertText:@"[UIColor colorWithRed:1.0 green:0.0 blue:0.0 alpha:1.0]" replacementRange:self.textView.selectedRange]; 180 | } else { 181 | [self.textView insertText:@"[NSColor colorWithCalibratedRed:1.0 green:0.0 blue:0.0 alpha:1.0]" replacementRange:self.textView.selectedRange]; 182 | } 183 | [self.textView.undoManager endUndoGrouping]; 184 | [self performSelector:@selector(activateColorWell) withObject:nil afterDelay:0.0]; 185 | } 186 | 187 | - (void)activateColorWell 188 | { 189 | [self.colorWell activate:YES]; 190 | } 191 | 192 | #pragma mark - Text Selection Handling 193 | 194 | - (void)selectionDidChange:(NSNotification *)notification 195 | { 196 | if ([[notification object] isKindOfClass:NSClassFromString(@"DVTSourceTextView")] && [[notification object] isKindOfClass:[NSTextView class]]) { 197 | self.textView = (NSTextView *)[notification object]; 198 | 199 | BOOL disabled = [[NSUserDefaults standardUserDefaults] boolForKey:kOMColorHelperHighlightingDisabled]; 200 | if (disabled) return; 201 | 202 | NSArray *selectedRanges = [self.textView selectedRanges]; 203 | if (selectedRanges.count >= 1) { 204 | NSRange selectedRange = [[selectedRanges objectAtIndex:0] rangeValue]; 205 | NSString *text = self.textView.textStorage.string; 206 | NSRange lineRange = [text lineRangeForRange:selectedRange]; 207 | NSRange selectedRangeInLine = NSMakeRange(selectedRange.location - lineRange.location, selectedRange.length); 208 | NSString *line = [text substringWithRange:lineRange]; 209 | 210 | NSRange colorRange = NSMakeRange(NSNotFound, 0); 211 | OMColorType colorType = OMColorTypeNone; 212 | NSColor *matchedColor = [self colorInText:line selectedRange:selectedRangeInLine type:&colorType matchedRange:&colorRange]; 213 | 214 | if (matchedColor) { 215 | NSColor *backgroundColor = [self.textView.backgroundColor colorUsingColorSpace:[NSColorSpace genericRGBColorSpace]]; 216 | CGFloat r = 1.0; CGFloat g = 1.0; CGFloat b = 1.0; 217 | [backgroundColor getRed:&r green:&g blue:&b alpha:NULL]; 218 | CGFloat backgroundLuminance = (r + g + b) / 3.0; 219 | 220 | NSColor *strokeColor = (backgroundLuminance > 0.5) ? [NSColor colorWithCalibratedWhite:0.2 alpha:1.0] : [NSColor whiteColor]; 221 | 222 | self.selectedColorType = colorType; 223 | self.colorWell.color = matchedColor; 224 | self.colorWell.strokeColor = strokeColor; 225 | 226 | self.selectedColorRange = NSMakeRange(colorRange.location + lineRange.location, colorRange.length); 227 | NSRect selectionRectOnScreen = [self.textView firstRectForCharacterRange:self.selectedColorRange]; 228 | NSRect selectionRectInWindow = [self.textView.window convertRectFromScreen:selectionRectOnScreen]; 229 | NSRect selectionRectInView = [self.textView convertRect:selectionRectInWindow fromView:nil]; 230 | NSRect colorWellRect = NSMakeRect(NSMaxX(selectionRectInView) - 49, NSMinY(selectionRectInView) - selectionRectInView.size.height - 2, 50, selectionRectInView.size.height + 2); 231 | self.colorWell.frame = NSIntegralRect(colorWellRect); 232 | [self.textView addSubview:self.colorWell]; 233 | self.colorFrameView.frame = NSInsetRect(NSIntegralRect(selectionRectInView), -1, -1); 234 | 235 | self.colorFrameView.color = strokeColor; 236 | 237 | [self.textView addSubview:self.colorFrameView]; 238 | } else { 239 | [self dismissColorWell]; 240 | } 241 | } else { 242 | [self dismissColorWell]; 243 | } 244 | } 245 | } 246 | 247 | - (void)dismissColorWell 248 | { 249 | if (self.colorWell.isActive) { 250 | [self.colorWell deactivate]; 251 | [[NSColorPanel sharedColorPanel] orderOut:nil]; 252 | } 253 | [self.colorWell removeFromSuperview]; 254 | [self.colorFrameView removeFromSuperview]; 255 | self.selectedColorRange = NSMakeRange(NSNotFound, 0); 256 | self.selectedColorType = OMColorTypeNone; 257 | } 258 | 259 | - (void)colorDidChange:(id)sender 260 | { 261 | if (self.selectedColorRange.location == NSNotFound) { 262 | return; 263 | } 264 | NSString *colorString = [self colorStringForColor:self.colorWell.color withType:self.selectedColorType]; 265 | if (colorString) { 266 | [self.textView.undoManager beginUndoGrouping]; 267 | [self.textView insertText:colorString replacementRange:self.selectedColorRange]; 268 | [self.textView.undoManager endUndoGrouping]; 269 | } 270 | } 271 | 272 | #pragma mark - View Initialization 273 | 274 | - (OMPlainColorWell *)colorWell 275 | { 276 | if (!_colorWell) { 277 | _colorWell = [[OMPlainColorWell alloc] initWithFrame:NSMakeRect(0, 0, 50, 30)]; 278 | [_colorWell setTarget:self]; 279 | [_colorWell setAction:@selector(colorDidChange:)]; 280 | } 281 | return _colorWell; 282 | } 283 | 284 | - (OMColorFrameView *)colorFrameView 285 | { 286 | if (!_colorFrameView) { 287 | _colorFrameView = [[OMColorFrameView alloc] initWithFrame:NSZeroRect]; 288 | } 289 | return _colorFrameView; 290 | } 291 | 292 | #pragma mark - Color String Parsing 293 | 294 | - (NSColor *)colorInText:(NSString *)text selectedRange:(NSRange)selectedRange type:(OMColorType *)type matchedRange:(NSRangePointer)matchedRange 295 | { 296 | __block NSColor *foundColor = nil; 297 | __block NSRange foundColorRange = NSMakeRange(NSNotFound, 0); 298 | __block OMColorType foundColorType = OMColorTypeNone; 299 | 300 | [_rgbaUIColorRegex enumerateMatchesInString:text options:0 range:NSMakeRange(0, text.length) usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) { 301 | NSRange colorRange = [result range]; 302 | if (selectedRange.location >= colorRange.location && NSMaxRange(selectedRange) <= NSMaxRange(colorRange)) { 303 | NSString *typeIndicator = [text substringWithRange:[result rangeAtIndex:1]]; 304 | if ([typeIndicator rangeOfString:@"init"].location != NSNotFound) { 305 | foundColorType = OMColorTypeUIRGBAInit; 306 | } else { 307 | foundColorType = OMColorTypeUIRGBA; 308 | } 309 | 310 | // [UIColor colorWithRed:128 / 255.0 green:10 / 255 blue:123/255 alpha:128 /255] 311 | 312 | double red = [[text substringWithRange:[result rangeAtIndex:2]] doubleValue]; 313 | red = [self dividedValue:red withDivisorRange:[result rangeAtIndex:3] inString:text]; 314 | 315 | double green = [[text substringWithRange:[result rangeAtIndex:4]] doubleValue]; 316 | green = [self dividedValue:green withDivisorRange:[result rangeAtIndex:5] inString:text]; 317 | 318 | double blue = [[text substringWithRange:[result rangeAtIndex:6]] doubleValue]; 319 | blue = [self dividedValue:blue withDivisorRange:[result rangeAtIndex:7] inString:text]; 320 | 321 | double alpha = [[text substringWithRange:[result rangeAtIndex:8]] doubleValue]; 322 | alpha = [self dividedValue:alpha withDivisorRange:[result rangeAtIndex:9] inString:text]; 323 | 324 | foundColor = [NSColor colorWithCalibratedRed:red green:green blue:blue alpha:alpha]; 325 | foundColorRange = colorRange; 326 | *stop = YES; 327 | } 328 | }]; 329 | 330 | if (!foundColor) { 331 | [_whiteUIColorRegex enumerateMatchesInString:text options:0 range:NSMakeRange(0, text.length) usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) { 332 | NSRange colorRange = [result range]; 333 | if (selectedRange.location >= colorRange.location && NSMaxRange(selectedRange) <= NSMaxRange(colorRange)) { 334 | NSString *typeIndicator = [text substringWithRange:[result rangeAtIndex:1]]; 335 | if ([typeIndicator rangeOfString:@"init"].location != NSNotFound) { 336 | foundColorType = OMColorTypeUIWhiteInit; 337 | } else { 338 | foundColorType = OMColorTypeUIWhite; 339 | } 340 | double white = [[text substringWithRange:[result rangeAtIndex:2]] doubleValue]; 341 | white = [self dividedValue:white withDivisorRange:[result rangeAtIndex:3] inString:text]; 342 | 343 | double alpha = [[text substringWithRange:[result rangeAtIndex:4]] doubleValue]; 344 | alpha = [self dividedValue:alpha withDivisorRange:[result rangeAtIndex:5] inString:text]; 345 | 346 | foundColor = [NSColor colorWithCalibratedWhite:white alpha:alpha]; 347 | foundColorRange = colorRange; 348 | *stop = YES; 349 | } 350 | }]; 351 | } 352 | 353 | if (!foundColor) { 354 | [_constantColorRegex enumerateMatchesInString:text options:0 range:NSMakeRange(0, text.length) usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) { 355 | NSRange colorRange = [result range]; 356 | if (selectedRange.location >= colorRange.location && NSMaxRange(selectedRange) <= NSMaxRange(colorRange)) { 357 | NSString *NS_UI = [text substringWithRange:[result rangeAtIndex:1]]; 358 | NSString *colorName = [text substringWithRange:[result rangeAtIndex:2]]; 359 | foundColor = [_constantColorsByName objectForKey:colorName]; 360 | foundColorRange = colorRange; 361 | if ([NS_UI isEqualToString:@"UI"]) { 362 | foundColorType = OMColorTypeUIConstant; 363 | } else { 364 | foundColorType = OMColorTypeNSConstant; 365 | } 366 | *stop = YES; 367 | } 368 | }]; 369 | } 370 | 371 | if (!foundColor) { 372 | [_rgbaNSColorRegex enumerateMatchesInString:text options:0 range:NSMakeRange(0, text.length) usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) { 373 | NSRange colorRange = [result range]; 374 | if (selectedRange.location >= colorRange.location && NSMaxRange(selectedRange) <= NSMaxRange(colorRange)) { 375 | NSString *deviceOrCalibrated = [text substringWithRange:[result rangeAtIndex:1]]; 376 | if ([deviceOrCalibrated isEqualToString:@"Device"]) { 377 | foundColorType = OMColorTypeNSRGBADevice; 378 | } else { 379 | foundColorType = OMColorTypeNSRGBACalibrated; 380 | } 381 | double red = [[text substringWithRange:[result rangeAtIndex:2]] doubleValue]; 382 | red = [self dividedValue:red withDivisorRange:[result rangeAtIndex:3] inString:text]; 383 | 384 | double green = [[text substringWithRange:[result rangeAtIndex:4]] doubleValue]; 385 | green = [self dividedValue:green withDivisorRange:[result rangeAtIndex:5] inString:text]; 386 | 387 | double blue = [[text substringWithRange:[result rangeAtIndex:6]] doubleValue]; 388 | blue = [self dividedValue:blue withDivisorRange:[result rangeAtIndex:7] inString:text]; 389 | 390 | double alpha = [[text substringWithRange:[result rangeAtIndex:8]] doubleValue]; 391 | alpha = [self dividedValue:alpha withDivisorRange:[result rangeAtIndex:9] inString:text]; 392 | 393 | if (foundColorType == OMColorTypeNSRGBACalibrated) { 394 | foundColor = [NSColor colorWithCalibratedRed:red green:green blue:blue alpha:alpha]; 395 | } else { 396 | foundColor = [NSColor colorWithDeviceRed:red green:green blue:blue alpha:alpha]; 397 | } 398 | foundColorRange = colorRange; 399 | *stop = YES; 400 | } 401 | }]; 402 | } 403 | 404 | if (!foundColor) { 405 | [_whiteNSColorRegex enumerateMatchesInString:text options:0 range:NSMakeRange(0, text.length) usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) { 406 | NSRange colorRange = [result range]; 407 | if (selectedRange.location >= colorRange.location && NSMaxRange(selectedRange) <= NSMaxRange(colorRange)) { 408 | NSString *deviceOrCalibrated = [text substringWithRange:[result rangeAtIndex:1]]; 409 | double white = [[text substringWithRange:[result rangeAtIndex:2]] doubleValue]; 410 | white = [self dividedValue:white withDivisorRange:[result rangeAtIndex:3] inString:text]; 411 | 412 | double alpha = [[text substringWithRange:[result rangeAtIndex:4]] doubleValue]; 413 | alpha = [self dividedValue:alpha withDivisorRange:[result rangeAtIndex:5] inString:text]; 414 | 415 | if ([deviceOrCalibrated isEqualToString:@"Device"]) { 416 | foundColor = [NSColor colorWithDeviceWhite:white alpha:alpha]; 417 | foundColorType = OMColorTypeNSWhiteDevice; 418 | } else { 419 | foundColor = [NSColor colorWithCalibratedWhite:white alpha:alpha]; 420 | foundColorType = OMColorTypeNSWhiteCalibrated; 421 | } 422 | foundColorRange = colorRange; 423 | *stop = YES; 424 | } 425 | }]; 426 | } 427 | 428 | if (foundColor) { 429 | if (matchedRange != NULL) { 430 | *matchedRange = foundColorRange; 431 | } 432 | if (type != NULL) { 433 | *type = foundColorType; 434 | } 435 | return foundColor; 436 | } 437 | 438 | return nil; 439 | } 440 | 441 | - (double)dividedValue:(double)value withDivisorRange:(NSRange)divisorRange inString:(NSString *)text 442 | { 443 | if (divisorRange.location != NSNotFound) { 444 | double divisor = [[[text substringWithRange:divisorRange] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"/ "]] doubleValue]; 445 | if (divisor != 0) { 446 | value /= divisor; 447 | } 448 | } 449 | return value; 450 | } 451 | 452 | - (NSString *)colorStringForColor:(NSColor *)color withType:(OMColorType)colorType 453 | { 454 | NSString *colorString = nil; 455 | CGFloat red = -1.0; CGFloat green = -1.0; CGFloat blue = -1.0; CGFloat alpha = -1.0; 456 | color = [color colorUsingColorSpace:[NSColorSpace genericRGBColorSpace]]; 457 | [color getRed:&red green:&green blue:&blue alpha:&alpha]; 458 | 459 | if (red >= 0) { 460 | for (NSString *colorName in _constantColorsByName) { 461 | NSColor *constantColor = [_constantColorsByName objectForKey:colorName]; 462 | if ([constantColor isEqual:color]) { 463 | if (OMColorTypeIsNSColor(colorType)) { 464 | colorString = [NSString stringWithFormat:@"[NSColor %@Color]", colorName]; 465 | } else { 466 | colorString = [NSString stringWithFormat:@"[UIColor %@Color]", colorName]; 467 | } 468 | break; 469 | } 470 | } 471 | if (!colorString) { 472 | if (fabs(red - green) < 0.001 && fabs(green - blue) < 0.001) { 473 | if (colorType == OMColorTypeUIRGBA || colorType == OMColorTypeUIWhite || colorType == OMColorTypeUIConstant) { 474 | colorString = [NSString stringWithFormat:@"[UIColor colorWithWhite:%.3f alpha:%.3f]", red, alpha]; 475 | } else if (colorType == OMColorTypeUIRGBAInit || colorType == OMColorTypeUIWhiteInit) { 476 | colorString = [NSString stringWithFormat:@"[[UIColor alloc] initWithWhite:%.3f alpha:%.3f]", red, alpha]; 477 | } 478 | else if (colorType == OMColorTypeNSConstant || colorType == OMColorTypeNSRGBACalibrated || colorType == OMColorTypeNSWhiteCalibrated) { 479 | colorString = [NSString stringWithFormat:@"[NSColor colorWithCalibratedWhite:%.3f alpha:%.3f]", red, alpha]; 480 | } else if (colorType == OMColorTypeNSRGBADevice || colorType == OMColorTypeNSWhiteDevice) { 481 | colorString = [NSString stringWithFormat:@"[NSColor colorWithDeviceWhite:%.3f alpha:%.3f]", red, alpha]; 482 | } 483 | } else { 484 | if (colorType == OMColorTypeUIRGBA || colorType == OMColorTypeUIWhite || colorType == OMColorTypeUIConstant) { 485 | colorString = [NSString stringWithFormat:@"[UIColor colorWithRed:%.3f green:%.3f blue:%.3f alpha:%.3f]", red, green, blue, alpha]; 486 | } else if (colorType == OMColorTypeUIRGBAInit || colorType == OMColorTypeUIWhiteInit) { 487 | colorString = [NSString stringWithFormat:@"[[UIColor alloc] initWithRed:%.3f green:%.3f blue:%.3f alpha:%.3f]", red, green, blue, alpha]; 488 | } 489 | else if (colorType == OMColorTypeNSConstant || colorType == OMColorTypeNSRGBACalibrated || colorType == OMColorTypeNSWhiteCalibrated) { 490 | colorString = [NSString stringWithFormat:@"[NSColor colorWithCalibratedRed:%.3f green:%.3f blue:%.3f alpha:%.3f]", red, green, blue, alpha]; 491 | } else if (colorType == OMColorTypeNSRGBADevice || colorType == OMColorTypeNSWhiteDevice) { 492 | colorString = [NSString stringWithFormat:@"[NSColor colorWithDeviceRed:%.3f green:%.3f blue:%.3f alpha:%.3f]", red, green, blue, alpha]; 493 | } 494 | } 495 | } 496 | } 497 | return colorString; 498 | } 499 | 500 | #pragma mark - 501 | 502 | - (void)dealloc 503 | { 504 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 505 | } 506 | 507 | @end 508 | -------------------------------------------------------------------------------- /Classes/OMPlainColorWell.h: -------------------------------------------------------------------------------- 1 | // 2 | // OMPlainColorWell.h 3 | // OMColorHelper 4 | // 5 | // Created by Ole Zorn on 09/07/12. 6 | // 7 | // 8 | 9 | #import 10 | 11 | @interface OMPlainColorWell : NSColorWell { 12 | 13 | NSColor *_strokeColor; 14 | } 15 | 16 | @property (nonatomic, strong) NSColor *strokeColor; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /Classes/OMPlainColorWell.m: -------------------------------------------------------------------------------- 1 | // 2 | // OMPlainColorWell.m 3 | // OMColorHelper 4 | // 5 | // Created by Ole Zorn on 09/07/12. 6 | // 7 | // 8 | 9 | #import "OMPlainColorWell.h" 10 | 11 | @implementation OMPlainColorWell 12 | 13 | @synthesize strokeColor=_strokeColor; 14 | 15 | - (void)drawRect:(NSRect)dirtyRect 16 | { 17 | [NSGraphicsContext saveGraphicsState]; 18 | NSBezierPath *path = [NSBezierPath bezierPathWithRoundedRect:NSMakeRect(0, -5, self.bounds.size.width, self.bounds.size.height + 5) xRadius:5.0 yRadius:5.0]; 19 | [path addClip]; 20 | [self drawWellInside:self.bounds]; 21 | [NSGraphicsContext restoreGraphicsState]; 22 | 23 | if (self.strokeColor) { 24 | NSBezierPath *strokePath = [NSBezierPath bezierPathWithRoundedRect:NSInsetRect(NSMakeRect(0, -5, self.bounds.size.width, self.bounds.size.height + 5), 0.5, 0.5) xRadius:5.0 yRadius:5.0]; 25 | [self.strokeColor setStroke]; 26 | [strokePath stroke]; 27 | } 28 | } 29 | 30 | - (void)deactivate 31 | { 32 | [super deactivate]; 33 | [[NSColorPanel sharedColorPanel] orderOut:nil]; 34 | } 35 | 36 | - (void)setStrokeColor:(NSColor *)strokeColor 37 | { 38 | if (strokeColor != _strokeColor) { 39 | _strokeColor = strokeColor; 40 | [self setNeedsDisplay:YES]; 41 | } 42 | } 43 | 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | com.omz-software.${PRODUCT_NAME:identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | ${CURRENT_PROJECT_VERSION} 19 | CFBundleVersion 20 | ${CURRENT_PROJECT_VERSION} 21 | NSPrincipalClass 22 | OMColorHelper 23 | XCGCReady 24 | 25 | XCPluginHasUI 26 | 27 | XC4Compatible 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /OMColorSense.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 7F2EB89C145057F200E97A87 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7F2EB899145057EA00E97A87 /* AppKit.framework */; }; 11 | 7F6EE2BF15FA6F3B00BA114A /* OMColorFrameView.m in Sources */ = {isa = PBXBuildFile; fileRef = 7F6EE2BE15FA6F3B00BA114A /* OMColorFrameView.m */; }; 12 | 7FDADE3A15FA6CA400A847E3 /* OMPlainColorWell.m in Sources */ = {isa = PBXBuildFile; fileRef = 7FDADE3915FA6CA400A847E3 /* OMPlainColorWell.m */; }; 13 | DA1B5D020E64686800921439 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 089C1672FE841209C02AAC07 /* Foundation.framework */; }; 14 | DA37E2DC0E6291C8001BDFEF /* OMColorHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = DA37E2DB0E6291C8001BDFEF /* OMColorHelper.m */; }; 15 | /* End PBXBuildFile section */ 16 | 17 | /* Begin PBXFileReference section */ 18 | 089C1672FE841209C02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = ""; }; 19 | 7F2B355F15FA59D000DB3249 /* OMColorHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OMColorHelper.h; sourceTree = ""; }; 20 | 7F2EB899145057EA00E97A87 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; 21 | 7F6EE2BD15FA6F3B00BA114A /* OMColorFrameView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OMColorFrameView.h; sourceTree = ""; }; 22 | 7F6EE2BE15FA6F3B00BA114A /* OMColorFrameView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OMColorFrameView.m; sourceTree = ""; }; 23 | 7FDADE3815FA6CA400A847E3 /* OMPlainColorWell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OMPlainColorWell.h; sourceTree = ""; }; 24 | 7FDADE3915FA6CA400A847E3 /* OMPlainColorWell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OMPlainColorWell.m; sourceTree = ""; }; 25 | 8D5B49B6048680CD000E48DA /* OMColorSense.xcplugin */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = OMColorSense.xcplugin; sourceTree = BUILT_PRODUCTS_DIR; }; 26 | 8D5B49B7048680CD000E48DA /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 27 | DA37E2DB0E6291C8001BDFEF /* OMColorHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OMColorHelper.m; sourceTree = ""; }; 28 | /* End PBXFileReference section */ 29 | 30 | /* Begin PBXFrameworksBuildPhase section */ 31 | 8D5B49B3048680CD000E48DA /* Frameworks */ = { 32 | isa = PBXFrameworksBuildPhase; 33 | buildActionMask = 2147483647; 34 | files = ( 35 | DA1B5D020E64686800921439 /* Foundation.framework in Frameworks */, 36 | 7F2EB89C145057F200E97A87 /* AppKit.framework in Frameworks */, 37 | ); 38 | runOnlyForDeploymentPostprocessing = 0; 39 | }; 40 | /* End PBXFrameworksBuildPhase section */ 41 | 42 | /* Begin PBXGroup section */ 43 | 089C166AFE841209C02AAC07 /* QuietXcode */ = { 44 | isa = PBXGroup; 45 | children = ( 46 | 7F411B0C15FABAC6002F77B6 /* Classes */, 47 | 089C167CFE841241C02AAC07 /* Resources */, 48 | 089C1671FE841209C02AAC07 /* Frameworks and Libraries */, 49 | 19C28FB8FE9D52D311CA2CBB /* Products */, 50 | ); 51 | name = QuietXcode; 52 | sourceTree = ""; 53 | }; 54 | 089C1671FE841209C02AAC07 /* Frameworks and Libraries */ = { 55 | isa = PBXGroup; 56 | children = ( 57 | 7F2EB899145057EA00E97A87 /* AppKit.framework */, 58 | 089C1672FE841209C02AAC07 /* Foundation.framework */, 59 | ); 60 | name = "Frameworks and Libraries"; 61 | sourceTree = ""; 62 | }; 63 | 089C167CFE841241C02AAC07 /* Resources */ = { 64 | isa = PBXGroup; 65 | children = ( 66 | 8D5B49B7048680CD000E48DA /* Info.plist */, 67 | ); 68 | name = Resources; 69 | sourceTree = ""; 70 | }; 71 | 19C28FB8FE9D52D311CA2CBB /* Products */ = { 72 | isa = PBXGroup; 73 | children = ( 74 | 8D5B49B6048680CD000E48DA /* OMColorSense.xcplugin */, 75 | ); 76 | name = Products; 77 | sourceTree = ""; 78 | }; 79 | 7F411B0C15FABAC6002F77B6 /* Classes */ = { 80 | isa = PBXGroup; 81 | children = ( 82 | 7F2B355F15FA59D000DB3249 /* OMColorHelper.h */, 83 | DA37E2DB0E6291C8001BDFEF /* OMColorHelper.m */, 84 | 7F6EE2BD15FA6F3B00BA114A /* OMColorFrameView.h */, 85 | 7F6EE2BE15FA6F3B00BA114A /* OMColorFrameView.m */, 86 | 7FDADE3815FA6CA400A847E3 /* OMPlainColorWell.h */, 87 | 7FDADE3915FA6CA400A847E3 /* OMPlainColorWell.m */, 88 | ); 89 | path = Classes; 90 | sourceTree = ""; 91 | }; 92 | /* End PBXGroup section */ 93 | 94 | /* Begin PBXNativeTarget section */ 95 | 8D5B49AC048680CD000E48DA /* OMColorSense */ = { 96 | isa = PBXNativeTarget; 97 | buildConfigurationList = 1DEB913A08733D840010E9CD /* Build configuration list for PBXNativeTarget "OMColorSense" */; 98 | buildPhases = ( 99 | 7F1DE9FB1B10AF0900B6CBA8 /* ShellScript */, 100 | 8D5B49B1048680CD000E48DA /* Sources */, 101 | 8D5B49B3048680CD000E48DA /* Frameworks */, 102 | ); 103 | buildRules = ( 104 | ); 105 | dependencies = ( 106 | ); 107 | name = OMColorSense; 108 | productInstallPath = "$(HOME)/Library/Bundles"; 109 | productName = QuietXcode; 110 | productReference = 8D5B49B6048680CD000E48DA /* OMColorSense.xcplugin */; 111 | productType = "com.apple.product-type.bundle"; 112 | }; 113 | /* End PBXNativeTarget section */ 114 | 115 | /* Begin PBXProject section */ 116 | 089C1669FE841209C02AAC07 /* Project object */ = { 117 | isa = PBXProject; 118 | attributes = { 119 | LastUpgradeCheck = 0440; 120 | }; 121 | buildConfigurationList = 1DEB913E08733D840010E9CD /* Build configuration list for PBXProject "OMColorSense" */; 122 | compatibilityVersion = "Xcode 3.2"; 123 | developmentRegion = English; 124 | hasScannedForEncodings = 1; 125 | knownRegions = ( 126 | English, 127 | Japanese, 128 | French, 129 | German, 130 | ); 131 | mainGroup = 089C166AFE841209C02AAC07 /* QuietXcode */; 132 | projectDirPath = ""; 133 | projectRoot = ""; 134 | targets = ( 135 | 8D5B49AC048680CD000E48DA /* OMColorSense */, 136 | ); 137 | }; 138 | /* End PBXProject section */ 139 | 140 | /* Begin PBXShellScriptBuildPhase section */ 141 | 7F1DE9FB1B10AF0900B6CBA8 /* ShellScript */ = { 142 | isa = PBXShellScriptBuildPhase; 143 | buildActionMask = 2147483647; 144 | files = ( 145 | ); 146 | inputPaths = ( 147 | ); 148 | outputPaths = ( 149 | ); 150 | runOnlyForDeploymentPostprocessing = 0; 151 | shellPath = /usr/bin/python; 152 | shellScript = "# Get the compatibility UUID from the current version of Xcode and update\n# the plugin's Info.plist accordingly:\n\nimport os\nimport plistlib\nimport subprocess\n\ndev_path = subprocess.check_output(['xcode-select', '-p']).strip()\nxcode_info_path = os.path.abspath(os.path.join(dev_path, '../Info'))\ncompat_uuid = subprocess.check_output(['defaults', 'read', xcode_info_path, 'DVTPlugInCompatibilityUUID']).strip()\ninfo_plist_path = os.path.join(os.getenv('BUILT_PRODUCTS_DIR'), 'OMColorSense.xcplugin/Contents/Info.plist')\ninfo = plistlib.readPlist(info_plist_path)\ninfo['DVTPlugInCompatibilityUUIDs'] = [compat_uuid]\nplistlib.writePlist(info, info_plist_path)\n"; 153 | }; 154 | /* End PBXShellScriptBuildPhase section */ 155 | 156 | /* Begin PBXSourcesBuildPhase section */ 157 | 8D5B49B1048680CD000E48DA /* Sources */ = { 158 | isa = PBXSourcesBuildPhase; 159 | buildActionMask = 2147483647; 160 | files = ( 161 | DA37E2DC0E6291C8001BDFEF /* OMColorHelper.m in Sources */, 162 | 7FDADE3A15FA6CA400A847E3 /* OMPlainColorWell.m in Sources */, 163 | 7F6EE2BF15FA6F3B00BA114A /* OMColorFrameView.m in Sources */, 164 | ); 165 | runOnlyForDeploymentPostprocessing = 0; 166 | }; 167 | /* End PBXSourcesBuildPhase section */ 168 | 169 | /* Begin XCBuildConfiguration section */ 170 | 1DEB913B08733D840010E9CD /* Debug */ = { 171 | isa = XCBuildConfiguration; 172 | buildSettings = { 173 | ALWAYS_SEARCH_USER_PATHS = NO; 174 | ARCHS = "$(ARCHS_STANDARD_64_BIT)"; 175 | CLANG_ENABLE_OBJC_ARC = YES; 176 | COMBINE_HIDPI_IMAGES = YES; 177 | COPY_PHASE_STRIP = NO; 178 | DEPLOYMENT_LOCATION = YES; 179 | DEPLOYMENT_POSTPROCESSING = YES; 180 | DSTROOT = "$(HOME)"; 181 | GCC_DYNAMIC_NO_PIC = NO; 182 | GCC_ENABLE_OBJC_GC = unsupported; 183 | GCC_MODEL_TUNING = G5; 184 | GCC_OPTIMIZATION_LEVEL = 0; 185 | INFOPLIST_FILE = Info.plist; 186 | INSTALL_PATH = "/Library/Application Support/Developer/Shared/Xcode/Plug-ins"; 187 | LD_RUNPATH_SEARCH_PATHS = /Developer; 188 | PRODUCT_NAME = OMColorSense; 189 | STRIP_INSTALLED_PRODUCT = NO; 190 | WRAPPER_EXTENSION = xcplugin; 191 | }; 192 | name = Debug; 193 | }; 194 | 1DEB913F08733D840010E9CD /* Debug */ = { 195 | isa = XCBuildConfiguration; 196 | buildSettings = { 197 | ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; 198 | CURRENT_PROJECT_VERSION = 1.0.1; 199 | GCC_C_LANGUAGE_STANDARD = c99; 200 | GCC_OPTIMIZATION_LEVEL = 0; 201 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 202 | GCC_WARN_UNUSED_VARIABLE = YES; 203 | INSTALL_PATH = "$(HOME)/Library/Application Support/Developer/Shared/Xcode/Plug-ins"; 204 | MACOSX_DEPLOYMENT_TARGET = 10.7; 205 | SDKROOT = macosx; 206 | }; 207 | name = Debug; 208 | }; 209 | /* End XCBuildConfiguration section */ 210 | 211 | /* Begin XCConfigurationList section */ 212 | 1DEB913A08733D840010E9CD /* Build configuration list for PBXNativeTarget "OMColorSense" */ = { 213 | isa = XCConfigurationList; 214 | buildConfigurations = ( 215 | 1DEB913B08733D840010E9CD /* Debug */, 216 | ); 217 | defaultConfigurationIsVisible = 0; 218 | defaultConfigurationName = Debug; 219 | }; 220 | 1DEB913E08733D840010E9CD /* Build configuration list for PBXProject "OMColorSense" */ = { 221 | isa = XCConfigurationList; 222 | buildConfigurations = ( 223 | 1DEB913F08733D840010E9CD /* Debug */, 224 | ); 225 | defaultConfigurationIsVisible = 0; 226 | defaultConfigurationName = Debug; 227 | }; 228 | /* End XCConfigurationList section */ 229 | }; 230 | rootObject = 089C1669FE841209C02AAC07 /* Project object */; 231 | } 232 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ColorSense for Xcode 2 | 3 | ## Overview 4 | 5 | ColorSense is an Xcode plugin that makes working with `UIColor` (and `NSColor`) more visual. 6 | 7 | There are [many](http://www.colorchooserapp.com) [tools](http://iconfactory.com/software/xscope) that allow you to insert a `UIColor`/`NSColor` from a color picker or by picking a color from the screen. But once you've inserted it, it can be hard to remember which color you're actually looking at in your code because you basically just have a series of numbers. 8 | 9 | This is where ColorSense comes in: When you put the caret on one of your colors, it automatically shows the actual color as an overlay, and you can even adjust it on-the-fly with the standard Mac OS X color picker. 10 | 11 | The plugin also adds some items to the _Edit_ menu to insert colors and to disable color highlighting temporarily. These menu items have no keyboard shortcuts by default, but you can set them via the system's keyboard preferences (Xcode's own preferences won't show them). 12 | 13 | **[Watch Demo Video (YouTube)](http://www.youtube.com/watch?v=eblRfDQM0Go)** 14 | 15 | I'm [@olemoritz](http://twitter.com/olemoritz) on Twitter. 16 | 17 | 18 | Flattr this 19 | 20 | ## Installation 21 | 22 | Simply build the Xcode project and restart Xcode. The plugin will automatically be installed in `~/Library/Application Support/Developer/Shared/Xcode/Plug-ins`. To uninstall, just remove the plugin from there (and restart Xcode). 23 | 24 | If you get a "Permission Denied" error while building, please see [this issue](https://github.com/omz/ColorSense-for-Xcode/issues/1). 25 | 26 | This is tested on OS X 10.8 with Xcode 4.4.1 and 4.5. 27 | 28 | ## Limitations 29 | 30 | * It only works for constant colors, something like `[UIColor colorWithWhite:foo * bar + 1 alpha:baz]` won't work. 31 | 32 | * Only RGB (`colorWithRed:green:blue:alpha:`), grayscale (`colorWithWhite:alpha:`), and named colors (`redColor`...) are supported at the moment (no HSB or CMYK). 33 | 34 | ## License 35 | 36 | Copyright (c) 2012, Ole Zorn 37 | All rights reserved. 38 | 39 | Redistribution and use in source and binary forms, with or without 40 | modification, are permitted provided that the following conditions are met: 41 | 42 | * Redistributions of source code must retain the above copyright notice, this 43 | list of conditions and the following disclaimer. 44 | 45 | * Redistributions in binary form must reproduce the above copyright notice, 46 | this list of conditions and the following disclaimer in the documentation 47 | and/or other materials provided with the distribution. 48 | 49 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 50 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 51 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 52 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 53 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 54 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 55 | OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 56 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 57 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 58 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------------------------------