unit IWTMSPCKDsnColorDialog;

interface

uses
  SysUtils, Classes,
  Windows, Messages,
  StdCtrls, ComCtrls, Grids, Controls, ExtCtrls, Graphics, Dialogs, Forms,
  IWColor, Math;

type
  TIWTMSPCKColorForm = class(TForm)
    StatusBar1: TStatusBar;
    LabelSelection: TLabel;
    PaintBoxSelection: TPaintBox;
    LabelIdent: TLabel;
    PageControl1: TPageControl;
    TabSheetWeb: TTabSheet;
    TabSheetSys: TTabSheet;
    WebColorsGrid: TDrawGrid;
    SysColorsGrid: TDrawGrid;
    Button1: TButton;
    Button2: TButton;
    TabSheet1: TTabSheet;
    PaintBoxColor: TPaintBox;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    EditHue: TEdit;
    EditSat: TEdit;
    EditBright: TEdit;
    TrackBright: TTrackBar;
    GridCustomColors: TDrawGrid;
    ButtonAdd: TButton;
    PaintBoxPickedColor: TPaintBox;
    Label4: TLabel;
    LabelR: TLabel;
    LabelG: TLabel;
    LabelB: TLabel;
    editRed: TEdit;
    editGreen: TEdit;
    editBlue: TEdit;
    procedure WebColorsGridSelectCell(Sender: TObject; ACol, ARow: Integer;
      var CanSelect: Boolean);
    procedure WebColorsGridDrawCell(Sender: TObject; ACol, ARow: Integer;
      Rect: TRect; State: TGridDrawState);
    procedure SysColorsGridDrawCell(Sender: TObject; ACol, ARow: Integer;
      Rect: TRect; State: TGridDrawState);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure WebColorsGridMouseMove(Sender: TObject; Shift: TShiftState;
      X, Y: Integer);
    procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure SysColorsGridMouseMove(Sender: TObject; Shift: TShiftState;
      X, Y: Integer);
    procedure SysColorsGridSelectCell(Sender: TObject; ACol, ARow: Integer;
      var CanSelect: Boolean);
    procedure PaintBoxSelectionPaint(Sender: TObject);
    procedure PaintBoxColorPaint(Sender: TObject);
    procedure PaintBoxColorMouseMove(Sender: TObject; Shift: TShiftState;
      X, Y: Integer);
    procedure PaintBoxColorMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure TrackBrightChange(Sender: TObject);
    procedure PaintBoxPickedColorPaint(Sender: TObject);
    procedure GridCustomColorsDrawCell(Sender: TObject; ACol,
      ARow: Integer; Rect: TRect; State: TGridDrawState);
    procedure ButtonAddClick(Sender: TObject);
    procedure GridCustomColorsSelectCell(Sender: TObject; ACol,
      ARow: Integer; var CanSelect: Boolean);
    procedure EditHueChange(Sender: TObject);
    procedure EditSatChange(Sender: TObject);
    procedure EditBrightChange(Sender: TObject);
    procedure editRedChange(Sender: TObject);
    procedure editGreenChange(Sender: TObject);
    procedure editBlueChange(Sender: TObject);
  private
    FBlue: Integer;
    FRed: Integer;
    FGreen: Integer;
  private

    //designates if the UI controls are commanded internally (not by the user)
    FIsInternalUICommand : boolean;

    FSysColors: TStringList;
    FCustomColors : TStringList;
    FSelectedIdentifier: string;
    FSelectedColor : Integer;
    FHue, FSat, FBright : Integer;
    FPickedColor : Integer;
    // FCustom: TStringList;
    FX, FY: Integer;
    FIsMarkerEnabled : boolean;

    { Private declarations }
    procedure DrawMarker;
    procedure CalcPickedColor(AFromRGB: Boolean);
    procedure SystemColorsCallback(const S: string);
    procedure SetSelectedIdentifier(const Value: string);
    procedure SetBright( Bright : Integer );
    procedure SetHue( Hue : Integer );
    procedure SetSat( Sat : Integer );
    procedure SetRed(AValue: Integer);
    procedure SetGreen(AValue: Integer);
    procedure SetBlue(AValue: Integer);
    procedure SetPickedColor( Color : Integer );
    function HSBtoRGB( Hue, Sat, Bright : Extended ) : Integer;
    procedure RGBToHSB(R, G, B: Integer; var AHue, ASat, ABright: Extended);
    function XToHue( X : Integer ) : Integer;
    function YToSat( Y : Integer ) : Integer;
    function HueToX( Hue : Integer ) : Integer;
    function SatToY( Sat : Integer ) : Integer;


    { private properties }
    property Red: Integer read FRed write SetRed;
    property Green: Integer read FGreen write SetGreen;
    property Blue: Integer read FBlue write SetBlue;
    property Bright : Integer read FBright write SetBright;
    property Hue : Integer read FHue write SetHue;
    property Sat : Integer read FSat write SetSat;
    property PickedColor : Integer read FPickedColor write SetPickedColor;
  public
     constructor Create( AOWner: TComponent; CustomProperties : TStringList ); reintroduce;
     property SelectedIdentifier : string read FSelectedIdentifier write SetSelectedIdentifier;
    { Public declarations }
  end;

var
  IWColorForm: TIWTMSPCKColorForm;

implementation

const
  SatPoints : Integer = 200;
  HuePoints : Integer = 200;
  BrightPoints : Integer = 200;
  RedPoints : Integer = 256;
  GreenPoints : Integer = 256;
  BluePoints : Integer = 256;

{$R *.dfm}

procedure TIWTMSPCKColorForm.WebColorsGridSelectCell(Sender: TObject; ACol,
  ARow: Integer; var CanSelect: Boolean);
var
  index : Integer;
begin
  index := ACol + ARow*WebColorsGrid.ColCount;
  if( (index >= Low(IWColors) ) and ( index <= High( IWColors ) ) ) then begin
    SelectedIdentifier := IWColors[index].Name;
  end else begin
//    SelectedIdentifier := '';   
  end;
end;

procedure TIWTMSPCKColorForm.WebColorsGridDrawCell(Sender: TObject; ACol,
  ARow: Integer; Rect: TRect; State: TGridDrawState);
var
  index : Integer;
  color : TIWColor;
begin
  index := ACol + ARow*WebColorsGrid.ColCount;
  if( (index >= Low(IWColors) ) and ( index <= High( IWColors ) ) ) then begin
    color := IWColors[index].Value;
    WebColorsGrid.Canvas.Brush.Color := color;
    WebColorsGrid.Canvas.FillRect( Rect );
  end else begin
    WebColorsGrid.Canvas.Pen.Color := clBlack;
    WebColorsGrid.Canvas.MoveTo( Rect.Left, Rect.Top );
    WebColorsGrid.Canvas.LineTo( Rect.Right, Rect.Bottom );
    WebColorsGrid.Canvas.MoveTo( Rect.Right, Rect.Top );
    WebColorsGrid.Canvas.LineTo( Rect.Left, Rect.Bottom );
  end;
end;

procedure TIWTMSPCKColorForm.SysColorsGridDrawCell(Sender: TObject; ACol,
  ARow: Integer; Rect: TRect; State: TGridDrawState);
var
  index : Integer;
  color : Longint;
  colorIdent : string;
begin

  index := ACol + ARow*SysColorsGrid.ColCount;
  if( (index >= 0 ) and ( index < FSysColors.Count )  ) then begin
    colorIdent := FSysColors[index];
    IdentToColor( colorIdent, color );
    SysColorsGrid.Canvas.Brush.Color := color;
    SysColorsGrid.Canvas.FillRect( Rect );
  end else begin
    SysColorsGrid.Canvas.Pen.Color := clBlack;
    SysColorsGrid.Canvas.MoveTo( Rect.Left, Rect.Top );
    SysColorsGrid.Canvas.LineTo( Rect.Right, Rect.Bottom );
    SysColorsGrid.Canvas.MoveTo( Rect.Right, Rect.Top );
    SysColorsGrid.Canvas.LineTo( Rect.Left, Rect.Bottom );
  end;

end;

procedure TIWTMSPCKColorForm.SystemColorsCallback(const S: string);
begin
  FSysColors.Add( S );
end;

procedure TIWTMSPCKColorForm.FormCreate(Sender: TObject);
var
  LNumCustomColors : Integer;
  I : Integer;
begin
  // init some props
  PaintBoxColor.Width :=  HuePoints + 2;
  PaintBoxColor.Height :=  SatPoints + 2;

  TrackBright.Min := 0;
  TrackBright.Max := BrightPoints - 1;
  TrackBright.Frequency := 10;

  Hue := 0;
  Sat := 0;
  Bright := BrightPoints div 2 + BrightPoints div 4;
  CalcPickedColor( False );

  FSysColors := TStringList.Create;

  if FCustomColors = nil  then begin
    FCustomColors := TStringList.Create;
  end;

  LNumCustomColors := GridCustomColors.ColCount * GridCustomColors.RowCount;
  if FCustomColors.Count < LNumCustomColors then begin
    for I := 0 to LNumCustomColors - FCustomColors.Count do begin
      FCustomColors.Add( '' );
    end;
  end;

  GetColorValues( SystemColorsCallback );
end;

procedure TIWTMSPCKColorForm.FormDestroy(Sender: TObject);
begin
  FreeAndNil(FSysColors);
end;

procedure TIWTMSPCKColorForm.WebColorsGridMouseMove(Sender: TObject;
  Shift: TShiftState; X, Y: Integer);
var
  Row, Col, Index : Integer;
begin
  WebColorsGrid.MouseToCell(X,Y,Col,Row);
  index := Col + Row*WebColorsGrid.ColCount;
  if( (index >= Low(IWColors) ) and ( index <= High( IWColors ) ) ) then begin
    StatusBar1.SimpleText := IWColors[index].Name;
  end else begin
    StatusBar1.SimpleText := '';
  end;
end;

procedure TIWTMSPCKColorForm.FormMouseMove(Sender: TObject; Shift: TShiftState;
  X, Y: Integer);
begin
  StatusBar1.SimpleText := '';
end;

procedure TIWTMSPCKColorForm.SysColorsGridMouseMove(Sender: TObject;
  Shift: TShiftState; X, Y: Integer);
var
  Row, Col, Index : Integer;
begin
  SysColorsGrid.MouseToCell(X,Y,Col,Row);
  index := Col + Row*SysColorsGrid.ColCount;
  if( (index >= 0) and ( index < FSysColors.Count ) ) then begin
    StatusBar1.SimpleText := FSysColors[index];
  end else begin
    StatusBar1.SimpleText := '';
  end;
end;

procedure TIWTMSPCKColorForm.SysColorsGridSelectCell(Sender: TObject; ACol,
  ARow: Integer; var CanSelect: Boolean);
var
  index : Integer;
begin
  index := ACol + ARow*SysColorsGrid.ColCount;
  if( (index >=0 )and ( index < FSysColors.Count ) ) then begin
    SelectedIdentifier := FSysColors[index];
  end else begin
//    SelectedIdentifier := '';
  end;
end;


procedure TIWTMSPCKColorForm.PaintBoxSelectionPaint(Sender: TObject);
{Var
  Color : Integer;}
begin
  if( SelectedIdentifier <> '' ) then begin
    PaintBoxSelection.Canvas.Brush.Color := FSelectedColor;
    PaintBoxSelection.Canvas.FillRect( Rect(0, 0, PaintBoxSelection.Width - 1, PaintBoxSelection.Height - 1));
  end else begin
  ;
  end;
end;

procedure TIWTMSPCKColorForm.SetSelectedIdentifier(const Value: string);
begin
  FSelectedIdentifier := Value;
  LabelIdent.Caption := 'Identifier: ' + FSelectedIdentifier;
  if not IdentToIWColor( FSelectedIdentifier, FSelectedColor ) then begin
    FSelectedColor := StrToInt( FSelectedIdentifier );
    if PageControl1.ActivePageIndex <> 2 then begin
      PageControl1.ActivePageIndex := 2;
    end;
    Red := FSelectedColor and $000000ff;
    Green := ( FSelectedColor and $0000ff00 ) shr 8;
    Blue := ( FSelectedColor and $00ff0000 ) shr 16;
    SetPickedColor(FSelectedColor);
    CalcPickedColor(True);
  end;
  PaintBoxSelection.Repaint;
end;

function TIWTMSPCKColorForm.HSBtoRGB(Hue, Sat, Bright: Extended): Integer;
var
  R, G, B: Integer;
  H, F, P, Q, T: Extended;
begin
  R := 0;
  G := 0;
  B := 0;
  if Sat = 0.0 then begin
    R := Trunc(  Bright * 255.0 + 0.5 );
    G := R;
    B := G;
  end else begin
    H := ( (Hue - Floor( Hue ))* 6.0 );
    F := H - Floor( H );
    P := Bright * ( 1.0 - Sat );
    Q := Bright * ( 1.0 - Sat * F );
    T := Bright * ( 1.0 - ( Sat * ( 1.0 - F ) ) );

    case Trunc( h ) of
      0: begin
           R := Trunc( Bright * 255.0 + 0.5 );
           G := Trunc( T * 255.0 + 0.5 );
           B := Trunc( P * 255.0 + 0.5 );
         end;
      1: begin
           R := Trunc( Q * 255.0 + 0.5 );
           G := Trunc( Bright * 255.0 + 0.5 );
           B := Trunc( P * 255.0 + 0.5 );
         end;
      2: begin
           R := Trunc( P * 255.0 + 0.5 );
           G := Trunc( Bright * 255.0 + 0.5 );
           B := Trunc( T * 255.0 + 0.5 );
         end;
      3: begin
           R := Trunc( P * 255.0 + 0.5 );
           G := Trunc( Q * 255.0 + 0.5 );
           B := Trunc( Bright * 255.0 + 0.5 );
         end;
      4: begin
           R := Trunc( T * 255.0 + 0.5 );
           G := Trunc( P * 255.0 + 0.5 );
           B := Trunc( Bright * 255.0 + 0.5 );
         end;
      5: begin
           R := Trunc( Bright * 255.0 + 0.5 );
           G := Trunc( P * 255.0 + 0.5 );
           B := Trunc( Q * 255.0 + 0.5 );
         end;
    end;
  end;
  Result := $00ffffff and (B Shl 16) or ( G shl 8 ) or R ;
end;

procedure TIWTMSPCKColorForm.PaintBoxColorPaint(Sender: TObject);
var
  Hue, Sat : Integer;
  Bright : Integer; // change
begin
  // frame
  with PaintBoxColor.Canvas do begin
    Pen.Color := clWhite;
    MoveTo( 0, 0 );
    LineTo( PaintBoxColor.Width - 1, 0 );
    LineTo( PaintBoxColor.Width - 1, PaintBoxColor.Height - 1 );
    LineTo( 0, PaintBoxColor.Height - 1 );
    LineTo( 0, 0 );
  end;

  Bright := 150;
  for Sat := SatPoints - 1  downto 0 do begin
    begin
      for Hue := 0 to HuePoints - 1 do begin
        PaintBoxColor.Canvas.Pixels[Hue + 1, SatPoints -1 - Sat + 1] :=
          HSBtoRGB( Hue / HuePoints, Sat / SatPoints, Bright / 200 );
      end;
    end;
  end;
  FIsMarkerEnabled := True;

  // repaint marker, do not erase old one, it's erased by this method
  FX := -1;
  FY := -1;
  DrawMarker;
end;

procedure TIWTMSPCKColorForm.PaintBoxColorMouseMove(Sender: TObject;
  Shift: TShiftState; X, Y: Integer);
begin
  if (ssLeft in Shift) and (X >= 1 ) and (Y >= 1) and
     (X <= PaintBoxColor.Width - 2 ) and (Y <= PaintBoxColor.Height -2 ) then begin

     Hue := XToHue( X );
     Sat := YtoSat( Y );

     DrawMarker;
     CalcPickedColor( False );
  end;
end;

procedure TIWTMSPCKColorForm.PaintBoxColorMouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  if Button = mbLeft then
    PaintBoxColorMouseMove( Sender, Shift, X, Y );
end;

procedure TIWTMSPCKColorForm.SetHue(Hue: Integer);
var
 LUIMode : boolean;
begin
  LUIMode := FIsInternalUICommand;
  FIsInternalUICommand := True;
  try
    FHue := Hue;
    EditHue.Text := IntToStr( Hue );
//    CalcPickedColor(False);
  finally
    FIsInternalUICommand := LUIMode;
  end;
end;

procedure TIWTMSPCKColorForm.SetSat(Sat: Integer);
var
 LUIMode : boolean;
begin
  LUIMode := FIsInternalUICommand;
  FIsInternalUICommand := True;
  try
    FSat := Sat;
    EditSat.Text := IntToStr( Sat );
//    CalcPickedColor(False);
  finally
    FIsInternalUICommand := LUIMode;
  end;
end;

procedure TIWTMSPCKColorForm.SetBright(Bright: Integer);
var
 LUIMode : boolean;
begin
  LUIMode := FIsInternalUICommand;
  FIsInternalUICommand := True;
  try
    FBright := Bright;
    TrackBright.Position := Bright;
    EditBright.Text := IntToStr( Bright );
//    CalcPickedColor(False);
  finally
    FIsInternalUICommand := LUIMode;
  end;
end;

procedure TIWTMSPCKColorForm.SetRed(AValue: Integer);
var
 LUIMode : boolean;
begin
  LUIMode := FIsInternalUICommand;
  FIsInternalUICommand := True;
  try
    FRed := AValue;
    EditRed.Text := IntToStr(Red);
  finally
    FIsInternalUICommand := LUIMode;
  end;
end;

procedure TIWTMSPCKColorForm.SetGreen(AValue: Integer);
var
 LUIMode : boolean;
begin
  LUIMode := FIsInternalUICommand;
  FIsInternalUICommand := True;
  try
    FGreen := AValue;
    editGreen.Text := IntToStr(Green);
  finally
    FIsInternalUICommand := LUIMode;
  end;
end;

procedure TIWTMSPCKColorForm.SetBlue(AValue: Integer);
var
 LUIMode : boolean;
begin
  LUIMode := FIsInternalUICommand;
  FIsInternalUICommand := True;
  try
    FBlue := AValue;
    editBlue.Text := IntToStr(Blue);
  finally
    FIsInternalUICommand := LUIMode;
  end;
end;

procedure TIWTMSPCKColorForm.TrackBrightChange(Sender: TObject);
begin
  if FIsInternalUICommand then begin
    Exit;
  end;
  Bright := TrackBright.Position;
  CalcPickedColor( false );
end;

procedure TIWTMSPCKColorForm.CalcPickedColor(AFromRGB: Boolean);
var
  H, S, B: Extended;
begin
  if not AFromRGB then begin
    PickedColor := HSBtoRGB( Hue/HuePoints, Sat/SatPoints, Bright/BrightPoints );
    Red := PickedColor and $000000ff;
    Green := ( PickedColor and $0000ff00 ) shr 8;
    Blue := ( PickedColor and $00ff0000 ) shr 16;
  end else begin
    RGBToHSB(Red, Green, Blue, H, S, B);
    Hue := Round(H * HuePoints);
    Sat := Round(S * SatPoints);
    Bright := Round(B * BrightPoints);
    PickedColor := Red or ( Green shl 8 ) or ( Blue shl 16);    
  end;
end;

procedure TIWTMSPCKColorForm.SetPickedColor(Color: Integer);
begin
  FPickedColor := Color;
  PaintBoxPickedColor.Repaint;
end;

procedure TIWTMSPCKColorForm.PaintBoxPickedColorPaint(Sender: TObject);
begin
  PaintBoxPickedColor.Canvas.Brush.Color := PickedColor;
  PaintBoxPickedColor.Canvas.FillRect(
    Rect(0,0,PaintBoxPickedColor.Width - 1, PaintBoxPickedColor.Height - 1 ) );
end;

procedure TIWTMSPCKColorForm.GridCustomColorsDrawCell(Sender: TObject; ACol,
  ARow: Integer; Rect: TRect; State: TGridDrawState);
var
  index : Integer;
  color : Longint;
  colorIdent : string;
  isValid : boolean;
begin
  color := 0;
  isValid := False;
  index := ACol + ARow*GridCustomColors.ColCount;
  if( (index >= 0 ) and ( index < FCustomColors.Count )  ) then begin
    colorIdent := FCustomColors[index];
    if colorIdent <> '' then begin
      color := StrToInt( colorIdent );
      isValid := True;
    end;
  end;

  if isValid then begin
    GridCustomColors.Canvas.Brush.Color := color;
    GridCustomColors.Canvas.FillRect( Rect );
  end else begin
    GridCustomColors.Canvas.Brush.Color := clWhite;
    GridCustomColors.Canvas.FillRect( Rect );
    GridCustomColors.Canvas.Pen.Color := clBlack;
    GridCustomColors.Canvas.MoveTo( Rect.Left, Rect.Top );
    GridCustomColors.Canvas.LineTo( Rect.Right, Rect.Bottom );
    GridCustomColors.Canvas.MoveTo( Rect.Right, Rect.Top );
    GridCustomColors.Canvas.LineTo( Rect.Left, Rect.Bottom );
  end;
end;

procedure TIWTMSPCKColorForm.ButtonAddClick(Sender: TObject);
var
  LIndex : Integer;
begin
  LIndex := GridCustomColors.Col + GridCustomColors.Row*GridCustomColors.ColCount;
  FCustomColors[LIndex]:= '$' + IntToHex( PickedColor, 8 );
  GridCustomColors.Repaint;
end;

procedure TIWTMSPCKColorForm.GridCustomColorsSelectCell(Sender: TObject; ACol,
  ARow: Integer; var CanSelect: Boolean);
var
  LIndex : Integer;
begin
  LIndex := ACol + ARow*GridCustomColors.ColCount;
  if( FCustomColors[LIndex] <> '' ) then begin
    SelectedIdentifier := FCustomColors[LIndex];
  end;

end;

procedure TIWTMSPCKColorForm.EditHueChange(Sender: TObject);
var
  newVal : Integer;
  isValid : boolean;
begin

  if FIsInternalUICommand then begin
    Exit;
  end;

  isValid := False;
  newVal := 0;
  try
    newVal := StrToInt( EditHue.Text );
  if ( newVal >= 0 ) and ( newVal < HuePoints ) then begin
    isValid := True;
  end;
  except;
  end;

  if EditHue.Text <> '' then begin
    if isValid then begin
      Hue := newVal;
      CalcPickedColor( False );
      DrawMarker;
    end else begin
      Hue := Hue; // update
    end;
  end;
end;

procedure TIWTMSPCKColorForm.EditSatChange(Sender: TObject);
var
  newVal : Integer;
  isValid : boolean;
begin

  if FIsInternalUICommand then begin
    Exit;
  end;

  isValid := False;
  newVal := 0;
  try
    newVal := StrToInt( EditSat.Text );
  if ( newVal >= 0 ) and ( newVal < SatPoints ) then begin
    isValid := True;
  end;
  except;
  end;

  if EditSat.Text <> '' then begin
    if isValid then begin
      Sat := newVal;
      CalcPickedColor( False );      
      DrawMarker;
    end else begin
      Sat := Sat; // update
    end;
  end;
end;

procedure TIWTMSPCKColorForm.EditBrightChange(Sender: TObject);
var
  newVal : Integer;
  isValid : boolean;
begin

  if FIsInternalUICommand then begin
    Exit;
  end;

  isValid := False;
  newVal := 0;
  try
    newVal := StrToInt( EditBright.Text );
  if ( newVal >= 0 ) and ( newVal < BrightPoints ) then begin
    isValid := True;
  end;
  except;
  end;

  if EditBright.Text <> '' then begin
    if isValid then begin
      Bright := newVal;
      CalcPickedColor( False );      
    end else begin
      Bright := Bright; // update
    end;
  end;
end;

procedure TIWTMSPCKColorForm.editRedChange(Sender: TObject);
var
  newVal : Integer;
  isValid : boolean;
begin
  if FIsInternalUICommand then begin
    Exit;
  end;

  isValid := False;
  newVal := 0;
  try
    newVal := StrToInt( EditRed.Text );
  if ( newVal >= 0 ) and ( newVal < RedPoints ) then begin
    isValid := True;
  end;
  except;
  end;

  if EditRed.Text <> '' then begin
    if isValid then begin
      Red := newVal;
      CalcPickedColor( True );
      DrawMarker;            
    end else begin
      Red := Red; // update
    end;
  end;
end;

procedure TIWTMSPCKColorForm.editGreenChange(Sender: TObject);
var
  newVal : Integer;
  isValid : boolean;
begin

  if FIsInternalUICommand then begin
    Exit;
  end;

  isValid := False;
  newVal := 0;
  try
    newVal := StrToInt( EditGreen.Text );
  if ( newVal >= 0 ) and ( newVal < GreenPoints ) then begin
    isValid := True;
  end;
  except;
  end;

  if EditGreen.Text <> '' then begin
    if isValid then begin
      Green := newVal;
      CalcPickedColor( True );
      DrawMarker;            
    end else begin
      Green := Green; // update
    end;
  end;
end;

procedure TIWTMSPCKColorForm.editBlueChange(Sender: TObject);
var
  newVal : Integer;
  isValid : boolean;
begin

  if FIsInternalUICommand then begin
    Exit;
  end;

  isValid := False;
  newVal := 0;
  try
    newVal := StrToInt( EditBlue.Text );
  if ( newVal >= 0 ) and ( newVal < BluePoints ) then begin
    isValid := True;
  end;
  except;
  end;

  if EditBlue.Text <> '' then begin
    if isValid then begin
      Blue := newVal;
      CalcPickedColor( True );
      DrawMarker;            
    end else begin
      BLue := Blue; // update
    end;
  end;
end;


constructor TIWTMSPCKColorForm.Create(AOWner: TComponent;
  CustomProperties: TStringList);
begin
  FCustomColors := CustomProperties;

  inherited Create(AOwner);

  FX := -1;
  FY := -1;
  FIsMarkerEnabled := False;
end;

procedure TIWTMSPCKColorForm.DrawMarker;
var
  LOldMode : TPenMode;
begin
  if FIsMarkerEnabled then begin

  LOldMode := PaintBoxColor.Canvas.Pen.Mode;
  PaintBoxColor.Canvas.Pen.Mode := pmNot;
  PaintBoxColor.Canvas.Pen.Color := clBlack;

  if FX <> -1 then begin
    PaintBoxColor.Canvas.MoveTo(FX, FY - 10);
    PaintBoxColor.Canvas.LineTo(FX, FY + 10);
    PaintBoxColor.Canvas.MoveTo(FX - 10, FY);
    PaintBoxColor.Canvas.LineTo(FX + 10, FY);
  end;

  FX := HueToX( Hue );
  FY := SatToY( Sat );

  PaintBoxColor.Canvas.MoveTo(FX, FY - 10);
  PaintBoxColor.Canvas.LineTo(FX, FY + 10);
  PaintBoxColor.Canvas.MoveTo(FX - 10, FY);
  PaintBoxColor.Canvas.LineTo(FX + 10, FY);

  PaintBoxColor.Canvas.Pen.Mode := LOldMode;

  end;
end;

function TIWTMSPCKColorForm.HueToX(Hue: Integer): Integer;
begin
  Result := Hue + 1;
end;

function TIWTMSPCKColorForm.SatToY(Sat: Integer): Integer;
begin
  Result := SatPoints - Sat;
end;

function TIWTMSPCKColorForm.XToHue(X: Integer): Integer;
begin
  Result := X -1 ; // remove bias
end;

function TIWTMSPCKColorForm.YToSat(Y: Integer): Integer;
begin
  Result := Y -1;  // remove bias
  Result := SatPoints -1 - Result;
end;

procedure TIWTMSPCKColorForm.RGBToHSB(R, G, B: Integer; var AHue, ASat, ABright: Extended);
var
  LHue, LSaturation, LBrightness : Extended;
  cMax, cMin: Integer;
  redc, greenc, bluec : Extended;
begin
  cMax := Math.Max(Math.Max(R, G), B);
  cMin := Math.Min(Math.Min(R, G), B);

  LBrightness := cMax / 255.0;
  if cMax <> 0 then begin
    LSaturation := (cMax - cMin) / cMax;
  end else begin
    LSaturation := 0;
  end;

  if LSaturation = 0 then begin
    LHue := 0;
  end else begin
    redc := (cMax - R)/(cMax-cMin);
    greenc := (cMax - G)/(cMax-cMin);
    bluec := (cMax - B)/(cMax-cMin);

    if R = cMax then begin
      LHue := bluec - greenc;
    end else begin
      if g = cMax then begin
        LHue := 2.0 + redc - bluec;
      end else begin
        LHue := 4.0 + greenc - redc;
      end;
    end;
    LHue := LHue / 6.0;
    if LHue < 0.0 then begin
      LHue := LHue + 1.0;
    end;
  end;

  AHue := LHue;
  ASat := LSaturation;
  ABright := LBrightness;
end;


end.
