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