<?xml version="1.0" encoding="utf-8"?>
<s:TitleWindow xmlns:fx="http://ns.adobe.com/mxml/2009"
               xmlns:s="library://ns.adobe.com/flex/spark"
               xmlns:mx="library://ns.adobe.com/flex/mx"
               width="430"
               height="318"
               styleName="colorPickerPanel"
               title="ColorPicker"
               visible="true"
               close="cancelMe();"
               creationComplete="initColorPicker();">
  <s:VGroup width="100%" height="100%" />

  <mx:HBox x="10"
           y="10"
           width="260"
           height="260"
           borderStyle="inset">
    <mx:Image x="0"
              y="0"
              width="256"
              height="256"
              id="CanvasPicker"
              mouseMove="doPickerMove(event);"
              mouseDown="doPickerDown(event);"
              mouseUp="doPickerUp(event);" />
  </mx:HBox>

  <mx:HBox x="279"
           y="10"
           width="30"
           height="260"
           borderStyle="inset" />
  <mx:Image x="276"
            y="12"
            width="36"
            height="256"
            id="CanvasHue"
            mouseMove="doHueMove(event);"
            mouseDown="doHueDown(event);"
            mouseUp="doHueUp(event);" />

  <mx:HBox x="330"
           y="10"
           width="68"
           height="86"
           borderStyle="inset">
    <mx:Image x="0"
              y="0"
              width="64"
              height="82"
              id="CanvasColor" />
  </mx:HBox>

  <mx:Button x="330"
             y="217"
             label="Cancel"
             width="68"
             id="ButtonCancel"
             click="cancelMe();"
             fontWeight="normal" />
  <mx:Button x="330"
             y="247"
             label="OK"
             width="68"
             id="ButtonOK"
             click="okMe();" />

  <fx:Script>
    <![CDATA[
      import mx.managers.PopUpManager;
      import mx.graphics.BitmapFill;
      import mx.controls.Image;
      import mx.core.UIComponent;
      import mx.core.mx_internal;
      use namespace mx_internal;
      import flash.display.*;

      private var red:Number = 0;
      private var green:Number = 0;
      private var blue:Number = 0;

      private var ored:Number = 0;
      private var ogreen:Number = 0;
      private var oblue:Number = 0;

      private var hue:Number = 0;
      private var saturation:Number = 0;
      private var lightness:Number = 0;

      private var colorArea:Sprite;
      private var handleLeft:Sprite;
      private var handleRight:Sprite;
      private var handlePicker:Sprite;
      private var colorPreview:Sprite;

      private var currentDragger:Sprite;

      public var lastColor:Number = 0;


      private function okMe():void
      {
        PopUpManager.removePopUp(this);
      }

      private function cancelMe():void
      {
        setColorRGB(lastColor);
        PopUpManager.removePopUp(this);
      }

      private function updateImagePickerColor():void
      {
        var w:Number = CanvasPicker.width;
        var h:Number = CanvasPicker.height;
        var rgb:Array = HSB2RGB(hue, 1, 1);
        colorArea.graphics.clear();
        colorArea.graphics.beginFill(uint((Math.round(rgb[0] * 255)) << 16) |
                                     uint((Math.round(rgb[1] * 255)) << 8) |
                                     uint(Math.round(rgb[2] * 255)));
        colorArea.graphics.drawRect(0, 0, w, h);
      }

      private function updateColorPreview():void
      {
        var w:Number = CanvasColor.width;
        var h:Number = CanvasColor.height;
        colorPreview.graphics.clear();
        colorPreview.graphics.beginFill(uint((Math.round(red * 255)) << 16) |
                                        uint((Math.round(green * 255)) << 8) |
                                        uint(Math.round(blue * 255)));
        colorPreview.graphics.drawRect(0, 0, w, h / 2);
        colorPreview.graphics.beginFill(uint((Math.round(ored * 255)) << 16) |
                                        uint((Math.round(ogreen * 255)) << 8) |
                                        uint(Math.round(oblue * 255)));
        colorPreview.graphics.drawRect(0, h / 2, w, h / 2);
      }

      private function updateImagePickerHue():void
      {
        handleRight.y = handleLeft.y = hue * 255;
      }

      private function updateImagePicker():void
      {
        handlePicker.x = saturation * 255;
        handlePicker.y = 255 - (lightness * 255);
      }

      private function HSB2RGB(H:Number, S:Number, B:Number):Array
      {
        var r:Number = 0;
        var g:Number = 0;
        var b:Number = 0;

        if (S == 0)
        {
          r = B;
          g = r;
          b = r;
        }
        else
        {
          var h:Number = (H - Math.floor(hue)) * 6.0;
          var f:Number = h - Math.floor(h);

          var p:Number = B * (1.0 - S);
          var q:Number = B * (1.0 - S * f);
          var t:Number = B * (1.0 - (S * (1.0 - f)));

          switch (Math.floor(h))
          {
            case 0:
              r = B;
              g = t;
              b = p;
              break;
            case 1:
              r = q;
              g = B;
              b = p;
              break;
            case 2:
              r = p;
              g = B;
              b = t;
              break;
            case 3:
              r = p;
              g = q;
              b = B;
              break;
            case 4:
              r = t;
              g = p;
              b = B;
              break;
            case 5:
              r = B;
              g = p;
              b = q;
              break;
          }
        }
        return [r, g, b];
      }

      private function RGB2HSL(r:Number, g:Number, b:Number):Array
      {
        var H:Number;
        var S:Number;
        var B:Number;

        var cmax:Number = (r > g) ? r : g;
        if (b > cmax)
        {
          cmax = b;
        }
        var cmin:Number = (r < g) ? r : g;
        if (b < cmin)
        {
          cmin = b;
        }
        B = cmax;
        if (cmax != 0)
        {
          S = (cmax - cmin) / cmax;
        }
        else
        {
          S = 0;
        }
        if (S == 0)
        {
          H = 0;
        }
        else
        {
          var redc:Number = (cmax - r) / (cmax - cmin);
          var greenc:Number = (cmax - g) / (cmax - cmin);
          var bluec:Number = (cmax - b) / (cmax - cmin);
          if (r == cmax)
          {
            H = bluec - greenc;
          }
          else if (g == cmax)
          {
            H = 2.0 + redc - bluec;
          }
          else
          {
            H = 4.0 + greenc - redc;
          }
          H = H / 6.0;
          if (H < 0)
          {
            H = H + 1.0;
          }
        }
        return [H, S, B];
      }

      private function initImagePicker():void
      {

        colorArea = new Sprite();

        var w:Number = CanvasPicker.width;
        var h:Number = CanvasPicker.height;

        colorArea.graphics.beginFill(0xFF0000);
        colorArea.graphics.drawRect(0, 0, w, h);
        CanvasPicker.addChild(colorArea);

        var whiteArea:Sprite = new Sprite();
        var matrix:Matrix = new Matrix();
        matrix.createGradientBox(w, h, 0, 0, 0);
        whiteArea.graphics.beginGradientFill(GradientType.LINEAR, [0xFFFFFF, 0x000000], [1, 1], [0, 255],
                                             matrix);
        whiteArea.graphics.drawRect(0, 0, w, h);
        whiteArea.blendMode = "screen";
        CanvasPicker.addChild(whiteArea);

        var blackArea:Sprite = new Sprite();
        matrix.createGradientBox(w, h, Math.PI / 2, 0, 0);
        blackArea.graphics.beginGradientFill(GradientType.LINEAR, [0xFFFFFF, 0x000000], [1, 1], [0, 255],
                                             matrix);
        blackArea.graphics.drawRect(0, 0, w, h);
        blackArea.blendMode = "multiply";
        CanvasPicker.addChild(blackArea);

        handlePicker = new Sprite();
        handlePicker.graphics.lineStyle(2, 0x000000, 1);
        handlePicker.graphics.drawCircle(0, 0, 4.5);
        handlePicker.graphics.endFill();
        handlePicker.graphics.lineStyle(1, 0xFFFFFF, 1);
        handlePicker.graphics.drawCircle(0, 0, 4);
        CanvasPicker.addChild(handlePicker);
      }

      private function initImageHue():void
      {

        var hueBitmap:BitmapData = new BitmapData(26, 256, false);
        for (var y:int = 0; y <= 256; y++)
        {
          var hsl:Array = HSB2RGB((1 / 256) * y, 1, 1);
          hueBitmap.fillRect(new Rectangle(0, y, 32, 1), (uint(hsl[0] * 255) << 16) |
                             (uint(hsl[1] * 255) << 8) |
                             (uint(hsl[2] * 255)));
        }
        var hueArea:Bitmap = new Bitmap(hueBitmap);
        hueArea.x = 5;
        CanvasHue.addChild(hueArea);

        handleLeft = new Sprite();

        handleLeft.graphics.beginFill(0x000000, .2);
        handleLeft.graphics.moveTo(-1, -4);
        handleLeft.graphics.lineTo(7, 2);
        handleLeft.graphics.lineTo(-1, 8);
        handleLeft.graphics.endFill();
        handleLeft.graphics.beginFill(0x000000, .2);
        handleLeft.graphics.moveTo(-1, -5);
        handleLeft.graphics.lineTo(7, 1);
        handleLeft.graphics.lineTo(-1, 7);
        handleLeft.graphics.endFill();
        handleLeft.graphics.beginFill(0x000000);
        handleLeft.graphics.moveTo(-1, -6);
        handleLeft.graphics.lineTo(7, 0);
        handleLeft.graphics.lineTo(-1, 6);
        handleLeft.graphics.endFill();
        handleLeft.graphics.beginFill(0xcccccc);
        handleLeft.graphics.moveTo(0, -4);
        handleLeft.graphics.lineTo(5, 0);
        handleLeft.graphics.lineTo(0, 4);
        handleLeft.graphics.beginFill(0xffffff);
        handleLeft.graphics.moveTo(0, -4);
        handleLeft.graphics.lineTo(3, -2);
        handleLeft.graphics.lineTo(0, 0);
        handleLeft.graphics.endFill();
        handleLeft.x = 1;
        handleLeft.y = 0;
        CanvasHue.addChild(handleLeft);

        handleRight = new Sprite();
        handleRight.graphics.beginFill(0x000000, .2);
        handleRight.graphics.moveTo(4, -4);
        handleRight.graphics.lineTo(-4, 2);
        handleRight.graphics.lineTo(4, 8);
        handleRight.graphics.endFill();
        handleRight.graphics.beginFill(0x000000, .2);
        handleRight.graphics.moveTo(4, -5);
        handleRight.graphics.lineTo(-4, 1);
        handleRight.graphics.lineTo(4, 7);
        handleRight.graphics.endFill();
        handleRight.graphics.beginFill(0x000000);
        handleRight.graphics.moveTo(4, -6);
        handleRight.graphics.lineTo(-4, 0);
        handleRight.graphics.lineTo(4, 6);
        handleRight.graphics.endFill();
        handleRight.graphics.beginFill(0xcccccc);
        handleRight.graphics.moveTo(3, -4);
        handleRight.graphics.lineTo(-2, 0);
        handleRight.graphics.lineTo(3, 4);
        handleRight.graphics.beginFill(0xffffff);
        handleRight.graphics.moveTo(3, -4);
        handleRight.graphics.lineTo(0, -2);
        handleRight.graphics.lineTo(3, 0);
        handleRight.graphics.endFill();
        handleRight.x = 28 + 5;
        handleRight.y = 0;
        CanvasHue.addChild(handleRight);
      }

      private function initImageColor():void
      {
        colorPreview = new Sprite();
        colorPreview.graphics.lineStyle(1, 0x000000);
        colorPreview.graphics.beginFill(0xFFFFFF);
        colorPreview.graphics.drawRect(0, 0, 64, 84);
        CanvasColor.addChild(colorPreview);
      }

      private function initColorPicker():void
      {

        this.x = 388;
        this.y = 311;

        initImagePicker();
        initImageHue();
        initImageColor();

        var hsb:Array = RGB2HSL(red, green, blue);
        hue = hsb[0];
        saturation = hsb[1];
        lightness = hsb[2];

        updateImagePickerColor();
        updateImagePickerHue();
        updateImagePicker();
        updateColorPreview();

      }

      private function doHueDown(event:MouseEvent):void
      {
        currentDragger = CanvasHue;
        doHueMove(event);
      }

      private function doHueUp(event:MouseEvent):void
      {
        currentDragger = undefined;
        doHueMove(event);
      }

      private function doHueMove(event:MouseEvent):void
      {
        if (event.buttonDown && currentDragger == CanvasHue)
        {
          var h:Number = Math.max(Math.min(255, CanvasHue.mouseY), 0);
          handleLeft.y = h;
          handleRight.y = h;
          hue = h * (1 / 255);
          var rgb:Array = HSB2RGB(hue, saturation, lightness);
          red = rgb[0];
          green = rgb[1];
          blue = rgb[2];
          updateImagePickerColor();
          updateImagePicker();
          updateColorPreview();
          event.updateAfterEvent();
        }
      }

      private function doPickerDown(event:MouseEvent):void
      {
        currentDragger = CanvasPicker;
        doPickerMove(event);
      }

      private function doPickerUp(event:MouseEvent):void
      {
        currentDragger = undefined;
        doPickerMove(event);
      }

      private function doPickerMove(event:MouseEvent):void
      {
        if (event.buttonDown && currentDragger == CanvasPicker)
        {
          var xx:Number = Math.max(Math.min(255, CanvasPicker.mouseX), 0);
          var yy:Number = Math.max(Math.min(255, CanvasPicker.mouseY), 0);
          handlePicker.x = xx;
          handlePicker.y = yy;
          saturation = xx / 255;
          lightness = 1 - (yy / 255);
          var rgb:Array = HSB2RGB(hue, saturation, lightness);
          red = rgb[0];
          green = rgb[1];
          blue = rgb[2];
          updateImagePickerColor();
          updateImagePickerHue();
          updateColorPreview();
          event.updateAfterEvent();
        }
      }

      public function setColorRGB(color:uint):void
      {
        ored = red = ((color >> 16) & 0xFF) / 255;
        ogreen = green = ((color >> 8) & 0xFF) / 255;
        oblue = blue = ((color) & 0xFF) / 255;
        var hsb:Array = RGB2HSL(red, green, blue);
        hue = hsb[0];
        saturation = hsb[1];
        lightness = hsb[2];
        if (colorArea)
        {
          updateImagePickerColor();
          updateImagePickerHue();
          updateImagePicker();
        }
      }

      public function getColorRGB():uint
      {
        return uint((Math.round(red * 255)) << 16) |
          uint((Math.round(green * 255)) << 8) |
          uint(Math.round(blue * 255))
      }
    ]]>
  </fx:Script>

</s:TitleWindow>
