|
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 |
|
12 using namespace mozilla; |
|
13 |
|
14 static unsigned int |
|
15 HexStrToInt(NSString* str) |
|
16 { |
|
17 unsigned int result = 0; |
|
18 |
|
19 for (unsigned int i = 0; i < [str length]; ++i) { |
|
20 char c = [str characterAtIndex:i]; |
|
21 result *= 16; |
|
22 if (c >= '0' && c <= '9') { |
|
23 result += c - '0'; |
|
24 } else if (c >= 'A' && c <= 'F') { |
|
25 result += 10 + (c - 'A'); |
|
26 } else { |
|
27 result += 10 + (c - 'a'); |
|
28 } |
|
29 } |
|
30 |
|
31 return result; |
|
32 } |
|
33 |
|
34 @interface NSColorPanelWrapper : NSObject <NSWindowDelegate> |
|
35 { |
|
36 NSColorPanel* mColorPanel; |
|
37 nsColorPicker* mColorPicker; |
|
38 } |
|
39 - (id)initWithPicker:(nsColorPicker*)aPicker; |
|
40 - (void)open:(NSColor*)aInitialColor title:(NSString*)aTitle; |
|
41 - (void)retarget:(nsColorPicker*)aPicker; |
|
42 - (void)colorChanged:(NSColorPanel*)aPanel; |
|
43 @end |
|
44 |
|
45 @implementation NSColorPanelWrapper |
|
46 - (id)initWithPicker:(nsColorPicker*)aPicker |
|
47 { |
|
48 mColorPicker = aPicker; |
|
49 mColorPanel = [NSColorPanel sharedColorPanel]; |
|
50 |
|
51 self = [super init]; |
|
52 return self; |
|
53 } |
|
54 |
|
55 - (void)open:(NSColor*)aInitialColor title:(NSString*)aTitle |
|
56 { |
|
57 [mColorPanel setTitle:aTitle]; |
|
58 [mColorPanel setColor:aInitialColor]; |
|
59 [mColorPanel setTarget:self]; |
|
60 [mColorPanel setAction:@selector(colorChanged:)]; |
|
61 [mColorPanel setDelegate:self]; |
|
62 [mColorPanel makeKeyAndOrderFront:nil]; |
|
63 } |
|
64 |
|
65 - (void)colorChanged:(NSColorPanel*)aPanel |
|
66 { |
|
67 mColorPicker->Update([mColorPanel color]); |
|
68 } |
|
69 |
|
70 - (void)windowWillClose:(NSNotification*)aNotification |
|
71 { |
|
72 mColorPicker->Done(); |
|
73 } |
|
74 |
|
75 - (void)retarget:(nsColorPicker*)aPicker |
|
76 { |
|
77 mColorPicker->DoneWithRetarget(); |
|
78 mColorPicker = aPicker; |
|
79 } |
|
80 |
|
81 - (void)dealloc |
|
82 { |
|
83 if ([mColorPanel delegate] == self) { |
|
84 [mColorPanel setTarget:nil]; |
|
85 [mColorPanel setAction:nil]; |
|
86 [mColorPanel setDelegate:nil]; |
|
87 } |
|
88 |
|
89 mColorPanel = nil; |
|
90 mColorPicker = nullptr; |
|
91 |
|
92 [super dealloc]; |
|
93 } |
|
94 @end |
|
95 |
|
96 NS_IMPL_ISUPPORTS(nsColorPicker, nsIColorPicker) |
|
97 |
|
98 NSColorPanelWrapper* nsColorPicker::sColorPanelWrapper = nullptr; |
|
99 |
|
100 NS_IMETHODIMP |
|
101 nsColorPicker::Init(nsIDOMWindow* aParent, const nsAString& aTitle, |
|
102 const nsAString& aInitialColor) |
|
103 { |
|
104 MOZ_ASSERT(NS_IsMainThread(), |
|
105 "Color pickers can only be opened from main thread currently"); |
|
106 mTitle = aTitle; |
|
107 mColor = aInitialColor; |
|
108 |
|
109 if (sColorPanelWrapper) { |
|
110 // Update current wrapper to target the new input instead |
|
111 [sColorPanelWrapper retarget:this]; |
|
112 } else { |
|
113 // Create a brand new color panel wrapper |
|
114 sColorPanelWrapper = [[NSColorPanelWrapper alloc] initWithPicker:this]; |
|
115 } |
|
116 return NS_OK; |
|
117 } |
|
118 |
|
119 /* static */ NSColor* |
|
120 nsColorPicker::GetNSColorFromHexString(const nsAString& aColor) |
|
121 { |
|
122 NSString* str = nsCocoaUtils::ToNSString(aColor); |
|
123 |
|
124 double red = HexStrToInt([str substringWithRange:NSMakeRange(1, 2)]) / 255.0; |
|
125 double green = HexStrToInt([str substringWithRange:NSMakeRange(3, 2)]) / 255.0; |
|
126 double blue = HexStrToInt([str substringWithRange:NSMakeRange(5, 2)]) / 255.0; |
|
127 |
|
128 return [NSColor colorWithDeviceRed: red green: green blue: blue alpha: 1.0]; |
|
129 } |
|
130 |
|
131 /* static */ void |
|
132 nsColorPicker::GetHexStringFromNSColor(NSColor* aColor, nsAString& aResult) |
|
133 { |
|
134 CGFloat redFloat, greenFloat, blueFloat; |
|
135 [aColor getRed: &redFloat green: &greenFloat blue: &blueFloat alpha: nil]; |
|
136 |
|
137 nsCocoaUtils::GetStringForNSString([NSString stringWithFormat:@"#%02x%02x%02x", |
|
138 (int)(redFloat * 255), |
|
139 (int)(greenFloat * 255), |
|
140 (int)(blueFloat * 255)], |
|
141 aResult); |
|
142 } |
|
143 |
|
144 NS_IMETHODIMP |
|
145 nsColorPicker::Open(nsIColorPickerShownCallback* aCallback) |
|
146 { |
|
147 MOZ_ASSERT(aCallback); |
|
148 mCallback = aCallback; |
|
149 |
|
150 [sColorPanelWrapper open:GetNSColorFromHexString(mColor) |
|
151 title:nsCocoaUtils::ToNSString(mTitle)]; |
|
152 |
|
153 NS_ADDREF_THIS(); |
|
154 |
|
155 return NS_OK; |
|
156 } |
|
157 |
|
158 void |
|
159 nsColorPicker::Update(NSColor* aColor) |
|
160 { |
|
161 GetHexStringFromNSColor(aColor, mColor); |
|
162 mCallback->Update(mColor); |
|
163 } |
|
164 |
|
165 void |
|
166 nsColorPicker::DoneWithRetarget() |
|
167 { |
|
168 mCallback->Done(EmptyString()); |
|
169 mCallback = nullptr; |
|
170 NS_RELEASE_THIS(); |
|
171 } |
|
172 |
|
173 void |
|
174 nsColorPicker::Done() |
|
175 { |
|
176 [sColorPanelWrapper release]; |
|
177 sColorPanelWrapper = nullptr; |
|
178 DoneWithRetarget(); |
|
179 } |