PageRenderTime 25ms CodeModel.GetById 11ms app.highlight 6ms RepoModel.GetById 2ms app.codeStats 0ms

/AppKit/CPColorPicker.j

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