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/. */
6 #import <Cocoa/Cocoa.h>
8 #include "nsColorPicker.h"
9 #include "nsCocoaUtils.h"
10 #include "nsThreadUtils.h"
12 using namespace mozilla;
14 static unsigned int HexStrToInt(NSString* str) {
15 unsigned int result = 0;
17 for (unsigned int i = 0; i < [str length]; ++i) {
18 char c = [str characterAtIndex:i];
20 if (c >= '0' && c <= '9') {
22 } else if (c >= 'A' && c <= 'F') {
23 result += 10 + (c - 'A');
25 result += 10 + (c - 'a');
32 @interface NSColorPanelWrapper : NSObject <NSWindowDelegate> {
33 NSColorPanel* mColorPanel;
34 nsColorPicker* mColorPicker;
36 - (id)initWithPicker:(nsColorPicker*)aPicker;
37 - (void)open:(NSColor*)aInitialColor title:(NSString*)aTitle;
38 - (void)colorChanged:(NSColorPanel*)aPanel;
39 - (void)windowWillClose:(NSNotification*)aNotification;
43 @implementation NSColorPanelWrapper
44 - (id)initWithPicker:(nsColorPicker*)aPicker {
45 mColorPicker = aPicker;
46 mColorPanel = [NSColorPanel sharedColorPanel];
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 setFrameOrigin:[NSEvent mouseLocation]];
59 [mColorPanel makeKeyAndOrderFront:nil];
62 - (void)colorChanged:(NSColorPanel*)aPanel {
66 mColorPicker->Update([mColorPanel color]);
69 - (void)windowWillClose:(NSNotification*)aNotification {
77 [mColorPanel setTarget:nil];
78 [mColorPanel setAction:nil];
79 [mColorPanel setDelegate:nil];
82 mColorPicker = nullptr;
86 NS_IMPL_ISUPPORTS(nsColorPicker, nsIColorPicker)
88 nsColorPicker::~nsColorPicker() {
89 if (mColorPanelWrapper) {
90 [mColorPanelWrapper close];
91 [mColorPanelWrapper release];
92 mColorPanelWrapper = nullptr;
96 // TODO(bug 1805397): Implement default colors
98 nsColorPicker::Init(mozIDOMWindowProxy* aParent, const nsAString& aTitle,
99 const nsAString& aInitialColor, const nsTArray<nsString>& aDefaultColors) {
100 MOZ_ASSERT(NS_IsMainThread(), "Color pickers can only be opened from main thread currently");
102 mColor = aInitialColor;
103 mColorPanelWrapper = [[NSColorPanelWrapper alloc] initWithPicker:this];
107 /* static */ NSColor* nsColorPicker::GetNSColorFromHexString(const nsAString& aColor) {
108 NSString* str = nsCocoaUtils::ToNSString(aColor);
110 double red = HexStrToInt([str substringWithRange:NSMakeRange(1, 2)]) / 255.0;
111 double green = HexStrToInt([str substringWithRange:NSMakeRange(3, 2)]) / 255.0;
112 double blue = HexStrToInt([str substringWithRange:NSMakeRange(5, 2)]) / 255.0;
114 return [NSColor colorWithDeviceRed:red green:green blue:blue alpha:1.0];
117 /* static */ void nsColorPicker::GetHexStringFromNSColor(NSColor* aColor, nsAString& aResult) {
118 CGFloat redFloat, greenFloat, blueFloat;
120 NSColor* color = aColor;
122 [color getRed:&redFloat green:&greenFloat blue:&blueFloat alpha:nil];
123 } @catch (NSException* e) {
124 color = [color colorUsingColorSpace:[NSColorSpace genericRGBColorSpace]];
125 [color getRed:&redFloat green:&greenFloat blue:&blueFloat alpha:nil];
128 nsCocoaUtils::GetStringForNSString(
129 [NSString stringWithFormat:@"#%02x%02x%02x", (int)(redFloat * 255), (int)(greenFloat * 255),
130 (int)(blueFloat * 255)],
135 nsColorPicker::Open(nsIColorPickerShownCallback* aCallback) {
136 MOZ_ASSERT(aCallback);
137 mCallback = aCallback;
139 [mColorPanelWrapper open:GetNSColorFromHexString(mColor) title:nsCocoaUtils::ToNSString(mTitle)];
146 void nsColorPicker::Update(NSColor* aColor) {
147 GetHexStringFromNSColor(aColor, mColor);
148 mCallback->Update(mColor);
151 void nsColorPicker::Done() {
152 [mColorPanelWrapper close];
153 [mColorPanelWrapper release];
154 mColorPanelWrapper = nullptr;
155 mCallback->Done(u""_ns);