{********************************************}
{   TeeChart Surface Series Nearest Tool     }
{ Copyright (c) 2003-2020 by Steema Software }
{        All Rights Reserved                 }
{********************************************}
unit TeeSurfaceTool;
{$I TeeDefs.inc}

interface

uses {$IFNDEF LINUX}
     {$IFNDEF FMX}
     Windows, Messages,
     {$ENDIF}
     {$ENDIF}
     SysUtils, Classes,

     {$IFDEF FMX}
     FMX.Types, System.UITypes,
     {$IFDEF D17}
     System.UIConsts,
     {$ENDIF}
     {$ELSE}
     Graphics, Controls,
     {$ENDIF}

     {$IFDEF FMX}
     FMXTee.Canvas, FMXTee.Engine, FMXTee.Chart, FMXTee.Tools,
     FMXTee.Series.Surface
     {$ELSE}
     {$IFDEF D17}
     System.UIConsts,
     {$ENDIF}
     TeeTools, TeCanvas, TeEngine, Chart, TeeSurfa
     {$ENDIF}
     ;

type
  TSurfaceNearestTool=class(TTeeCustomToolSeries)
  private
    FCell   : TColor;
    FColumn : TColor;
    FRow    : TColor;
    FOnSelect : TNotifyEvent;

    procedure SetCell(const Value: TColor);
    procedure SetColumn(const Value: TColor);
    procedure SetRow(const Value: TColor);
  protected
    Procedure ChartMouseEvent( AEvent: TChartMouseEvent;
                               Button:TMouseButton;
                               Shift: TShiftState; X, Y: Integer); override;
    class Function GetEditorClass:String; override;
    procedure SetSeries(const Value: TChartSeries); override;
  public
    SelectedCell : Integer;

    Constructor Create(AOwner:TComponent); override;
    class Function Description:String; override;
    class Function LongDescription:String; override;
    Procedure GetRowCol(out Row,Col:Double);
  published
    property Active;
    property CellColor:TColor read FCell write SetCell default {$IFDEF FMX}claRed{$ELSE}clRed{$ENDIF};
    property ColumnColor:TColor read FColumn write SetColumn default {$IFDEF FMX}claGreen{$ELSE}clGreen{$ENDIF};
    property RowColor:TColor read FRow write SetRow default {$IFDEF FMX}claBlue{$ELSE}clBlue{$ENDIF};
    property Series;

    property OnSelectCell:TNotifyEvent read FOnSelect write FOnSelect;
  end;

implementation

uses
  {$IFDEF FMX}
  FMXTee.ProConstants
  {$ELSE}
  TeeProCo
  {$ENDIF}
  ;

{ TSurfaceNearestTool }

Constructor TSurfaceNearestTool.Create(AOwner: TComponent);
begin
  inherited;

  FColumn:={$IFDEF FMX}claGreen{$ELSE}clGreen{$ENDIF};
  FRow:={$IFDEF FMX}claBlue{$ELSE}clBlue{$ENDIF};
  FCell:={$IFDEF FMX}claRed{$ELSE}clRed{$ENDIF};

  SelectedCell:=-1;
end;

class function TSurfaceNearestTool.Description: String;
begin
  result:=TeeMsg_SurfaceNearestTool;
end;

class function TSurfaceNearestTool.GetEditorClass: String;
begin
  result:='TSurfaceNearest';
end;

procedure TSurfaceNearestTool.SetSeries(const Value: TChartSeries);
begin
  if Value is TSurfaceSeries then inherited
                             else inherited SetSeries(nil);
end;

Procedure TSurfaceNearestTool.GetRowCol(out Row,Col:Double);
var tmpO : TCellsOrientation;
begin
  if SelectedCell=-1 then
  begin
    Row:=-1;
    Col:=-1;
  end
  else
  with TSurfaceSeries(Series) do
  begin
    tmpO:=CellsOrientation;

    Row:=XValues.Value[SelectedCell];
    if tmpO.IncX=1 then Row:=Row-1;

    Col:=ZValues.Value[SelectedCell]-1; // Always return -1 (see bug 692)
    if tmpO.IncZ=-1 then Col:=Col+1;
  end;
end;

procedure TSurfaceNearestTool.ChartMouseEvent(AEvent: TChartMouseEvent;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var tmp,t : Integer;
    tmpRow,
    tmpCol : Double;
begin
  if (AEvent=cmeMove) and Assigned(Series) then
  begin
    tmp:=TSurfaceSeries(Series).ClickedCell(x,y);

    if tmp<>SelectedCell then
    begin
      SelectedCell:=tmp;

      Series.ParentChart.AutoRepaint:=False;

      with TCustom3DSeries(Series) do
        if SelectedCell=-1 then
           for t:=0 to Count-1 do
               ValueColor[t]:=clTeeColor
        else
        begin
          GetRowCol(tmpRow,tmpCol);

          // Always increment +1 here (see bug 692)
          tmpCol:=tmpCol+1;

          for t:=0 to Count-1 do
            if (XValues.Value[t]=tmpRow) and (ZValues.Value[t]=tmpCol) then
               ValueColor[t]:=CellColor
            else
            if XValues.Value[t]=tmpRow then
               ValueColor[t]:=RowColor
            else
            if ZValues.Value[t]=tmpCol then
               ValueColor[t]:=ColumnColor
            else
               ValueColor[t]:=clTeeColor;
        end;

      Series.ParentChart.AutoRepaint:=True;
      Series.ParentChart.Invalidate;

      if Assigned(FOnSelect) then
         FOnSelect(Self);
    end;
  end;
end;

procedure TSurfaceNearestTool.SetColumn(const Value: TColor);
begin
  SetColorProperty(FColumn,Value);
end;

procedure TSurfaceNearestTool.SetRow(const Value: TColor);
begin
  SetColorProperty(FRow,Value);
end;

procedure TSurfaceNearestTool.SetCell(const Value: TColor);
begin
  SetColorProperty(FCell,Value);
end;

class function TSurfaceNearestTool.LongDescription: String;
begin
  result:=TeeMsg_SurfaceNearestDesc;
end;

initialization
  RegisterTeeTools([TSurfaceNearestTool]);
finalization
  UnRegisterTeeTools([TSurfaceNearestTool]);
end.
