API  0.9.6
 All Classes Files Functions Variables Macros Groups Pages
CPColorPicker.j
Go to the documentation of this file.
1 /*
2  * CPColorPicker.j
3  * AppKit
4  *
5  * Created by Ross Boucher.
6  * Copyright 2008, 280 North, Inc.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 
23 
24 
25 
32 @implementation CPColorPicker : CPObject
33 {
34  CPColorPanel _panel;
35  int _mask;
36 }
37 
43 - (id)initWithPickerMask:(int)aMask colorPanel:(CPColorPanel)aPanel
44 {
45  if (self = [super init])
46  {
47  _panel = aPanel;
48  _mask = aMask;
49  }
50 
51  return self;
52 }
53 
57 - (CPColorPanel)colorPanel
58 {
59  return _panel;
60 }
61 
62 /*
63  FIXME Not implemented.
64  @return \c nil
65  @ignore
66 */
67 - (CPImage)provideNewButtonImage
68 {
69  return nil;
70 }
71 
76 - (void)setMode:(CPColorPanelMode)mode
77 {
78 }
79 
84 - (void)setColor:(CPColor)aColor
85 {
86 }
87 
88 @end
89 
90 /*
91  The wheel mode color picker.
92  @ignore
93 */
95 {
96  CPView _pickerView;
97  CPView _brightnessSlider;
98  __CPColorWheel _hueSaturationView;
99 
100  CPColor _cachedColor;
101 }
102 
103 - (id)initWithPickerMask:(int)mask colorPanel:(CPColorPanel)owningColorPanel
104 {
105  return [super initWithPickerMask:mask colorPanel: owningColorPanel];
106 }
107 
108 - (id)initView
109 {
110  var aFrame = _CGRectMake(0, 0, CPColorPickerViewWidth, CPColorPickerViewHeight);
111 
112  _pickerView = [[CPView alloc] initWithFrame:aFrame];
113  [_pickerView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
114 
115  _brightnessSlider = [[CPSlider alloc] initWithFrame:_CGRectMake(0, (aFrame.size.height - 34), aFrame.size.width, 15)];
116 
117  [_brightnessSlider setValue:15.0 forThemeAttribute:@"track-width"];
118  [_brightnessSlider setValue:[CPColor colorWithPatternImage:[[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:[CPColorPicker class]] pathForResource:@"brightness_bar.png"]]] forThemeAttribute:@"track-color"];
119 
120  [_brightnessSlider setMinValue:0.0];
121  [_brightnessSlider setMaxValue:100.0];
122  [_brightnessSlider setFloatValue:100.0];
123 
124  [_brightnessSlider setTarget:self];
125  [_brightnessSlider setAction:@selector(brightnessSliderDidChange:)];
126  [_brightnessSlider setAutoresizingMask:CPViewWidthSizable | CPViewMinYMargin];
127 
128  _hueSaturationView = [[__CPColorWheel alloc] initWithFrame:_CGRectMake(0, 0, aFrame.size.width, aFrame.size.height - 38)];
129  [_hueSaturationView setDelegate:self];
130  [_hueSaturationView setAutoresizingMask:(CPViewWidthSizable | CPViewHeightSizable)];
131 
132  [_pickerView addSubview:_hueSaturationView];
133  [_pickerView addSubview:_brightnessSlider];
134 }
135 
136 - (void)brightnessSliderDidChange:(id)sender
137 {
138  [self updateColor];
139 }
140 
141 - (void)colorWheelDidChange:(id)sender
142 {
143  [self updateColor];
144 }
145 
146 - (void)updateColor
147 {
148  var hue = [_hueSaturationView angle],
149  saturation = [_hueSaturationView distance],
150  brightness = [_brightnessSlider floatValue];
151 
152  [_hueSaturationView setWheelBrightness:brightness / 100.0];
153  [_brightnessSlider setBackgroundColor:[CPColor colorWithHue:hue saturation:saturation brightness:100]];
154 
155  var colorPanel = [self colorPanel],
156  opacity = [colorPanel opacity];
157 
158  _cachedColor = [CPColor colorWithHue:hue saturation:saturation brightness:brightness alpha:opacity];
159 
160  [[self colorPanel] setColor:_cachedColor];
161 }
162 
163 - (BOOL)supportsMode:(int)mode
164 {
165  return (mode == CPWheelColorPickerMode) ? YES : NO;
166 }
167 
168 - (int)currentMode
169 {
170  return CPWheelColorPickerMode;
171 }
172 
173 - (CPView)provideNewView:(BOOL)initialRequest
174 {
175  if (initialRequest)
176  [self initView];
177 
178  return _pickerView;
179 }
180 
181 - (void)setColor:(CPColor)newColor
182 {
183  if ([newColor isEqual:_cachedColor])
184  return;
185 
186  var hsb = [newColor hsbComponents];
187 
188  [_hueSaturationView setPositionToColor:newColor];
189  [_brightnessSlider setFloatValue:hsb[2]];
190  [_hueSaturationView setWheelBrightness:hsb[2] / 100.0];
191 
192  [_brightnessSlider setBackgroundColor:[CPColor colorWithHue:hsb[0] saturation:hsb[1] brightness:100]];
193 }
194 
195 - (CPImage)provideNewButtonImage
196 {
197  return [[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:CPColorPicker] pathForResource:"wheel_button.png"] size:CGSizeMake(32, 32)];
198 }
199 
200 - (CPImage)provideNewAlternateButtonImage
201 {
202  return [[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:CPColorPicker] pathForResource:"wheel_button_h.png"] size:CGSizeMake(32, 32)];
203 }
204 
205 @end
206 
207 /* @ignore */
208 @implementation __CPColorWheel : CPView
209 {
210  DOMElement _wheelImage;
211  DOMElement _blackWheelImage;
212 
213  CPView _crosshair;
214 
215  id _delegate;
216 
217  float _angle;
218  float _distance;
219 
220  float _radius;
221 }
222 
223 - (id)initWithFrame:(CPRect)aFrame
224 {
225  if (self = [super initWithFrame:aFrame])
226  {
227 #if PLATFORM(DOM)
228  var path = [[CPBundle bundleForClass:CPColorPicker] pathForResource:@"wheel.png"];
229 
230  _wheelImage = new Image();
231  _wheelImage.src = path;
232  _wheelImage.style.position = "absolute";
233 
234  path = [[CPBundle bundleForClass:CPColorPicker] pathForResource:@"wheel_black.png"];
235 
236  _blackWheelImage = new Image();
237  _blackWheelImage.src = path;
238  _blackWheelImage.style.opacity = "0";
239  _blackWheelImage.style.filter = "alpha(opacity=0)"
240  _blackWheelImage.style.position = "absolute";
241 
242  _DOMElement.appendChild(_wheelImage);
243  _DOMElement.appendChild(_blackWheelImage);
244 #endif
245 
246  [self setWheelSize:aFrame.size];
247 
248  _crosshair = [[CPView alloc] initWithFrame:CGRectMake(_radius - 2, _radius - 2, 4, 4)];
249  [_crosshair setBackgroundColor:[CPColor blackColor]];
250 
251  var view = [[CPView alloc] initWithFrame:CGRectInset([_crosshair bounds], 1.0, 1.0)];
252  [view setBackgroundColor:[CPColor whiteColor]];
253 
254  [_crosshair addSubview:view];
255 
256  [self addSubview:_crosshair];
257  }
258 
259  return self;
260 }
261 
262 - (void)setWheelBrightness:(float)brightness
263 {
264 #if PLATFORM(DOM)
265  _blackWheelImage.style.opacity = 1.0 - brightness;
266  _blackWheelImage.style.filter = "alpha(opacity=" + (1.0 - brightness) * 100 + ")"
267 #endif
268 }
269 
270 - (void)setFrameSize:(CPSize)aSize
271 {
272  [super setFrameSize:aSize];
273  [self setWheelSize:aSize];
274 }
275 
276 - (void)setWheelSize:(CPSize)aSize
277 {
278  var min = MIN(aSize.width, aSize.height);
279 
280 #if PLATFORM(DOM)
281  _blackWheelImage.style.width = min;
282  _blackWheelImage.style.height = min;
283  _blackWheelImage.width = min;
284  _blackWheelImage.height = min;
285  _blackWheelImage.style.top = (aSize.height - min) / 2.0 + "px";
286  _blackWheelImage.style.left = (aSize.width - min) / 2.0 + "px";
287 
288  _wheelImage.style.width = min;
289  _wheelImage.style.height = min;
290  _wheelImage.width = min;
291  _wheelImage.height = min;
292  _wheelImage.style.top = (aSize.height - min) / 2.0 + "px";
293  _wheelImage.style.left = (aSize.width - min) / 2.0 + "px";
294 #endif
295 
296  _radius = min / 2.0;
297 
298  [self setAngle:[self degreesToRadians:_angle] distance:(_distance / 100.0) * _radius];
299 }
300 
301 - (void)setDelegate:(id)aDelegate
302 {
303  _delegate = aDelegate;
304 }
305 
306 - (id)delegate
307 {
308  return _delegate;
309 }
310 
311 - (float)angle
312 {
313  return _angle;
314 }
315 
316 - (float)distance
317 {
318  return _distance;
319 }
320 
321 - (void)mouseDown:(CPEvent)anEvent
322 {
323  [self reposition:anEvent];
324 }
325 
326 - (void)mouseDragged:(CPEvent)anEvent
327 {
328  [self reposition:anEvent];
329 }
330 
331 - (void)reposition:(CPEvent)anEvent
332 {
333  var bounds = [self bounds],
334  location = [self convertPoint:[anEvent locationInWindow] fromView:nil],
335  midX = CGRectGetMidX(bounds),
336  midY = CGRectGetMidY(bounds),
337  distance = MIN(SQRT((location.x - midX) * (location.x - midX) + (location.y - midY) * (location.y - midY)), _radius),
338  angle = ATAN2(location.y - midY, location.x - midX);
339 
340  [self setAngle:angle distance:distance];
341 
342  [_delegate colorWheelDidChange:self];
343 }
344 
345 - (void)setAngle:(int)angle distance:(float)distance
346 {
347  var bounds = [self bounds],
348  midX = CGRectGetMidX(bounds),
349  midY = CGRectGetMidY(bounds);
350 
351  _angle = [self radiansToDegrees:angle];
352  _distance = (distance / _radius) * 100.0;
353 
354  [_crosshair setFrameOrigin:CPPointMake(COS(angle) * distance + midX - 2.0, SIN(angle) * distance + midY - 2.0)];
355 }
356 
357 - (void)setPositionToColor:(CPColor)aColor
358 {
359  var hsb = [aColor hsbComponents],
360  bounds = [self bounds],
361  angle = [self degreesToRadians:hsb[0]],
362  distance = (hsb[1] / 100.0) * _radius;
363 
364  [self setAngle:angle distance:distance];
365 }
366 
367 - (int)radiansToDegrees:(float)radians
368 {
369  return ((-radians / PI) * 180 + 360) % 360;
370 }
371 
372 - (float)degreesToRadians:(float)degrees
373 {
374  return -(((degrees - 360) / 180) * PI);
375 }
376 
377 @end
378