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