Index: /as3/gunyarapaint/trunk/colorpicker/.flexLibProperties =================================================================== --- /as3/gunyarapaint/trunk/colorpicker/.flexLibProperties (リビジョン 2167) +++ /as3/gunyarapaint/trunk/colorpicker/.flexLibProperties (リビジョン 2167) @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + Index: /as3/gunyarapaint/trunk/colorpicker/.project =================================================================== --- /as3/gunyarapaint/trunk/colorpicker/.project (リビジョン 2167) +++ /as3/gunyarapaint/trunk/colorpicker/.project (リビジョン 2167) @@ -0,0 +1,18 @@ + + + colorpicker + + + + + + com.adobe.flexbuilder.project.flexbuilder + + + + + + com.adobe.flexbuilder.project.flexlibnature + com.adobe.flexbuilder.project.actionscriptnature + + Index: /as3/gunyarapaint/trunk/colorpicker/src/mxml-manifest.xml =================================================================== --- /as3/gunyarapaint/trunk/colorpicker/src/mxml-manifest.xml (リビジョン 2167) +++ /as3/gunyarapaint/trunk/colorpicker/src/mxml-manifest.xml (リビジョン 2167) @@ -0,0 +1,10 @@ + + + + + + + + + + Index: /as3/gunyarapaint/trunk/colorpicker/src/manifest.xml =================================================================== --- /as3/gunyarapaint/trunk/colorpicker/src/manifest.xml (リビジョン 2167) +++ /as3/gunyarapaint/trunk/colorpicker/src/manifest.xml (リビジョン 2167) @@ -0,0 +1,9 @@ + + + + + + + + + Index: /as3/gunyarapaint/trunk/colorpicker/src/org/sepy/graphics/ColorMatrix.as =================================================================== --- /as3/gunyarapaint/trunk/colorpicker/src/org/sepy/graphics/ColorMatrix.as (リビジョン 2167) +++ /as3/gunyarapaint/trunk/colorpicker/src/org/sepy/graphics/ColorMatrix.as (リビジョン 2167) @@ -0,0 +1,174 @@ +package org.sepy.graphics +{ + import org.sepy.geom.Matrix2d; + + public class ColorMatrix extends Matrix2d + { + + public static const BRIGHTNESS_MIN:int = -255; + public static const BRIGHTNESS_MAX:int = 255; + + public static const HUE_MIN:int = -180; + public static const HUE_MAX:int = 180; + + public static const SATURATION_MIN:int = -100; + public static const SATURATION_MAX:int = 100; + + public static const CONTRAST_MIN:int = -100; + public static const CONTRAST_MAX:int = 100; + + // constant for contrast calculations: + private static var DELTA_INDEX:Array = [ + 0, 0.01, 0.02, 0.04, 0.05, 0.06, 0.07, 0.08, 0.1, 0.11, + 0.12, 0.14, 0.15, 0.16, 0.17, 0.18, 0.20, 0.21, 0.22, 0.24, + 0.25, 0.27, 0.28, 0.30, 0.32, 0.34, 0.36, 0.38, 0.40, 0.42, + 0.44, 0.46, 0.48, 0.5, 0.53, 0.56, 0.59, 0.62, 0.65, 0.68, + 0.71, 0.74, 0.77, 0.80, 0.83, 0.86, 0.89, 0.92, 0.95, 0.98, + 1.0, 1.06, 1.12, 1.18, 1.24, 1.30, 1.36, 1.42, 1.48, 1.54, + 1.60, 1.66, 1.72, 1.78, 1.84, 1.90, 1.96, 2.0, 2.12, 2.25, + 2.37, 2.50, 2.62, 2.75, 2.87, 3.0, 3.2, 3.4, 3.6, 3.8, + 4.0, 4.3, 4.7, 4.9, 5.0, 5.5, 6.0, 6.5, 6.8, 7.0, + 7.3, 7.5, 7.8, 8.0, 8.4, 8.7, 9.0, 9.4, 9.6, 9.8, + 10.0 + ]; + + public function ColorMatrix(matrix:Array = null) + { + super(5, 5); + + setFlatData(matrix ? matrix : IDENTITY, true); + } + + public function adjustColor(brightness:int, contrast:int, saturation:int, hue:int):void + { + adjustHue(hue); + adjustContrast(contrast); + adjustSaturation(saturation); + adjustBrightness(brightness); + } + + public function adjustBrightness(val:int):void + { + val = fixValue(val, 255); + if(!val) + return; + + multiply([ + 1,0,0,0,val, + 0,1,0,0,val, + 0,0,1,0,val, + 0,0,0,1,0, + 0,0,0,0,1 + ]); + } + + public function adjustContrast(val:int):void + { + var x:Number; + + val = fixValue(val, 100); + if(!val) + return; + + if (val < 0) + x = 127 + val / 100 * 127; + else { + x = val % 1; + x = (x == 0) ? DELTA_INDEX[val] : DELTA_INDEX[(val<<0)]*(1-x)+DELTA_INDEX[(val<<0)+1]*x; + x = x * 127 + 127; + } + + multiply([ + x/127,0,0,0,0.5*(127-x), + 0,x/127,0,0,0.5*(127-x), + 0,0,x/127,0,0.5*(127-x), + 0,0,0,1,0, + 0,0,0,0,1 + ]); + } + + public function grayScale():void + { + adjustSaturation(-100); + } + + public function adjustSaturation(val:int):void + { + var x:Number; + /* + var lumR:Number = 0.212671; + var lumG:Number = 0.715160; + var lumB:Number = 0.072169; + */ + var lumR:Number = 0.3086; + var lumG:Number = 0.6094; + var lumB:Number = 0.0820; + + val = fixValue(val, 100); + if(!val) + return; + + x = 1 + ((val > 0) ? 3 * val / 100 : val / 100); + + multiply([ + lumR*(1-x)+x,lumG*(1-x),lumB*(1-x),0,0, + lumR*(1-x),lumG*(1-x)+x,lumB*(1-x),0,0, + lumR*(1-x),lumG*(1-x),lumB*(1-x)+x,0,0, + 0,0,0,1,0, + 0,0,0,0,1 + ]); + } + + public function adjustHue(val:int):void + { + var cosVal:Number; + var sinVal:Number; + var lumR:Number = 0.213; + var lumG:Number = 0.715; + var lumB:Number = 0.072; + + val = fixValue(val, 180) / 180 * Math.PI; + if(!val) + return; + + cosVal = Math.cos(val); + sinVal = Math.sin(val); + + multiply([ + lumR+cosVal*(1-lumR)+sinVal*(-lumR),lumG+cosVal*(-lumG)+sinVal*(-lumG),lumB+cosVal*(-lumB)+sinVal*(1-lumB),0,0, + lumR+cosVal*(-lumR)+sinVal*(0.143),lumG+cosVal*(1-lumG)+sinVal*(0.140),lumB+cosVal*(-lumB)+sinVal*(-0.283),0,0, + lumR+cosVal*(-lumR)+sinVal*(-(1-lumR)),lumG+cosVal*(-lumG)+sinVal*(lumG),lumB+cosVal*(1-lumB)+sinVal*(lumB),0,0, + 0,0,0,1,0, + 0,0,0,0,1 + ]); + } + + private function multiply(matrix:Array):void + { + var temp:Array; + var i:uint; + + temp = new Array(); + i = 0; + for (var y:uint = 0; y < 5; y++ ) + { + for (var x:uint = 0; x < 5; x++ ) + { + temp[i + x] = data[i ] * matrix[x ] + + data[i+1] * matrix[x + 5] + + data[i+2] * matrix[x + 10] + + data[i+3] * matrix[x + 15] + + (x == 5 ? data[i+5] : 0); + } + i+=5; + } + + setFlatData(temp, true); + } + + private function fixValue(val:int, limit:int):int + { + return Math.min(limit, Math.max(-limit, val)); + } + } +} Index: /as3/gunyarapaint/trunk/colorpicker/src/org/sepy/graphics/filters/BaseImageCustomFilter.as =================================================================== --- /as3/gunyarapaint/trunk/colorpicker/src/org/sepy/graphics/filters/BaseImageCustomFilter.as (リビジョン 2167) +++ /as3/gunyarapaint/trunk/colorpicker/src/org/sepy/graphics/filters/BaseImageCustomFilter.as (リビジョン 2167) @@ -0,0 +1,140 @@ +package org.sepy.graphics.filters +{ + import flash.display.BitmapData; + import flash.geom.Rectangle; + import flash.geom.Point; + import flash.utils.Timer; + import flash.events.TimerEvent; + import flash.events.Event; + + public class BaseImageCustomFilter extends BaseImageFilter + { + private var _y:uint; + private var _src:BitmapData; + private var _dest:BitmapData; + private var _region:Rectangle; + private var _point:Point + private var timer:Timer; + private var _rows_count:uint; + private var _rect:Rectangle; + private var _gap:uint; + protected var fillgap:Boolean; + + private static var ceil:Function = Math.ceil; + + public function BaseImageCustomFilter(rows_count:uint=1) + { + super(true); + + _rows_count = rows_count; + _y = 0; + _gap = 1; + _src = null; + _dest = null; + _region = null; + _point = null; + _rect = null; + timer = null; + fillgap = true; + } + + public function stop():void + { + timer.stop(); + } + + protected function get src():BitmapData + { + return _src; + } + + protected function get dest():BitmapData + { + return _dest; + } + + public function set gap(value:uint):void + { + _gap = value; + } + + public function get gap():uint + { + return _gap; + } + + protected override function doFilter(src:BitmapData, dest:BitmapData, region:Rectangle, point:Point):void + { + // setup + _src = src; + _dest = dest; + _region = region; + _point = point; + _y = _region.y; + + timer = new Timer(10); + timer.addEventListener(TimerEvent.TIMER, nextStep); + + timer.start(); + } + + protected virtual function step(r:uint, g:uint, b:uint, x:uint, y:uint):uint + { + return 0; + } + + private function nextStep(event:Event):void + { + var rect:Rectangle; + + rect = _region; + if(_y > rect.bottom) + { + timer.stop(); + completed(_dest); + }else + { + var color:uint; + var r:uint; + var g:uint; + var b:uint; + var count:uint; + + count = _rows_count; + while(count-- > 0) + { + if(_y > rect.bottom) + { + timer.stop(); + completed(_dest); + + return; + } + + for(var x:uint = rect.x; x < rect.right; x += _gap) + { + if(!_region.containsPoint(new Point(x, _y))) + continue; + + color = _src.getPixel(x, _y); + r = (color >> 16) & 0xFF; + g = (color >> 8) & 0xFF; + b = (color) & 0xFF; + + color = step(r, g, b, x, _y); + + if(_gap == 1) + _dest.setPixel(x, _y, color); + else + if(fillgap) + _dest.fillRect(new Rectangle(x, _y, _gap, _gap), color); + } + _y += _gap; + } + + // mettere a posto + progress(ceil((_y - rect.y) / rect.height * 100), _dest); + } + } + } +} Index: /as3/gunyarapaint/trunk/colorpicker/src/org/sepy/graphics/filters/BaseImageFilter.as =================================================================== --- /as3/gunyarapaint/trunk/colorpicker/src/org/sepy/graphics/filters/BaseImageFilter.as (リビジョン 2167) +++ /as3/gunyarapaint/trunk/colorpicker/src/org/sepy/graphics/filters/BaseImageFilter.as (リビジョン 2167) @@ -0,0 +1,56 @@ +package org.sepy.graphics.filters +{ + import flash.events.EventDispatcher; + import flash.display.BitmapData; + import flash.geom.Rectangle; + import flash.geom.Point; + import org.sepy.events.ImageFilterEvent; + + public class BaseImageFilter extends EventDispatcher + { + private var _delayed:Boolean; + + public function BaseImageFilter(delayed:Boolean = false) + { + super(); + + _delayed = delayed; + } + + public function apply(src:BitmapData, dest:BitmapData, region:Rectangle = null, point:Point = null):void + { + region = region || new Rectangle(0, 0, src.rect.width, src.rect.height); + point = point || new Point(0, 0); + + doFilter(src, dest, region, point); + if(!_delayed) + completed(dest); + } + + protected function progress(p:uint, dest:BitmapData):void + { + var event:ImageFilterEvent; + + event = new ImageFilterEvent(ImageFilterEvent.PROGRESS); + event.dest = dest; + event.progress = p; + + dispatchEvent(event); + } + + protected function completed(dest:BitmapData):void + { + var event:ImageFilterEvent; + + event = new ImageFilterEvent(ImageFilterEvent.COMPLETE); + event.dest = dest; + + dispatchEvent(event); + } + + protected virtual function doFilter(src:BitmapData, dest:BitmapData, rect:Rectangle, point:Point):void + { + + } + } +} Index: /as3/gunyarapaint/trunk/colorpicker/src/org/sepy/graphics/filters/WebcolorsImageFilter.as =================================================================== --- /as3/gunyarapaint/trunk/colorpicker/src/org/sepy/graphics/filters/WebcolorsImageFilter.as (リビジョン 2167) +++ /as3/gunyarapaint/trunk/colorpicker/src/org/sepy/graphics/filters/WebcolorsImageFilter.as (リビジョン 2167) @@ -0,0 +1,26 @@ +package org.sepy.graphics.filters +{ + public class WebcolorsImageFilter extends BaseImageCustomFilter + { + private var round:Function; + + public function WebcolorsImageFilter(rows_count:uint=1) + { + super(rows_count); + + round = Math.round; + } + + protected override function step(r:uint, g:uint, b:uint, x:uint, y:uint):uint + { + var l_round:Function; + + l_round = round; + r = l_round(r / 51) * 51; + g = l_round(g / 51) * 51; + b = l_round(b / 51) * 51; + + return r << 16 | g << 8 | b; + } + } +} Index: /as3/gunyarapaint/trunk/colorpicker/src/org/sepy/utils/ColorUtils.as =================================================================== --- /as3/gunyarapaint/trunk/colorpicker/src/org/sepy/utils/ColorUtils.as (リビジョン 2167) +++ /as3/gunyarapaint/trunk/colorpicker/src/org/sepy/utils/ColorUtils.as (リビジョン 2167) @@ -0,0 +1,211 @@ +package org.sepy.utils +{ + import org.sepy.color.HLS; + import org.sepy.color.LAB; + + public class ColorUtils + { + protected static const RGBMAX:uint = 255; + protected static const HLSMAX:uint = 240; + + + /** + * Convert an rgb color, passed as combination of red green and blue, + * into an HLS instance + * + * @see org.sepy.color.HLS + */ + public static function RGB2HLS(r:uint, g:uint, b:uint):HLS + { + var min:Number; + var max:Number; + var hls:HLS = new HLS(); + + max = Math.max(r,g,b); + min = Math.min(r,g,b); + + var L:Number + var S:Number + var H:Number + + var Rdelta:Number + var Bdelta:Number + var Gdelta:Number + + L = (((max+min)*HLSMAX) + RGBMAX )/(2*RGBMAX); + + if (max == min) { + S = 0; + H = (HLSMAX*2/3); + } else + { + if (L <= (HLSMAX/2)) + { + S = ( ((max-min)*HLSMAX) + ((max+min)/2) ) / (max+min); + } else + { + S = ( ((max-min)*HLSMAX) + ((2*RGBMAX-max-min)/2) ) / (2*RGBMAX-max-min); + } + + Rdelta = ( ((max-r)*(HLSMAX/6)) + ((max-min)/2) ) / (max-min); + Gdelta = ( ((max-g)*(HLSMAX/6)) + ((max-min)/2) ) / (max-min); + Bdelta = ( ((max-b)*(HLSMAX/6)) + ((max-min)/2) ) / (max-min); + + if (r == max) + { + H = Bdelta - Gdelta; + } else if (g == max) + { + H = (HLSMAX/3) + Rdelta - Bdelta; + } else + { + H = ((2*HLSMAX)/3) + Gdelta - Rdelta; + } + + if (H < 0) + { + H += HLSMAX; + } + if (H > HLSMAX) + { + H -= HLSMAX; + } + } + hls.hue = H; + hls.luminance = L + hls.saturation = S; + return hls; + } // RGB2HLS + + + + /** + * Convert an HLS instance color into an rgb value + * + * @see org.sepy.color.HLS + */ + public static function HLS2RGB(hls:HLS):uint + { + var R:uint; + var G:uint; + var B:uint; + + var Magic2:Number; + var Magic1:Number; + + if(hls.saturation == 0) + { + R = G = B= (hls.luminance*RGBMAX)/HLSMAX; + if(hls.hue != (HLSMAX*2/3)) + { + return 0; + } + } else + { + if (hls.luminance <= (HLSMAX/2)) + { + Magic2 = (hls.luminance*(HLSMAX + hls.saturation) + (HLSMAX/2))/HLSMAX; + } else + { + Magic2 = hls.luminance + hls.saturation - ((hls.luminance * hls.saturation) + (HLSMAX/2))/HLSMAX; + } + Magic1 = 2 * hls.luminance - Magic2; + + /* get RGB, change units from HLSMAX to RGBMAX */ + R = (HueToRGB(Magic1,Magic2,hls.hue +(HLSMAX/3))*RGBMAX + (HLSMAX/2))/HLSMAX; + G = (HueToRGB(Magic1,Magic2,hls.hue)*RGBMAX + (HLSMAX/2)) / HLSMAX; + B = (HueToRGB(Magic1,Magic2,hls.hue-(HLSMAX/3))*RGBMAX + (HLSMAX/2))/HLSMAX; + } + return R << 16 | G << 8 | B; + } // HLS2RGB + + + public static function RGB2LAB(red:uint, green:uint, blue:uint):LAB + { + + var result:Array = new Array(3); + + result[0]=(0.490*red+0.310*green+0.200*blue ); + result[1]=(0.177*red+0.812*green+0.011*blue ); + result[2]=(0.000*red+0.010*green+0.990*blue ); + + + result[0]/=255; + result[1]/=255; + result[2]/=255; + + var L:Number; + + if (result[1] > 0.008856) + { + L=116*(Math.pow(result[1],1.0/3.0))-16; + } else { + L=903.3*result[1]; + } + + var a:Number = 500*(flab(result[0])-flab(result[1])); + var b:Number = 200*(flab(result[1])-flab(result[2])); + + return new LAB(L, a, b) + } // RGB2LAb + + + private static function flab(x:Number):Number + { + var res:Number; + if (x>0.008856) + { + res = Math.pow(x,1.0/3.0); + } else + { + res = 7.787* x + (16.0/116.0); + } + return res; + } // flab + + + public static function LAB2RGB(lab:Array):uint + { + + var P:Number = (lab[0]+ 16) / 116.0; + var x:Number = Math.pow((P+lab[1]/500.0),3); + var y:Number = Math.pow(P,3); + var z:Number = Math.pow((P-lab[2]/200.0),3); + + lab[0]=(2.365*x-0.896*y-0.468*z); + lab[1]=(-0.515*x+1.425*y+0.088*z); + lab[2]=(0.005*x-0.014*y+1.009*z); + + return (lab[0]*255) << 16 | (lab[1]*255) << 8 | lab[2]*255 + } // LAB2RGB + + + private static function HueToRGB(n1:Number, n2:Number, hue:Number):Number + { + if (hue < 0) + { + hue += HLSMAX; + } + if (hue > HLSMAX) + { + hue -= HLSMAX; + } + + if (hue < (HLSMAX/6)) + { + return ( n1 + (((n2-n1)*hue+(HLSMAX/12))/(HLSMAX/6)) ); + } + if (hue < (HLSMAX/2)) + { + return ( n2 ); + } + if (hue < ((HLSMAX*2)/3)) + { + return ( n1 + (((n2-n1)*(((HLSMAX*2)/3)-hue)+(HLSMAX/12))/(HLSMAX/6))); + } else + { + return ( n1 ); + } + } + } +} Index: /as3/gunyarapaint/trunk/colorpicker/src/org/sepy/utils/StringUtils.as =================================================================== --- /as3/gunyarapaint/trunk/colorpicker/src/org/sepy/utils/StringUtils.as (リビジョン 2167) +++ /as3/gunyarapaint/trunk/colorpicker/src/org/sepy/utils/StringUtils.as (リビジョン 2167) @@ -0,0 +1,29 @@ +package org.sepy.utils +{ + public class StringUtils + { + + /** + * Fill the passed string of n chars to the right with the passed c char + * + * @param s Source string + * @param c char to be used as fill char + * @param fillCount lenght of the string to be returned + */ + public static function fillRight(s:String, c:String, fillCount:uint):String + { + while(s.length < fillCount){ + s += c.substr(0,1); + } + return s; + } + + public static function fillLeft(s:String, c:String, fillCount:uint):String + { + while(s.length < fillCount){ + s = c.substr(0,1) + s; + } + return s; + } + } +} Index: /as3/gunyarapaint/trunk/colorpicker/src/org/sepy/controls/SColorPicker.as =================================================================== --- /as3/gunyarapaint/trunk/colorpicker/src/org/sepy/controls/SColorPicker.as (リビジョン 2167) +++ /as3/gunyarapaint/trunk/colorpicker/src/org/sepy/controls/SColorPicker.as (リビジョン 2167) @@ -0,0 +1,1123 @@ +package org.sepy.controls +{ + import flash.display.Bitmap; + import flash.display.BitmapData; + import flash.display.GradientType; + import flash.display.Graphics; + import flash.display.MovieClip; + import flash.display.SpreadMethod; + import flash.display.Sprite; + import flash.events.Event; + import flash.events.MouseEvent; + import flash.filters.ColorMatrixFilter; + import flash.geom.ColorTransform; + import flash.geom.Matrix; + import flash.geom.Point; + import flash.geom.Rectangle; + + import mx.containers.Canvas; + import mx.containers.Grid; + import mx.containers.GridItem; + import mx.containers.GridRow; + import mx.containers.HBox; + import mx.containers.TitleWindow; + import mx.containers.VBox; + import mx.controls.Button; + import mx.controls.CheckBox; + import mx.controls.Label; + import mx.controls.Spacer; + import mx.controls.TextInput; + import mx.core.BitmapAsset; + import mx.core.MovieClipAsset; + import mx.core.UIComponent; + import mx.events.CloseEvent; + import mx.events.FlexEvent; + import mx.managers.CursorManager; + import mx.managers.FocusManager; + import mx.managers.IFocusManagerComponent; + + import org.sepy.color.HLS; + import org.sepy.events.ImageFilterEvent; + import org.sepy.events.SPickerEvent; + import org.sepy.graphics.ColorMatrix; + import org.sepy.graphics.filters.WebcolorsImageFilter; + import org.sepy.utils.ColorUtils; + import org.sepy.utils.StringUtils; + import flash.display.DisplayObject; + import flash.display.Stage; + + [Event(name="changing", type="org.sepy.events.SPickerEvent")] + [Event(name="swatchAdd", type="org.sepy.events.SPickerEvent")] + [Event(name="close", type="mx.events.CloseEvent")] + [Event(name="change", type="flash.events.Event")] + + [IconFile("ColorPicker.png")] + public class SColorPicker extends TitleWindow + { + private const BOX_HEIGHT:uint = 200; + private const BOX_WIDTH:uint = 180; + private const COLOR_WIDTH:uint = 60; + private const COLOR_HEIGHT:uint = 40; + private const SLIDER_WIDTH:uint = 22; + private const MAX_STEPS:int = 1000; + + private const c_fillType:String = "linear"; + private const c_colors:Array = [0x000000, 0x000000]; + private const c_alphas:Array = [0, 1]; + private const c_ratios:Array = [0, 255]; + private const c_matrix:Matrix = new Matrix(); + + private const m_fillType:String = "linear" + private var m_colors:Array = [0xFFFFFF, 0x000000] + private var m_alphas:Array = [1, 1] + private var m_ratios:Array = [0, 255] + private const m_matrix:Matrix = new Matrix(); + + private const s_fillType:String = "linear" + private const s_matrix:Matrix = new Matrix(); + private var s_colors:Array = [0xFF0000, 0xFFFF00, 0x00FF00, 0x00FFFF, 0x0000FF, 0xFF00FF, 0xFF0000 ] + private var s_ratios:Array; + private var s_alphas:Array; + + protected var _selectedColor:uint; + protected var _originalColor:int = -1; + protected var _suggested_websafe:uint; + protected var _add_swatch_enabled:Boolean; + + private var _box1:HBox; + private var _slider_mc:UIComponent; + private var _slider_bmp:BitmapData; + private var gradient_bitmap:Bitmap; + private var _websafe_canvas:Canvas; + private var gradient_canvas:Canvas; + private var gradient_mc:UIComponent; + private var gradient_rect:Rectangle; + + private var _buffer:BitmapData; + private var _output:BitmapData; + private var _right_color:UIComponent; + private var _right_safe_mc:UIComponent; + private var _right_safe_bitmap:Bitmap; + + private var sliderDirty:Boolean; + private var matrixDirty:Boolean; + private var dirty:Boolean; + private var slider_down:Boolean; + private var matrix_down:Boolean; + + private var rgb_input:TextInput; + private var r_input:TextInput; + private var g_input:TextInput; + private var b_input:TextInput; + + private var h_input:TextInput; + private var l_input:TextInput; + private var s_input:TextInput; + + private var ok_button:Button; + private var cancel_button:Button; + private var add_swatch_button:Button; + + private var websafe_check:CheckBox; + + private var _picker_enabled:Boolean; + private var pickerDirty:Boolean; + + [Embed(source="/assets/scolorpicker/spicker_assets.swf", symbol="cross_png")] + private var baseClass:Class; + private var _crossair:BitmapAsset; + + [Embed(source="/assets/scolorpicker/spicker_assets.swf", symbol="cross_slider")] + private var sliderClass:Class; + private var _cross_slider:BitmapAsset; + + [Embed(source="/assets/scolorpicker/warning_small.png")] + private var warningClass:Class; + private var warningAsset:BitmapAsset; + + [Embed(source="/assets/scolorpicker/warning_small_disabled.png")] + private var warningClassDisabled:Class; + private var warningAssetDisabled:BitmapAsset; + private var currentCursorID:int = -1; + private var currentStageBuffer:BitmapData; + + [Embed(source="/assets/scolorpicker/picker.png")] + private var pickerClass:Class; + + public static const VERSION:String = "1.0"; + public static const AUTHOR:String = "Alessandro Crugnola"; + + public function SColorPicker() + { + super(); + + s_ratios = new Array(); + s_alphas = new Array(); + + for(var i:uint = 0; i < s_colors.length; i++) + { + s_ratios.push(int((i/(s_colors.length-1))*255)); + s_alphas.push(1); + } + + _slider_bmp = new BitmapData(SLIDER_WIDTH, BOX_HEIGHT, false, 0x00); + } + + + override protected function measure():void + { + super.measure(); + } + + override protected function commitProperties():void + { + // TODO: commitProperties + super.commitProperties(); + + var pt:Point; + + if(dirty) + { + dirty = false; + var s:uint = selectedColor; + var steps:uint = 0; + var r:uint; + var g:uint; + var b:uint; + var rect:Rectangle; + do + { + rect = _output.getColorBoundsRect(0xFFFFFFFF, 0xFF000000+s, true); + s++ + steps++; + } while(rect.width == 0 && s < 0xffffff && steps < MAX_STEPS); + if(rect.width > 0 && rect.height > 0) + { + _crossair.x = rect.x - _crossair.width/2; + _crossair.y = rect.y - _crossair.height/2; + } + setSelectedColor(selectedColor, false); + + } + if(sliderDirty) + { + sliderDirty = false; + pt = new Point(Math.floor(_crossair.x + _crossair.width/2), Math.floor(_crossair.y + _crossair.height/2)); + updateGradient(_slider_bmp.getPixel(_slider_bmp.width/2, _cross_slider.y + _cross_slider.height/2)); + setSelectedColor(_output.getPixel(pt.x, pt.y), false); // TODO: fix here + } + if(matrixDirty){ + matrixDirty = false; + pt = new Point(_crossair.x + _crossair.width/2, _crossair.y + _crossair.height/2) + //changeSliderColor(_output.getPixel(pt.x, pt.y)); + setSelectedColor(_output.getPixel(pt.x, pt.y), false); + } + if(pickerDirty){ + if(picker_enabled){ + this.visible = false; + if(stage) + { + currentStageBuffer = new BitmapData(Math.min(stage.width, 2880), Math.min(stage.height, 2880)); + currentStageBuffer.draw(this.stage); + this.stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseStage_event); + this.stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseStage_event); + } + } else { + if(stage) + { + this.stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseStage_event); + this.stage.removeEventListener(MouseEvent.MOUSE_DOWN, mouseStage_event); + if(currentStageBuffer) + currentStageBuffer.dispose(); + } + } + pickerDirty = false; + } + + add_swatch_button.visible = _add_swatch_enabled; + } + + override protected function childrenCreated():void + { + super.childrenCreated(); + var d:DisplayObject = this; + callLater( + function():void { + gradient_rect = gradient_bitmap.getBounds(d); + } + ); + } + + + override protected function createChildren():void + { + super.createChildren(); + + if(!_box1){ + _box1 = new HBox(); + _box1.percentWidth = 100; + _box1.percentHeight = 100; + } else { + return; + } + + var box2:VBox = new VBox(); + var box3:HBox = new HBox(); + var box4:HBox = new HBox(); + var box5:VBox = new VBox(); + var box6:VBox = new VBox(); + var box7:VBox = new VBox(); + var box8:HBox = new HBox(); + var spacer:Spacer; + + gradient_canvas = new Canvas(); + gradient_canvas.setStyle("borderStyle", "solid"); + gradient_canvas.setStyle("horizontalGap", 0); + gradient_canvas.setStyle("verticalGap", 0); + + // matrix color gradient container + gradient_mc = new UIComponent(); + gradient_mc.width = BOX_WIDTH; + gradient_mc.height = BOX_HEIGHT; + gradient_mc.graphics.beginFill(0xFFFFCC, 1); + gradient_mc.graphics.drawRect(0, 0, BOX_WIDTH, BOX_HEIGHT); + gradient_mc.graphics.endFill(); + + _buffer = createGradientMatrix(BOX_WIDTH, BOX_HEIGHT); + _output = _buffer.clone(); + _crossair = BitmapAsset(new baseClass()); + var mask:UIComponent = new UIComponent(); + mask.width = BOX_WIDTH + mask.height = BOX_HEIGHT; + mask.graphics.beginFill(0x00, 1); + mask.graphics.drawRect(0,0, BOX_WIDTH, BOX_HEIGHT); + mask.graphics.endFill(); + + _crossair.x = - _crossair.width/2 + _crossair.y = - _crossair.height/2 + _crossair.mask = mask; + + box4.setStyle("horizontalGap", 1); + var canv2:Canvas = new Canvas(); + canv2.setStyle("borderStyle", "solid"); + + _slider_mc = new UIComponent(); + _slider_mc.width = SLIDER_WIDTH; + _slider_mc.height = BOX_HEIGHT; + + _cross_slider = BitmapAsset(new sliderClass()); + var cross_slider_mc:UIComponent = new UIComponent(); + cross_slider_mc.width = 10; + cross_slider_mc.height = BOX_HEIGHT + cross_slider_mc.graphics.beginFill(0x00, 0); + cross_slider_mc.graphics.drawRect(0, 0, 15, BOX_HEIGHT); + cross_slider_mc.graphics.endFill(); + _cross_slider.y = -5; + + // original and current color container + var canv3:Canvas = new Canvas(); + canv3.setStyle("borderStyle", "solid"); + canv3.setStyle("borderColor", 0x999999); + _right_color = new UIComponent(); + _right_color.width = COLOR_WIDTH; + _right_color.height = COLOR_HEIGHT; + _right_color.graphics.beginFill(0x00, 1); + _right_color.graphics.drawRect(0, 0, COLOR_WIDTH, COLOR_HEIGHT); + _right_color.graphics.endFill(); + + canv3.addChild(_right_color); + + + _websafe_canvas = new Canvas(); + _websafe_canvas.setStyle("borderStyle", "solid"); + _websafe_canvas.buttonMode = true; + + _right_safe_mc = new UIComponent(); + _right_safe_mc.width = 10; + _right_safe_mc.height = 10; + _right_safe_mc.graphics.beginFill(0x00, 1); + _right_safe_mc.graphics.drawRect(0, 0, 10, 10); + _right_safe_mc.graphics.endFill(); + _right_safe_mc.toolTip = "Suggested web-safe color (click to apply)"; + + _right_safe_bitmap = new Bitmap(new BitmapData( 10, 10,false)); + _right_safe_mc.addChild(_right_safe_bitmap); + + + var warning_ui:UIComponent = new UIComponent(); + warningAsset = BitmapAsset(new warningClass()); + warningAssetDisabled = BitmapAsset(new warningClassDisabled()); + warning_ui.addChild(warningAsset); + warning_ui.addChild(warningAssetDisabled); + + warning_ui.width = warningAsset.width; + warning_ui.height = warningAsset.height; + + box7.addChild(warning_ui); + + + _websafe_canvas.addChild(_right_safe_mc); + box7.addChild(_websafe_canvas); + + box8.addChild(canv3); + box8.addChild(box7); + box5.addChild(box8); + + spacer = new Spacer(); + spacer.height = 1; + box5.addChild(spacer); + + var rgb_grid:Grid = new Grid(); + rgb_grid.setStyle("verticalGap", 3); + rgb_grid.setStyle("horizontalGap", 2); + var rgb_row:GridRow = new GridRow(); + var rgb_item1:GridItem = new GridItem(); + var rgb_item2:GridItem = new GridItem(); + + rgb_item1.setStyle("horizontalGap", 0); + rgb_item2.setStyle("horizontalGap", 0); + + // R field + r_input = new TextInput(); + r_input.condenseWhite = true; + r_input.maxChars = 3 + r_input.restrict = "0-9" + var r_label:Label = new Label(); + r_label.text = "R"; + rgb_item1.addChild(r_label); + rgb_item2.addChild(r_input); + rgb_row.addChild(rgb_item1); + rgb_row.addChild(rgb_item2); + + + // HUE field + rgb_item1 = new GridItem(); + rgb_item2 = new GridItem(); + h_input = new TextInput(); + h_input.condenseWhite = true; + h_input.maxChars = 3 + h_input.restrict = "0-9" + var h_label:Label = new Label(); + h_label.text = "H"; + rgb_item1.addChild(h_label); + rgb_item2.addChild(h_input); + rgb_row.addChild(rgb_item1); + rgb_row.addChild(rgb_item2); + rgb_grid.addChild(rgb_row); + + // G field + rgb_row = new GridRow(); + rgb_item1 = new GridItem(); + rgb_item2 = new GridItem(); + g_input = new TextInput(); + g_input.condenseWhite = true; + g_input.maxChars = 3 + g_input.restrict = "0-9" + var g_label:Label = new Label(); + g_label.text = "G"; + rgb_item1.addChild(g_label); + rgb_item2.addChild(g_input); + rgb_row.addChild(rgb_item1); + rgb_row.addChild(rgb_item2); + + + // LUMINANCE field + rgb_item1 = new GridItem(); + rgb_item2 = new GridItem(); + l_input = new TextInput(); + l_input.condenseWhite = true; + l_input.maxChars = 3 + l_input.restrict = "0-9" + var l_label:Label = new Label(); + l_label.text = "L"; + rgb_item1.addChild(l_label); + rgb_item2.addChild(l_input); + rgb_row.addChild(rgb_item1); + rgb_row.addChild(rgb_item2); + rgb_grid.addChild(rgb_row); + + // B field + rgb_row = new GridRow(); + rgb_item1 = new GridItem(); + rgb_item2 = new GridItem(); + b_input = new TextInput(); + b_input.condenseWhite = true; + b_input.maxChars = 3 + b_input.restrict = "0-9" + var b_label:Label = new Label(); + b_label.text = "B"; + rgb_item1.addChild(b_label); + rgb_item2.addChild(b_input); + rgb_row.addChild(rgb_item1); + rgb_row.addChild(rgb_item2); + + // SATURATION field + rgb_item1 = new GridItem(); + rgb_item2 = new GridItem(); + s_input = new TextInput(); + s_input.condenseWhite = true; + s_input.maxChars = 3 + s_input.restrict = "0-9" + var s_label:Label = new Label(); + s_label.text = "S"; + rgb_item1.addChild(s_label); + rgb_item2.addChild(s_input); + rgb_row.addChild(rgb_item1); + rgb_row.addChild(rgb_item2); + rgb_grid.addChild(rgb_row); + + // RGB field + rgb_row = new GridRow(); + rgb_item1 = new GridItem(); + rgb_item2 = new GridItem(); + rgb_item2.colSpan = 3; + var rgb_label:Label = new Label(); + rgb_label.text = "#" + rgb_input = new TextInput(); + rgb_input.condenseWhite = true; + rgb_input.maxChars = 6 + rgb_input.restrict = "0-9A-F" + rgb_input.percentWidth = 100; + rgb_item1.addChild(rgb_label); + rgb_item2.addChild(rgb_input); + rgb_row.addChild(rgb_item1); + rgb_row.addChild(rgb_item2); + rgb_grid.addChild(rgb_row); + + box5.addChild(rgb_grid); + + ok_button = new Button(); + ok_button.label = "Ok"; + ok_button.percentWidth = 100; + + add_swatch_button = new Button(); + add_swatch_button.label = "Add swatch"; + add_swatch_button.percentWidth = 100; + add_swatch_button.visible = add_swatch; + //add_swatch_button.toolTip = "add current color to picker default colors"; + + cancel_button = new Button(); + cancel_button.label = "Cancel"; + cancel_button.percentWidth = 100; + + + box6.percentHeight = 100; + box6.percentWidth = 100; + box6.setStyle("verticalAlign", "bottom"); + + spacer = new Spacer(); + spacer.height = 2; + + box6.addChild(spacer); + box6.addChild(ok_button); + box6.addChild(cancel_button); + box6.addChild(add_swatch_button); + + + websafe_check = new CheckBox(); + websafe_check.label = "WebSafe Colors"; + + box5.addChild(box6); + + canv2.addChild(_slider_mc); + box4.addChild(canv2); + cross_slider_mc.addChild(_cross_slider); + box4.addChild(cross_slider_mc); + + gradient_bitmap = new Bitmap(_output); + + gradient_mc.addChild(gradient_bitmap); + gradient_mc.addChild(_crossair); + gradient_mc.addChild(mask); + gradient_canvas.addChild(gradient_mc); + + var box9:VBox = new VBox(); + box9.addChild(gradient_canvas); + box9.addChild(websafe_check); + box3.addChild(box9); + + box3.addChild(box4); + box3.addChild(box5); + box2.addChild(box3); + //box2.addChild(websafe_check); + _box1.addChild(box2); + this.addChild(_box1); + + gradient_mc.addEventListener(MouseEvent.MOUSE_DOWN, matrix_mouseEvent); + //gradient_mc.addEventListener(MouseEvent.MOUSE_UP, matrix_mouseEvent); + //gradient_mc.addEventListener(MouseEvent.MOUSE_MOVE, matrix_mouseEvent); + + // added by Tasuku SUENAGA + _slider_mc.addEventListener(MouseEvent.MOUSE_DOWN, slider_mouseEvent); + _slider_mc.addEventListener(MouseEvent.MOUSE_UP, slider_mouseEvent); + _slider_mc.addEventListener(MouseEvent.MOUSE_OUT, slider_mouseEvent); + _slider_mc.addEventListener(MouseEvent.MOUSE_MOVE, slider_mouseEvent); + // end + + cross_slider_mc.addEventListener(MouseEvent.MOUSE_DOWN, slider_mouseEvent); + cross_slider_mc.addEventListener(MouseEvent.MOUSE_UP, slider_mouseEvent); + cross_slider_mc.addEventListener(MouseEvent.MOUSE_OUT, slider_mouseEvent); + cross_slider_mc.addEventListener(MouseEvent.MOUSE_MOVE, slider_mouseEvent); + _right_color.addEventListener(MouseEvent.CLICK, restore_color); + rgb_input.addEventListener( Event.CHANGE, text_rgb_change); + r_input.addEventListener(Event.CHANGE, text_rgb_change); + g_input.addEventListener(Event.CHANGE, text_rgb_change); + b_input.addEventListener(Event.CHANGE, text_rgb_change); + + h_input.addEventListener(Event.CHANGE, text_hls_change); + l_input.addEventListener(Event.CHANGE, text_hls_change); + s_input.addEventListener(Event.CHANGE, text_hls_change); + + ok_button.addEventListener(MouseEvent.CLICK, button_event) + cancel_button.addEventListener(MouseEvent.CLICK, button_event) + websafe_check.addEventListener(Event.CHANGE, websafe_event); + add_swatch_button.addEventListener(MouseEvent.CLICK, button_event); + _right_safe_mc.addEventListener(MouseEvent.CLICK, websafe_click); + + this.addEventListener(CloseEvent.CLOSE, onClose); + this.addEventListener(Event.REMOVED_FROM_STAGE, onClose); + + updateSliderColor(); + } + + private function createGradientMatrix(w:uint, h:uint):BitmapData + { + var mc:Sprite = new Sprite(); + var bmp:BitmapData = new BitmapData(w, h, false, 0x00); + var gr:Graphics = mc.graphics; + mc.width = w + mc.height = h + m_matrix.createGradientBox(w, h, 0, 0, 0); + gr.clear(); + gr.beginGradientFill(m_fillType, m_colors, m_alphas, m_ratios, m_matrix); + gr.drawRect(0, 0, w, h); + gr.endFill() + + c_matrix.createGradientBox(w, h, 90*Math.PI/180, 0, 0); + gr.beginGradientFill(c_fillType, c_colors, c_alphas, c_ratios, c_matrix) + gr.moveTo(0,0) + gr.lineTo(w,0) + gr.lineTo(w, h) + gr.lineTo(0, h) + gr.lineTo(0,0) + gr.endFill(); + + bmp.draw(mc); + return bmp; + } + + /** + * update brightness of the main gradient box display + * based on the selection over the right slider box + */ + private function updateGradient(color:int = -1):void + { + m_colors[1] = color > -1 ? color : _selectedColor; + _buffer = createGradientMatrix(BOX_WIDTH, BOX_HEIGHT); + _output = _buffer.clone(); + gradient_bitmap.bitmapData = _output + } + + + private function updateSliderColor():void + { + changeSliderColor(selectedColor); + } + + /** + * Update display colors, and color RGB/HLS informations + * + */ + private function updateColors(updateGColor:Boolean = true):void + { + var current:IFocusManagerComponent; + var r:uint, g:uint, b:uint; + + _right_color.graphics.beginFill(_selectedColor, 1); + _right_color.graphics.drawRect(0,0, COLOR_WIDTH, COLOR_HEIGHT/2); + _right_color.graphics.endFill(); + _right_color.graphics.beginFill(_originalColor, 1); + _right_color.graphics.drawRect(0, COLOR_HEIGHT/2, COLOR_WIDTH, COLOR_HEIGHT/2); + _right_color.graphics.endFill(); + + r = _selectedColor >> 16; + g = _selectedColor >> 8 & 0xFF; + b = _selectedColor & 0xFF; + + // update websafe suggested color + var sr:uint = Math.round(r / 51) * 51; + var sg:uint = Math.round(g / 51) * 51; + var sb:uint = Math.round(b / 51) * 51; + + _suggested_websafe = sr << 16 | sg << 8 | sb + + + + if(_suggested_websafe != _selectedColor){ + warningAsset.visible = true; + warningAssetDisabled.visible = false; + } else { + warningAsset.visible = false; + warningAssetDisabled.visible = true; + } + _right_safe_bitmap.bitmapData.fillRect(_right_safe_bitmap.bitmapData.rect, _suggested_websafe); + + if(!matrix_down && !slider_down){ + try{ + current = focusManager.getFocus() + } catch(e:Error){ + + } + } + + if(current != r_input){ + r_input.text = r.toString(); + } + + if(current != g_input){ + g_input.text = g.toString(); + } + + if(current != b_input){ + b_input.text = b.toString(); + } + + if(current != rgb_input){ + rgb_input.text = StringUtils.fillLeft(_selectedColor.toString(16), "0", 6); + } + + var _hls:HLS = ColorUtils.RGB2HLS(r,g,b); + + if(current != h_input){ + h_input.text = _hls.hue.toString() + } + + if(current != l_input){ + l_input.text = _hls.luminance.toString() + } + + if(current != s_input){ + s_input.text = _hls.saturation.toString() + } + + if(updateGColor) + updateGradient(_selectedColor); + } + + + private function setSelectedColor(c:uint, updateGColor:Boolean = true):void + { + _selectedColor = c; + updateColors(updateGColor); + var evt:SPickerEvent = new SPickerEvent(SPickerEvent.CHANGING); + evt.value = _selectedColor; + dispatchEvent(evt); + } + + + /** + * change the slider color based on the selection + * of the matrix color cross-air + * + */ + private function changeSliderColor(c:uint):void + { + // TODO: changeSliderColor + + var _m:Matrix = new Matrix(); + var _c:Array = [s_colors[s_colors.length-1], 0x000000, 0xFFFFFF] + var gr:Graphics = _slider_mc.graphics; + var w:uint = SLIDER_WIDTH; + var h:uint = _slider_mc.height; + + _m.createGradientBox(SLIDER_WIDTH, 20, 90*Math.PI/180, 0, _slider_mc.height - 20); + + s_matrix.createGradientBox(SLIDER_WIDTH, BOX_HEIGHT - 20, 90*Math.PI/180); + + _slider_mc.graphics.clear(); + _slider_mc.graphics.beginGradientFill(GradientType.LINEAR, s_colors, s_alphas, s_ratios, s_matrix, SpreadMethod.PAD, s_fillType); + _slider_mc.graphics.drawRect(0, 0, SLIDER_WIDTH, _slider_mc.height - 20); + + _slider_mc.graphics.beginGradientFill(GradientType.LINEAR, _c, [1,1,1], [0,127,200], _m, SpreadMethod.PAD, s_fillType); + _slider_mc.graphics.drawRect(0, _slider_mc.height - 20, SLIDER_WIDTH, 20); + + + _slider_mc.graphics.endFill(); + _slider_bmp.draw(_slider_mc); + + var s:uint = c; + var steps:uint = 0; + var rect:Rectangle; + var r:uint; + var g:uint; + var b:uint; + do + { + rect = _slider_bmp.getColorBoundsRect(0xFFFFFFFF, 0xFF000000+s, true); + steps++; + + r = s >> 16 & 0xff + g = s >> 8 & 0xff + b = s & 0xff; + r = Math.min(r+1, 255); + g = Math.min(g+1, 255); + b = Math.min(b+1, 255); + + s = r << 16 | g << 8 | b + } while(rect.width == 0 && s > 0 && steps < MAX_STEPS); + + _cross_slider.y = rect.bottom - _cross_slider.height/2 + setSelectedColor(c); + } + + /** + * Events dispatched from the right slider bar + * + */ + private function slider_mouseEvent(evt:MouseEvent):void + { + if(evt.type == MouseEvent.MOUSE_DOWN) + { + // added by Tasuku SUENAGA + _cross_slider.y = evt.localY - (_cross_slider.height / 2); + // end + slider_down = true; + websafe_check.selected = false; + } + if(evt.type == MouseEvent.MOUSE_UP) { + slider_down = false; + } else if ((evt.type == MouseEvent.MOUSE_MOVE || + evt.type == MouseEvent.MOUSE_DOWN) && + slider_down && + evt.localY < _slider_mc.height && + evt.localY >= _slider_mc.y) { + _cross_slider.y = evt.localY - (_cross_slider.height/2); + sliderDirty = true; + evt.updateAfterEvent(); + invalidateProperties(); + } else if(evt.type == MouseEvent.MOUSE_OUT) + { + slider_down = false; + } + } + + + /** + * Events dispatched from the gradient cross-air + * + */ + private function matrix_mouseEvent(evt:MouseEvent):void + { + if(evt.type == MouseEvent.MOUSE_DOWN) + { + matrix_down = true; + _crossair.y = evt.localY - (_crossair.height/2) + _crossair.x = evt.localX - (_crossair.width/2) + matrixDirty = true; + evt.updateAfterEvent(); + invalidateProperties(); + + this.addEventListener(MouseEvent.MOUSE_MOVE, matrix_mouseEvent); + this.addEventListener(MouseEvent.MOUSE_UP, matrix_mouseEvent); + if(stage) + stage.addEventListener(MouseEvent.MOUSE_MOVE, matrix_mouseEvent); + } else if(evt.type == MouseEvent.MOUSE_UP) + { + matrix_down = false; + this.removeEventListener(MouseEvent.MOUSE_MOVE, matrix_mouseEvent); + this.removeEventListener(MouseEvent.MOUSE_UP, matrix_mouseEvent); + if(stage) + stage.removeEventListener(MouseEvent.MOUSE_MOVE, matrix_mouseEvent); + } else if(evt.type == MouseEvent.MOUSE_MOVE && matrix_down) + { + if(evt.currentTarget is Stage) + { + if(!this.getBounds(stage).contains(stage.mouseX, stage.mouseY)) + { + matrix_down = false; + this.removeEventListener(MouseEvent.MOUSE_MOVE, matrix_mouseEvent); + this.removeEventListener(MouseEvent.MOUSE_UP, matrix_mouseEvent); + stage.removeEventListener(MouseEvent.MOUSE_MOVE, matrix_mouseEvent); + return; + } + } + + var pt:Point = new Point(this.mouseX, this.mouseY); + + if(gradient_mc.mouseX < 0) + pt.x = gradient_rect.x; + else if(gradient_rect.right - 1 < this.mouseX) + pt.x = gradient_rect.right - 1 + + if(gradient_mc.mouseY < 0) + pt.y = gradient_rect.y + else if(gradient_rect.bottom - 1 < this.mouseY) + pt.y = gradient_rect.bottom -1 + + _crossair.y = (pt.y - (_crossair.height/2)) - gradient_rect.y + _crossair.x = pt.x - ((_crossair.width/2)) - gradient_rect.x + matrixDirty = true; + evt.updateAfterEvent(); + invalidateProperties(); + + } + } + + /** + * User click on the original starting color box + * + */ + private function restore_color(evt:MouseEvent):void + { + if(evt.localY > UIComponent(evt.target).height/2){ + selectedColor = int(_originalColor); + } + } + + /** + * User change values from the text input (RGB) + * + */ + private function text_rgb_change(evt:Event):void + { + var nextColor:uint; + var textColor:String = TextInput(evt.target).text; + switch(evt.target){ + case rgb_input: + nextColor = parseInt(textColor, 16); + break; + case r_input: + nextColor = uint( uint(textColor) << 16 | uint(g_input.text) << 8 | uint(b_input.text) ) + break; + case g_input: + nextColor = uint( uint(r_input.text) << 16 | uint(textColor) << 8 | uint(b_input.text) ) + break; + case b_input: + nextColor = uint( uint(r_input.text) << 16 | uint(g_input.text) << 8 | uint(textColor) ) + break; + } + websafe_check.selected = false; + changeSliderColor(nextColor); + } + + /** + * User change values from the text input (HLS) + * + */ + private function text_hls_change(evt:Event):void + { + var _hls:HLS; + var nextColor:uint; + var textColor:String = TextInput(evt.target).text; + switch(evt.target){ + case h_input: + _hls = new HLS( uint(textColor), uint(l_input.text), uint(s_input.text)) + break; + case l_input: + _hls = new HLS(uint(h_input.text), uint(textColor) , uint(s_input.text)) + break; + case s_input: + _hls = new HLS(uint(h_input.text), uint(h_input.text), uint(textColor)) + break; + } + nextColor = ColorUtils.HLS2RGB(_hls); + websafe_check.selected = false; + changeSliderColor(nextColor); + } + + + + /** + * ok and cancel button events + * + */ + private function button_event(evt:MouseEvent):void + { + if(evt.target == ok_button){ + dispatchEvent(new Event(Event.CHANGE)); + } else if(evt.target == add_swatch_button){ + var event:SPickerEvent = new SPickerEvent(SPickerEvent.SWATCH_ADD); + event.value = _selectedColor; + dispatchEvent(event); + } else { + dispatchEvent(new CloseEvent(CloseEvent.CLOSE)); + } + } + + + /** + * Perform internal actions before closing the window + * + */ + private function onClose(evt:Event):void + { + CursorManager.removeAllCursors(); + if(currentStageBuffer){ + currentStageBuffer.dispose(); + } + if(evt.type == Event.REMOVED_FROM_STAGE){ + cleanup(); + } + } + + /** + * Clean-up everything before removing + * this component from the display list + * + */ + private function cleanup():void + { + if(this.stage.hasEventListener(MouseEvent.MOUSE_MOVE)){ + this.stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseStage_event); + this.stage.removeEventListener(MouseEvent.MOUSE_DOWN, mouseStage_event); + } + if(currentStageBuffer){ + currentStageBuffer.dispose(); + } + } + + /** + * switch between web-safe or regular colors + * + */ + private function websafe_event(evt:Event):void + { + if(websafe_check.selected){ + CursorManager.setBusyCursor(); + var tmp:BitmapData = new BitmapData(_buffer.width, _buffer.height); + var filter:WebcolorsImageFilter = new WebcolorsImageFilter(40); + filter.addEventListener(ImageFilterEvent.COMPLETE, onwebsafe_complete) + filter.apply(_buffer, tmp); + this.enabled = false; + } else { + _output = _buffer.clone(); + gradient_bitmap.bitmapData = _output; + + matrixDirty = true; // TODO: websafe_event + invalidateProperties(); + + } + } + + + /** + * Mouse stage event + * currently dispatched when outside picker is enabled + * + */ + private function mouseStage_event(evt:MouseEvent):void + { + var pt:Point = new Point(evt.stageX, evt.stageY); + if(evt.type == MouseEvent.MOUSE_MOVE){ + if(this.getRect(stage).containsPoint(pt)){ + if(CursorManager.currentCursorID == currentCursorID){ + CursorManager.removeCursor(currentCursorID); + } + } else { + if(CursorManager.currentCursorID != currentCursorID){ + currentCursorID = CursorManager.setCursor(pickerClass, 2, 0, -17); + } + selectedColor = currentStageBuffer.getPixel(pt.x, pt.y); + } + } else if(evt.type == MouseEvent.MOUSE_DOWN){ + if(!this.getRect(stage).containsPoint(pt)){ + selectedColor = currentStageBuffer.getPixel(pt.x, pt.y); + dispatchEvent(new Event(Event.CHANGE)); + } + } + } + + + private function websafe_click(evt:MouseEvent):void + { + // TODO: websafe_click + selectedColor = int(_suggested_websafe); + } + + private function onwebsafe_complete(evt:ImageFilterEvent):void + { + CursorManager.removeAllCursors(); + this.enabled = true; + + _output = evt.dest; + gradient_bitmap.bitmapData = _output + + matrixDirty = true; // TODO: websafe_event + invalidateProperties(); + } + + public function get selectedColor():uint + { + return _selectedColor; + } + + public function set selectedColor(i:uint):void + { + //if(i != _selectedColor){ + _selectedColor = i; + if(_originalColor < 0){ + _originalColor = i; + } + dirty = true; + invalidateProperties(); + //} + } + + /** + * Return the original color (defined on window opening) + * @return + * + */ + public function get originalColor():uint + { + return _originalColor; + } + + + /** + * Return the suggested websafe color + * @return + * + */ + public function get suggested_websafe():uint + { + return _suggested_websafe; + } + + + /** + * Display the 'add swatch' button + * @param value + * @see org.sepy.events.SPickerEvent.SWATCH_ADD + */ + public function set add_swatch(value:Boolean):void + { + _add_swatch_enabled = value; + invalidateProperties(); + } + + public function get add_swatch():Boolean + { + return _add_swatch_enabled; + } + + + + /** + * Enable/Disable the possibility to pick color + * from the stage DisplayObject + * + */ + public function set picker_enabled(value:Boolean):void + { + _picker_enabled = value; + pickerDirty = true; + invalidateProperties() + } + + public function get picker_enabled():Boolean + { + return _picker_enabled; + } + } +} Index: /as3/gunyarapaint/trunk/colorpicker/src/org/sepy/events/SPickerEvent.as =================================================================== --- /as3/gunyarapaint/trunk/colorpicker/src/org/sepy/events/SPickerEvent.as (リビジョン 2167) +++ /as3/gunyarapaint/trunk/colorpicker/src/org/sepy/events/SPickerEvent.as (リビジョン 2167) @@ -0,0 +1,37 @@ +// ActionScript file + +package org.sepy.events +{ + import flash.events.Event; + + /** + * Event dispatched from the Color Picker component + * + */ + public class SPickerEvent extends Event + { + + /** + * dispatched every time the internal color selection + * is changing + */ + public static const CHANGING:String = "changing"; + + /** + * + */ + public static const SWATCH_ADD:String = "swatchAdd"; + + public var value:uint; + + public function SPickerEvent(type:String, bubbles:Boolean = false, cancelable:Boolean = false) + { + super(type, bubbles, cancelable); + } + + override public function clone():Event + { + return new SPickerEvent(type, bubbles, cancelable); + } + } +} Index: /as3/gunyarapaint/trunk/colorpicker/src/org/sepy/events/ImageFilterEvent.as =================================================================== --- /as3/gunyarapaint/trunk/colorpicker/src/org/sepy/events/ImageFilterEvent.as (リビジョン 2167) +++ /as3/gunyarapaint/trunk/colorpicker/src/org/sepy/events/ImageFilterEvent.as (リビジョン 2167) @@ -0,0 +1,27 @@ +package org.sepy.events +{ + import flash.events.Event; + import flash.display.BitmapData; + + public class ImageFilterEvent extends Event + { + public static const COMPLETE:String = "ImageFilterEvent_complete"; + public static const PROGRESS:String = "ImageFilterEvent_progress";; + + public var dest:BitmapData; + public var progress:uint; + + public function ImageFilterEvent(type:String) + { + super(type, false, false); + + dest = null; + progress = 0; + } + + public override function clone():Event + { + return new ImageFilterEvent(type); + } + } +} Index: /as3/gunyarapaint/trunk/colorpicker/src/org/sepy/geom/Array2d.as =================================================================== --- /as3/gunyarapaint/trunk/colorpicker/src/org/sepy/geom/Array2d.as (リビジョン 2167) +++ /as3/gunyarapaint/trunk/colorpicker/src/org/sepy/geom/Array2d.as (リビジョン 2167) @@ -0,0 +1,106 @@ +package org.sepy.geom +{ + public class Array2d + { + protected var data:Array; + protected var _w:uint; + protected var _h:uint; + protected var dirty:Boolean; + + public function Array2d(w:uint, h:uint) + { + data = new Array(w * h); + + _w = w; + _h = h; + + dirty = true; + } + + public function get width():uint + { + return _w; + } + + public function get height():uint + { + return _h; + } + + public function get length():uint + { + return _w * _h; + } + + public function get flatData():Array + { + return data; + } + + public function fill(value:Number):void + { + var i:int; + + for(i = 0; i < data.length; ++i) + data[i] = value; + + dirty = true; + } + + public function setAt(x:uint, y:uint, value:Number):void + { + checkBounds(x, y); + + data[(y * _w) + x] = value; + + dirty = true; + } + + public function getAt(x:uint, y:uint):Number + { + checkBounds(x, y); + + return data[(y * _w) + x]; + } + + public function sumValues():Number + { + var sum:Number; + + sum = 0; + + for(var i:uint = 0; i < data.length; ++i) + sum += data[i]; + + return sum; + } + + public function clone():Array2d + { + var cloned:Array2d; + + cloned = new Array2d(_w, _h); + cloned.setFlatData(data); + + return cloned; + } + + protected virtual function setFlatData(new_data:Array, copy:Boolean=false):void + { + if(new_data.length != data.length) + throw new ArgumentError("data assigned trought setFlatData MUST be the same length of the array"); + + if(copy) + new_data = new_data.slice(); + + data = new_data; + dirty = true; + } + + private function checkBounds(x:uint, y:uint):void + { + if((x < 0 || x > _w) || (y < 0 || y > _h)) + throw new ArgumentError("Out of bound Array2d indexes"); + } + } +} Index: /as3/gunyarapaint/trunk/colorpicker/src/org/sepy/geom/Matrix2d.as =================================================================== --- /as3/gunyarapaint/trunk/colorpicker/src/org/sepy/geom/Matrix2d.as (リビジョン 2167) +++ /as3/gunyarapaint/trunk/colorpicker/src/org/sepy/geom/Matrix2d.as (リビジョン 2167) @@ -0,0 +1,38 @@ +package org.sepy.geom +{ + public class Matrix2d extends Array2d + { + private var _identity:Array; + + public function Matrix2d(w:uint, h:uint) + { + super(w, h); + + _identity = null; + } + + public function get IDENTITY():Array + { + if(_identity == null) + { + _identity = new Array(_w * _h); + for(var y:uint = 0; y < _h; ++y) + for(var x:uint = 0; x < _w; ++x) + _identity[(y * _w) + x] = (x == y) ? 1 : 0; + } + + return _identity; + } + + protected override function setFlatData(new_data:Array, copy:Boolean=false):void + { + // Fix the matrix to the given bounds + if(new_data.length < length) + new_data = new_data.slice(0, new_data.length).concat(IDENTITY.slice(new_data.length, length)); + else if(new_data.length > length) + new_data = new_data.slice(0, length); + + super.setFlatData(new_data, copy); + } + } +} Index: /as3/gunyarapaint/trunk/colorpicker/src/org/sepy/core/sepy_internal.as =================================================================== --- /as3/gunyarapaint/trunk/colorpicker/src/org/sepy/core/sepy_internal.as (リビジョン 2167) +++ /as3/gunyarapaint/trunk/colorpicker/src/org/sepy/core/sepy_internal.as (リビジョン 2167) @@ -0,0 +1,5 @@ +package org.sepy.core +{ + +public namespace sepy_internal = "http://www.sephiroth.it/2006/flex/mx/internal"; +} Index: /as3/gunyarapaint/trunk/colorpicker/src/org/sepy/color/LAB.as =================================================================== --- /as3/gunyarapaint/trunk/colorpicker/src/org/sepy/color/LAB.as (リビジョン 2167) +++ /as3/gunyarapaint/trunk/colorpicker/src/org/sepy/color/LAB.as (リビジョン 2167) @@ -0,0 +1,16 @@ +package org.sepy.color +{ + public class LAB + { + public var l:Number; + public var a:Number; + public var b:Number; + + public function LAB(_l:Number, _a:Number, _b:Number) + { + l = _l + a = _a + b = _b + } + } +} Index: /as3/gunyarapaint/trunk/colorpicker/src/org/sepy/color/HLS.as =================================================================== --- /as3/gunyarapaint/trunk/colorpicker/src/org/sepy/color/HLS.as (リビジョン 2167) +++ /as3/gunyarapaint/trunk/colorpicker/src/org/sepy/color/HLS.as (リビジョン 2167) @@ -0,0 +1,76 @@ +package org.sepy.color +{ + /** + * The HSL color space, also called HLS or HSI, stands for Hue, Saturation, Lightness + * (also Luminance or Luminosity) / Intensity. While HSV (Hue, Saturation, Value) + * can be viewed graphically as a color cone or hexcone, HSL can be drawn as a + * double cone or double hexcone as well as a sphere. Both systems are non-linear + * deformations of the RGB colour cube. + * + */ + public class HLS + { + private var _hue:uint; + private var _luminance:uint; + private var _saturation:uint; + + private static var min_func:Function = Math.min; + private static var max_func:Function = Math.max; + + public function HLS(hh:uint = 0, ll:uint = 0, ss:uint = 0):void + { + _hue = hh; + _luminance = ll; + _saturation = ss; + } + + /** + * 0-240 value + * + */ + public function get hue():uint + { + return _hue + } + + /** + * 0 - 240 value + * + */ + public function get luminance():uint + { + return _luminance + } + + /** + * 0 - 240 value + */ + public function get saturation():uint + { + return _saturation; + } + + public function set hue(value:uint):void + { + _hue = checkBounds(value, 0, 240); + } + + public function set luminance(value:uint):void + { + _luminance = checkBounds(value, 0, 240); + } + + public function set saturation(value:uint):void + { + _saturation = checkBounds(value, 0, 240); + } + + private function checkBounds(value:uint, min:uint, max:uint):uint + { + if(value < min || value > max) + value = min_func(max, max_func(min, value)); + + return value; + } + } +} Index: /as3/gunyarapaint/trunk/colorpicker/src/test_colorpicker.mxml =================================================================== --- /as3/gunyarapaint/trunk/colorpicker/src/test_colorpicker.mxml (リビジョン 2167) +++ /as3/gunyarapaint/trunk/colorpicker/src/test_colorpicker.mxml (リビジョン 2167) @@ -0,0 +1,95 @@ + + + + + + + + + + + + + + + global { + modal-transparency-blur: 0; + modal-transparency: false; + } + + Application { + backgroundColor: #ffffff; + backgroundGradientColors: #ffffff, #68808c; + } + + Panel { + borderStyle: solid; + borderAlpha: 1; + borderThickness: 0; + roundedBottomCorners: false; + backgroundAlpha: 1; + highlightAlphas: 1, 0.42; + headerColors: #000000, #ffffff; + titleStyleName: "mypanelTitle"; + } + + .mypanelTitle { + color: #ffffff; + } + + + Index: /as3/gunyarapaint/trunk/colorpicker/.actionScriptProperties =================================================================== --- /as3/gunyarapaint/trunk/colorpicker/.actionScriptProperties (リビジョン 2167) +++ /as3/gunyarapaint/trunk/colorpicker/.actionScriptProperties (リビジョン 2167) @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + Index: /as3/gunyarapaint/trunk/colorpicker/.settings/org.eclipse.core.resources.prefs =================================================================== --- /as3/gunyarapaint/trunk/colorpicker/.settings/org.eclipse.core.resources.prefs (リビジョン 2167) +++ /as3/gunyarapaint/trunk/colorpicker/.settings/org.eclipse.core.resources.prefs (リビジョン 2167) @@ -0,0 +1,3 @@ +#Wed Dec 03 18:13:47 JST 2008 +eclipse.preferences.version=1 +encoding/=utf-8