API  0.9.7
 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 @class CPSlider
26 
27 @global CPColorPickerViewWidth
28 @global CPColorPickerViewHeight
29 @global CPWheelColorPickerMode
30 
31 
38 @implementation CPColorPicker : CPObject
39 {
40  CPColorPanel _panel;
41  int _mask;
42 }
43 
49 - (id)initWithPickerMask:(int)aMask colorPanel:(CPColorPanel)aPanel
50 {
51  if (self = [super init])
52  {
53  _panel = aPanel;
54  _mask = aMask;
55  }
56 
57  return self;
58 }
59 
63 - (CPColorPanel)colorPanel
64 {
65  return _panel;
66 }
67 
68 /*
69  FIXME Not implemented.
70  @return \c nil
71  @ignore
72 */
73 - (CPImage)provideNewButtonImage
74 {
75  return nil;
76 }
77 
82 - (void)setMode:(CPColorPanelMode)mode
83 {
84 }
85 
90 - (void)setColor:(CPColor)aColor
91 {
92 }
93 
94 @end
95 
96 /*
97  The wheel mode color picker.
98  @ignore
99 */
100 @implementation CPColorWheelColorPicker : CPColorPicker
101 {
102  CPView _pickerView;
103  CPView _brightnessSlider;
104  __CPColorWheel _hueSaturationView;
105 
106  CPColor _cachedColor;
107 }
108 
109 - (id)initWithPickerMask:(int)mask colorPanel:(CPColorPanel)owningColorPanel
110 {
111  return [super initWithPickerMask:mask colorPanel: owningColorPanel];
112 }
113 
114 - (id)initView
115 {
116  var aFrame = CGRectMake(0, 0, CPColorPickerViewWidth, CPColorPickerViewHeight);
117 
118  _pickerView = [[CPView alloc] initWithFrame:aFrame];
119  [_pickerView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
120 
121  _brightnessSlider = [[CPSlider alloc] initWithFrame:CGRectMake(0, (aFrame.size.height - 34), aFrame.size.width, 15)];
122 
123  [_brightnessSlider setValue:15.0 forThemeAttribute:@"track-width"];
124  [_brightnessSlider setValue:[CPColor colorWithPatternImage:[[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:[CPColorPicker class]] pathForResource:@"brightness_bar.png"]]] forThemeAttribute:@"track-color"];
125 
126  [_brightnessSlider setMinValue:0.0];
127  [_brightnessSlider setMaxValue:100.0];
128  [_brightnessSlider setFloatValue:100.0];
129 
130  [_brightnessSlider setTarget:self];
131  [_brightnessSlider setAction:@selector(brightnessSliderDidChange:)];
132  [_brightnessSlider setAutoresizingMask:CPViewWidthSizable | CPViewMinYMargin];
133 
134  _hueSaturationView = [[__CPColorWheel alloc] initWithFrame:CGRectMake(0, 0, aFrame.size.width, aFrame.size.height - 38)];
135  [_hueSaturationView setDelegate:self];
136  [_hueSaturationView setAutoresizingMask:(CPViewWidthSizable | CPViewHeightSizable)];
137 
138  [_pickerView addSubview:_hueSaturationView];
139  [_pickerView addSubview:_brightnessSlider];
140 }
141 
142 - (void)brightnessSliderDidChange:(id)sender
143 {
144  [self updateColor];
145 }
146 
147 - (void)colorWheelDidChange:(id)sender
148 {
149  [self updateColor];
150 }
151 
152 - (void)updateColor
153 {
154  var hue = [_hueSaturationView angle],
155  saturation = [_hueSaturationView distance],
156  brightness = [_brightnessSlider floatValue];
157 
158  [_hueSaturationView setWheelBrightness:brightness / 100.0];
159  [_brightnessSlider setBackgroundColor:[CPColor colorWithHue:hue / 360.0 saturation:saturation / 100.0 brightness:1]];
160 
161  var colorPanel = [self colorPanel],
162  opacity = [colorPanel opacity];
163 
164  _cachedColor = [CPColor colorWithHue:hue / 360.0 saturation:saturation / 100.0 brightness:brightness / 100.0 alpha:opacity];
165 
166  [[self colorPanel] setColor:_cachedColor];
167 }
168 
169 - (BOOL)supportsMode:(int)mode
170 {
171  return (mode == CPWheelColorPickerMode) ? YES : NO;
172 }
173 
174 - (int)currentMode
175 {
176  return CPWheelColorPickerMode;
177 }
178 
179 - (CPView)provideNewView:(BOOL)initialRequest
180 {
181  if (initialRequest)
182  [self initView];
183 
184  return _pickerView;
185 }
186 
187 - (void)setColor:(CPColor)newColor
188 {
189  if ([newColor isEqual:_cachedColor])
190  return;
191 
192  var hsb = [newColor hsbComponents];
193 
194  [_hueSaturationView setPositionToColor:newColor];
195  [_brightnessSlider setFloatValue:hsb[2] * 100.0];
196  [_hueSaturationView setWheelBrightness:hsb[2]];
197 
198  [_brightnessSlider setBackgroundColor:[CPColor colorWithHue:hsb[0] saturation:hsb[1] brightness:1]];
199 }
200 
201 - (CPImage)provideNewButtonImage
202 {
203  return [[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:CPColorPicker] pathForResource:"wheel_button.png"] size:CGSizeMake(32, 32)];
204 }
205 
206 - (CPImage)provideNewAlternateButtonImage
207 {
208  return [[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:CPColorPicker] pathForResource:"wheel_button_h.png"] size:CGSizeMake(32, 32)];
209 }
210 
211 @end
212 
213 /* @ignore */
214 @implementation __CPColorWheel : CPView
215 {
216  DOMElement _wheelImage;
217  DOMElement _blackWheelImage;
218 
219  CPView _crosshair;
220 
221  id _delegate;
222 
223  float _angle;
224  float _distance;
225 
226  float _radius;
227 }
228 
229 - (id)initWithFrame:(CGRect)aFrame
230 {
231  if (self = [super initWithFrame:aFrame])
232  {
233 #if PLATFORM(DOM)
234  var path = [[CPBundle bundleForClass:CPColorPicker] pathForResource:@"wheel.png"];
235 
236  _wheelImage = new Image();
237  _wheelImage.src = path;
238  _wheelImage.style.position = "absolute";
239 
240  path = [[CPBundle bundleForClass:CPColorPicker] pathForResource:@"wheel_black.png"];
241 
242  _blackWheelImage = new Image();
243  _blackWheelImage.src = path;
244  _blackWheelImage.style.opacity = "0";
245  _blackWheelImage.style.filter = "alpha(opacity=0)"
246  _blackWheelImage.style.position = "absolute";
247 
248  _DOMElement.appendChild(_wheelImage);
249  _DOMElement.appendChild(_blackWheelImage);
250 #endif
251 
252  [self setWheelSize:aFrame.size];
253 
254  _crosshair = [[CPView alloc] initWithFrame:CGRectMake(_radius - 2, _radius - 2, 4, 4)];
255  [_crosshair setBackgroundColor:[CPColor blackColor]];
256 
257  var view = [[CPView alloc] initWithFrame:CGRectInset([_crosshair bounds], 1.0, 1.0)];
258  [view setBackgroundColor:[CPColor whiteColor]];
259 
260  [_crosshair addSubview:view];
261 
262  [self addSubview:_crosshair];
263  }
264 
265  return self;
266 }
267 
268 - (void)setWheelBrightness:(float)brightness
269 {
270 #if PLATFORM(DOM)
271  _blackWheelImage.style.opacity = 1.0 - brightness;
272  _blackWheelImage.style.filter = "alpha(opacity=" + (1.0 - brightness) * 100 + ")"
273 #endif
274 }
275 
276 - (void)setFrameSize:(CGSize)aSize
277 {
278  [super setFrameSize:aSize];
279  [self setWheelSize:aSize];
280 }
281 
282 - (void)setWheelSize:(CGSize)aSize
283 {
284  var min = MIN(aSize.width, aSize.height);
285 
286 #if PLATFORM(DOM)
287  _blackWheelImage.style.width = min;
288  _blackWheelImage.style.height = min;
289  _blackWheelImage.width = min;
290  _blackWheelImage.height = min;
291  _blackWheelImage.style.top = (aSize.height - min) / 2.0 + "px";
292  _blackWheelImage.style.left = (aSize.width - min) / 2.0 + "px";
293 
294  _wheelImage.style.width = min;
295  _wheelImage.style.height = min;
296  _wheelImage.width = min;
297  _wheelImage.height = min;
298  _wheelImage.style.top = (aSize.height - min) / 2.0 + "px";
299  _wheelImage.style.left = (aSize.width - min) / 2.0 + "px";
300 #endif
301 
302  _radius = min / 2.0;
303 
304  [self setAngle:[self degreesToRadians:_angle] distance:(_distance / 100.0) * _radius];
305 }
306 
307 - (void)setDelegate:(id)aDelegate
308 {
309  _delegate = aDelegate;
310 }
311 
312 - (id)delegate
313 {
314  return _delegate;
315 }
316 
317 - (float)angle
318 {
319  return _angle;
320 }
321 
322 - (float)distance
323 {
324  return _distance;
325 }
326 
327 - (void)mouseDown:(CPEvent)anEvent
328 {
329  [self reposition:anEvent];
330 }
331 
332 - (void)mouseDragged:(CPEvent)anEvent
333 {
334  [self reposition:anEvent];
335 }
336 
337 - (void)reposition:(CPEvent)anEvent
338 {
339  var bounds = [self bounds],
340  location = [self convertPoint:[anEvent locationInWindow] fromView:nil],
341  midX = CGRectGetMidX(bounds),
342  midY = CGRectGetMidY(bounds),
343  distance = MIN(SQRT((location.x - midX) * (location.x - midX) + (location.y - midY) * (location.y - midY)), _radius),
344  angle = ATAN2(location.y - midY, location.x - midX);
345 
346  [self setAngle:angle distance:distance];
347 
348  [_delegate colorWheelDidChange:self];
349 }
350 
351 - (void)setAngle:(int)angle distance:(float)distance
352 {
353  var bounds = [self bounds],
354  midX = CGRectGetMidX(bounds),
355  midY = CGRectGetMidY(bounds);
356 
357  _angle = [self radiansToDegrees:angle];
358  _distance = (distance / _radius) * 100.0;
359 
360  [_crosshair setFrameOrigin:CGPointMake(COS(angle) * distance + midX - 2.0, SIN(angle) * distance + midY - 2.0)];
361 }
362 
363 - (void)setPositionToColor:(CPColor)aColor
364 {
365  var hsb = [aColor hsbComponents],
366  bounds = [self bounds],
367  angle = [self degreesToRadians:hsb[0] * 360.0],
368  distance = hsb[1] * _radius;
369 
370  [self setAngle:angle distance:distance];
371 }
372 
373 - (int)radiansToDegrees:(float)radians
374 {
375  return ((-radians / PI) * 180 + 360) % 360;
376 }
377 
378 - (float)degreesToRadians:(float)degrees
379 {
380  return -(((degrees - 360) / 180) * PI);
381 }
382 
383 @end
384