1/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2/* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6#import <Cocoa/Cocoa.h> 7 8#include "nsColorPicker.h" 9#include "nsCocoaUtils.h" 10#include "nsThreadUtils.h" 11 12using namespace mozilla; 13 14static unsigned int HexStrToInt(NSString* str) { 15 unsigned int result = 0; 16 17 for (unsigned int i = 0; i < [str length]; ++i) { 18 char c = [str characterAtIndex:i]; 19 result *= 16; 20 if (c >= '0' && c <= '9') { 21 result += c - '0'; 22 } else if (c >= 'A' && c <= 'F') { 23 result += 10 + (c - 'A'); 24 } else { 25 result += 10 + (c - 'a'); 26 } 27 } 28 29 return result; 30} 31 32@interface NSColorPanelWrapper : NSObject <NSWindowDelegate> { 33 NSColorPanel* mColorPanel; 34 nsColorPicker* mColorPicker; 35} 36- (id)initWithPicker:(nsColorPicker*)aPicker; 37- (void)open:(NSColor*)aInitialColor title:(NSString*)aTitle; 38- (void)colorChanged:(NSColorPanel*)aPanel; 39- (void)windowWillClose:(NSNotification*)aNotification; 40- (void)close; 41@end 42 43@implementation NSColorPanelWrapper 44- (id)initWithPicker:(nsColorPicker*)aPicker { 45 mColorPicker = aPicker; 46 mColorPanel = [NSColorPanel sharedColorPanel]; 47 48 self = [super init]; 49 return self; 50} 51 52- (void)open:(NSColor*)aInitialColor title:(NSString*)aTitle { 53 [mColorPanel setTarget:self]; 54 [mColorPanel setAction:@selector(colorChanged:)]; 55 [mColorPanel setDelegate:self]; 56 [mColorPanel setTitle:aTitle]; 57 [mColorPanel setColor:aInitialColor]; 58 [mColorPanel makeKeyAndOrderFront:nil]; 59} 60 61- (void)colorChanged:(NSColorPanel*)aPanel { 62 if (!mColorPicker) { 63 return; 64 } 65 mColorPicker->Update([mColorPanel color]); 66} 67 68- (void)windowWillClose:(NSNotification*)aNotification { 69 if (!mColorPicker) { 70 return; 71 } 72 mColorPicker->Done(); 73} 74 75- (void)close { 76 [mColorPanel setTarget:nil]; 77 [mColorPanel setAction:nil]; 78 [mColorPanel setDelegate:nil]; 79 80 mColorPanel = nil; 81 mColorPicker = nullptr; 82} 83@end 84 85NS_IMPL_ISUPPORTS(nsColorPicker, nsIColorPicker) 86 87nsColorPicker::~nsColorPicker() { 88 if (mColorPanelWrapper) { 89 [mColorPanelWrapper close]; 90 [mColorPanelWrapper release]; 91 mColorPanelWrapper = nullptr; 92 } 93} 94 95NS_IMETHODIMP 96nsColorPicker::Init(mozIDOMWindowProxy* aParent, const nsAString& aTitle, 97 const nsAString& aInitialColor) { 98 MOZ_ASSERT(NS_IsMainThread(), "Color pickers can only be opened from main thread currently"); 99 mTitle = aTitle; 100 mColor = aInitialColor; 101 mColorPanelWrapper = [[NSColorPanelWrapper alloc] initWithPicker:this]; 102 return NS_OK; 103} 104 105/* static */ NSColor* nsColorPicker::GetNSColorFromHexString(const nsAString& aColor) { 106 NSString* str = nsCocoaUtils::ToNSString(aColor); 107 108 double red = HexStrToInt([str substringWithRange:NSMakeRange(1, 2)]) / 255.0; 109 double green = HexStrToInt([str substringWithRange:NSMakeRange(3, 2)]) / 255.0; 110 double blue = HexStrToInt([str substringWithRange:NSMakeRange(5, 2)]) / 255.0; 111 112 return [NSColor colorWithDeviceRed:red green:green blue:blue alpha:1.0]; 113} 114 115/* static */ void nsColorPicker::GetHexStringFromNSColor(NSColor* aColor, nsAString& aResult) { 116 CGFloat redFloat, greenFloat, blueFloat; 117 118 NSColor* color = aColor; 119 @try { 120 [color getRed:&redFloat green:&greenFloat blue:&blueFloat alpha:nil]; 121 } @catch (NSException* e) { 122 color = [color colorUsingColorSpace:[NSColorSpace genericRGBColorSpace]]; 123 [color getRed:&redFloat green:&greenFloat blue:&blueFloat alpha:nil]; 124 } 125 126 nsCocoaUtils::GetStringForNSString( 127 [NSString stringWithFormat:@"#%02x%02x%02x", (int)(redFloat * 255), (int)(greenFloat * 255), 128 (int)(blueFloat * 255)], 129 aResult); 130} 131 132NS_IMETHODIMP 133nsColorPicker::Open(nsIColorPickerShownCallback* aCallback) { 134 MOZ_ASSERT(aCallback); 135 mCallback = aCallback; 136 137 [mColorPanelWrapper open:GetNSColorFromHexString(mColor) title:nsCocoaUtils::ToNSString(mTitle)]; 138 139 NS_ADDREF_THIS(); 140 141 return NS_OK; 142} 143 144void nsColorPicker::Update(NSColor* aColor) { 145 GetHexStringFromNSColor(aColor, mColor); 146 mCallback->Update(mColor); 147} 148 149void nsColorPicker::Done() { 150 [mColorPanelWrapper close]; 151 [mColorPanelWrapper release]; 152 mColorPanelWrapper = nullptr; 153 mCallback->Done(u""_ns); 154 mCallback = nullptr; 155 NS_RELEASE_THIS(); 156} 157