{********************************************}
{     TeeChart Pro Charting Library          }
{ Copyright (c) 2012-2020 by Steema Software }
{         All Rights Reserved                }
{********************************************}
unit TeeScrollPagerTool;
{$I TeeDefs.inc}

interface

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

     {$IFDEF D18}
     System.Generics.Collections,
     {$ENDIF}

     {$IFDEF D16}
     System.UITypes, System.UIConsts,
     {$ENDIF}

     {$IFDEF FMX}
     FMX.Types,
     {$ELSE}
     Graphics, Controls,
     {$ENDIF}

     {$IFDEF D9}
     Types,
     {$ENDIF}

     {$IFDEF FMX}
     FMXTee.Canvas, FMXTee.Engine, FMXTee.Series.Surface, FMXTee.Tools.SubChart,
     FMXTee.Tools, FMXTee.Procs, FMXTee.Chart
     {$ELSE}
     TeEngine, TeeSurfa, TeCanvas, TeeSubChart, TeeTools, Chart, TeeProcs
     {$ENDIF}
     ;

type
  TTeeSubChartAccess=class(TSubChartTool);
  TTeeColorLineAccess=class(TColorLineTool);

  TScrollPagerPointer=class(TSeriesPointer)
  private
    FOldColor : TColor;
    FMouseIn,
    FOldColorSaved : Boolean;
  end;

  TScrollPagerAlign=(saAfter,saBefore,saCustom);

  TScrollPagerTool=class(TTeeCustomToolSeries)
  private
    FAlign         : TScrollPagerAlign;
    FDivisionRatio : Double;

    FStartPointerClicked,
    FEndPointerClicked : Boolean;

    FStartPointer,
    FEndPointer : TScrollPagerPointer;

    FPointHLColor : TColor;

    FSubChartTool : TSubChartTool;

    { Event }
    FScrolled   : TNotifyEvent;

    procedure ColorBandChanged(Sender: TObject);
    function CreateColorBand:TColorBandTool;
    function GetColorBandTool: TColorBandTool;
    function GetEndLinePointer: TSeriesPointer;
    function GetNoLimitDrag:Boolean;
    function GetStartLinePointer: TSeriesPointer;
    function GetSubChartTChart: TChart;
    function GetSubChartTool: TSubChartTool;
    procedure HookColorBand(const ABand:TColorBandTool);
    procedure HookSubChart(const AChart:TCustomChart);
    function ParentNotMandatoryAxis:TChartAxis;
    procedure ResetZoomPanning;
    function SeriesLinkExists(const ASeries:TChartSeries):TChartSeries;
    function SeriesPointerClick(X, Y: Integer; const Point: TSeriesPointer; Start: Boolean): Boolean;
    procedure SetAlign(const Value:TScrollPagerAlign);
    Procedure SetDivisionRatio(const Value:Double);
    procedure SetNoLimitDrag(const Value:Boolean);
    Procedure SetUpChartLayout;
    Procedure SetUpColorBand;
    procedure SetupSeries(const Value: TChartSeries);
    Procedure SetPointerHighlightColor(Value:TColor);
    procedure SubChartTChart_AfterDraw(Sender: TObject);
    procedure SubChartTChart_MouseMove(Sender: TObject; Shift: TShiftState; X, Y: TCoordinate);
    procedure SubChartTChart_MouseDown (Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: TCoordinate);
    procedure SubChartTChart_MouseUp (Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: TCoordinate);
    function SubChartNotMandatoryAxis:TChartAxis;
    function SubChartSeries:TChartSeries;
  protected
    procedure ChartEvent(AEvent: TChartToolEvent); override;
    Procedure ChartMouseEvent(AEvent: TChartMouseEvent; Button:TMouseButton; Shift:TShiftState; X, Y: Integer); override;
    class Function GetEditorClass:String; override;
    procedure Loaded; override;
    Procedure SetActive(Value:Boolean); override;
    procedure SetParentChart(const Value: TCustomAxisPanel); override;
    procedure SetSeries(const Value: TChartSeries); override;
    procedure DoScrolled;
  public
    Constructor Create(AOwner:TComponent); override;
    Destructor Destroy; override;

    procedure AddSeries(const ASeries:TChartSeries);
    procedure Assign(Source:TPersistent); override;

    class Function Description:String; override;
    class Function LongDescription:String; override;

    procedure RemoveSeries(const ASeries:TChartSeries);
    Procedure SetUpScrollPager;
  published
    property Align:TScrollPagerAlign read FAlign write SetAlign default saAfter;
    property ColorBandTool:TColorBandTool read GetColorBandTool;
    property DivisionRatio:Double read FDivisionRatio write SetDivisionRatio;
    property EndLinePointer:TSeriesPointer read GetEndLinePointer;
    property NoLimitDrag:Boolean read GetNoLimitDrag write SetNoLimitDrag default True;
    property PointerHighlightColor:TColor read FPointHLColor write SetPointerHighlightColor
                    default {$IFDEF FMX}claRed{$ELSE}clRed{$ENDIF};
    property Series;

    // Pending. See HTML5 JScript ScrollPager:
    // property EndHandle:TDragHandle
    // property StartHandle:TDragHandle

    property StartLinePointer:TSeriesPointer read GetStartLinePointer;
    property SubChartTChart:TChart read GetSubChartTChart;
    property SubChartTool:TSubChartTool read GetSubChartTool;

    { event }
    property OnScrolled:TNotifyEvent read FScrolled write FScrolled;
  end;

implementation

uses
  Math,
  {$IFDEF FMX}
  FMXTee.Constants, FMXTee.ProConstants
  {$ELSE}
  TeeProCo, TeeConst
  {$ENDIF};

{ TScrollPagerTool }

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

  FDivisionRatio:=3; // 33.33 %

  FPointHLColor:={$IFDEF FMX}claRed{$ELSE}clRed{$ENDIF};
end;

Destructor TScrollPagerTool.Destroy;
begin
  FreeAndNil(FEndPointer);
  FreeAndNil(FStartPointer);
  FreeAndNil(FSubChartTool);

  inherited;
end;

procedure TScrollPagerTool.AddSeries(const ASeries:TChartSeries);
begin
  if SubChartTChart.SeriesCount=0 then
     Series:=ASeries
  else
     SetupSeries(ASeries);
end;

function DifferentRect(const A,B:TRect):Boolean;
begin
  result:=(A.Left<>B.Left) or (A.Top<>B.Top) or (A.Right<>B.Right) or
          (A.Bottom<>B.Bottom);
end;

type
  TPanelAccess=class(TCustomTeePanel);
  
procedure TScrollPagerTool.ChartEvent(AEvent: TChartToolEvent);
begin
  inherited;

  if Active and (AEvent=cteBeforeDraw) then
  begin
    TPanelAccess(ParentChart).ApplyMargins;

    if FAlign<>saCustom then
       SetUpChartLayout;

    if ColorBandTool.Axis<>SubChartNotMandatoryAxis then
    begin
      SubChartTChart.FreeAllSeries;
      ParentChart.Axes.Reset;
      SetSeries(Series);
    end;
  end;
end;

function TScrollPagerTool.SeriesLinkExists(const ASeries:TChartSeries):TChartSeries;
var t : Integer;
begin
  result:=nil;

  if Assigned(FSubChartTool) then
  for t:=0 to SubChartTChart.SeriesCount-1 do
  if SubChartTChart[t].DataSource=ASeries then
  begin
    result:=SubChartTChart[t];
    break;
  end;
end;

procedure TScrollPagerTool.RemoveSeries(const ASeries:TChartSeries);
var tmp : TChartSeries;
begin
  if Assigned(ASeries) then
  begin
    tmp:=SeriesLinkExists(ASeries);

    if Assigned(tmp) then
       tmp.{$IFDEF AUTOREFCOUNT}DisposeOf{$ELSE}Free{$ENDIF};
  end;
end;

procedure TScrollPagerTool.Assign(Source:TPersistent);
begin
  if Source is TScrollPagerTool then
  with TScrollPagerTool(Source) do
  begin
    Self.FDivisionRatio:=FDivisionRatio;
    Self.FPointHLColor:=FPointHLColor;

    //Self.ColorBandTool.Assign(FColorBandTool);
    Self.EndLinePointer.Assign(FEndPointer);
    Self.StartLinePointer.Assign(FStartPointer);
    Self.SubChartTool.Assign(FSubChartTool);
  end;

  inherited;
end;

function TScrollPagerTool.ParentNotMandatoryAxis:TChartAxis;
begin
  if Assigned(Series) then
     if Series.YMandatory then
        result:=Series.GetHorizAxis
     else
        result:=Series.GetVertAxis
  else
     result:=ParentChart.Axes.Bottom;
end;

{ event }
procedure TScrollPagerTool.DoScrolled;
Begin
  if Assigned(FScrolled) then
     FScrolled(Self);
end;

procedure TScrollPagerTool.ChartMouseEvent(AEvent: TChartMouseEvent;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var tmpAxis : TChartAxis;
    tmpBand : TColorBandTool;
    Old     : TNotifyEvent;
begin
  if Active and Assigned(Series) then
  begin
    TTeeSubChartAccess(SubChartTool).ChartMouseEvent(AEvent, Button, Shift, X, Y);

    if SubChartTool.Charts.Count>0 then
    if PointInRect(SubChartTool.Charts[0].Bounds, X, Y) and (not FStartPointerClicked) and (not FEndPointerClicked) then
    begin
      ParentChart.Cursor:=SubChartTChart.Cursor;
      ParentChart.CancelMouse:=True;
    end;

    if ((AEvent=cmeMove) and (not ParentChart.CancelMouse)) or (AEvent=cmeUp) then
    begin
      tmpAxis:=ParentNotMandatoryAxis;
      tmpBand:=ColorBandTool;

      if (tmpBand.StartValue<>tmpAxis.Minimum) or (tmpBand.EndValue<>tmpAxis.Maximum) then
      begin
        Old:=tmpBand.OnChanged;
        tmpBand.OnChanged:=nil;

        tmpBand.StartValue:=tmpAxis.Minimum;
        tmpBand.EndValue:=tmpAxis.Maximum;

        tmpBand.OnChanged:=Old;
      end;
    end;
  end;
end;

class function TScrollPagerTool.Description: String;
begin
 result:=TeeMsg_ScrollPagerTool;
end;

procedure TScrollPagerTool.SetParentChart(const Value: TCustomAxisPanel);
begin
  inherited;

  if Assigned(ParentChart) then
  begin
    TCustomChart(ParentChart).Legend.Visible:=False;
    ParentChart.View3D:=False;

    if Assigned(Series) then
       ResetZoomPanning
    else
    if not (csLoading in ComponentState) then
       if ParentChart.SeriesCount>0 then
          Series:=ParentChart[0]; // <-- automatic initialization
  end;

  if Assigned(FSubChartTool) then
     FSubChartTool.ParentChart:=ParentChart;
end;

function TScrollPagerTool.GetNoLimitDrag:Boolean;
begin
  result:=ColorBandTool.NoLimitDrag;
end;

function TScrollPagerTool.CreateColorBand:TColorBandTool;
begin
  result:=TColorBandTool.Create(Self);

  // Ugly trick to recognize band tool when loading.
  // This should be done better, using a read/write property.
  result.Tag:=1;

  //result.ShowInEditor:=False;

  result.ParentChart:=SubChartTChart;
  result.Cursor:=crHandPoint;
  result.Pen.Hide;
  result.DrawBehind:=False;

  result.ResizeEnd:=True;
  result.ResizeStart:=True;
  result.Transparency:=50;

  result.StartLine.AllowDrag:=True;
  result.EndLine.AllowDrag:=True;

  result.NoLimitDrag:=False;
  result.Axis:=SubChartNotMandatoryAxis;

  HookColorBand(result);
end;

function TScrollPagerTool.GetColorBandTool: TColorBandTool;
var t : Integer;
    tmp : TTeeCustomTool;
begin
  for t:=0 to SubChartTChart.Tools.Count-1 do
  begin
    tmp:=SubChartTChart.Tools[t];

    //if (tmp.Tag=1) and (tmp is TColorBandTool) then //#2228 Tag not saving properly
    if (tmp is TColorBandTool) then
    begin
      result:=TColorBandTool(tmp);
      Exit;
    end;
  end;

  result:=CreateColorBand;
end;

class function TScrollPagerTool.GetEditorClass: String;
begin
  result:='TScrollPagerEditor';
end;

procedure TScrollPagerTool.HookColorBand(const ABand:TColorBandTool);
begin
  ABand.OnChanged:=ColorBandChanged;
  ABand.OnDragging:=ColorBandChanged;
  ABand.OnResizing:=ColorBandChanged;
end;

procedure TScrollPagerTool.HookSubChart(const AChart:TCustomChart);
begin
  AChart.OnAfterDraw:=SubChartTChart_AfterDraw;
  AChart.OnMouseMove:=SubChartTChart_MouseMove;
  AChart.OnMouseDown:=SubChartTChart_MouseDown;
  AChart.OnMouseUp:=SubChartTChart_MouseUp;
end;

Procedure TScrollPagerTool.SetActive(Value:Boolean);
begin
  if Active<>Value then
  begin
    inherited;

    SubChartTool.Active:=Active;
    SetUpChartLayout;
  end;
end;

procedure TScrollPagerTool.Loaded;
var t : Integer;
begin
  inherited;

  // Note: The ugly trick "Tag=1" limits having just one ScrollPager tool per Chart.
  // See GetColorBand and GetSubChartTool methods.

  if Assigned(ParentChart) then
  begin
    for t:=0 to ParentChart.Tools.Count-1 do
    if ParentChart.Tools[t] is TSubChartTool and TSubChartTool(ParentChart.Tools[t]).IsScroller=true then
      if ParentChart.Tools[t] is TSubChartTool then
      begin
        FSubChartTool.Free;

        FSubChartTool:=TSubChartTool(ParentChart.Tools[t]);

        if FSubChartTool.Charts.Count>0 then
           HookSubChart(FSubChartTool.Charts[0].Chart);

        HookColorBand(ColorBandTool);
      end;
  end;

  // Force re-setup:
  Series:=Series;
end;

function TScrollPagerTool.SubChartSeries:TChartSeries;
begin
  if Assigned(FSubChartTool) and (SubChartTChart.SeriesCount>0) then
     result:=SubChartTChart[0]
  else
     result:=nil;
end;

function TScrollPagerTool.GetEndLinePointer: TSeriesPointer;
begin
  if not Assigned(FEndPointer) then
  begin
    FEndPointer:=TScrollPagerPointer.Create(SubChartSeries);
    FEndPointer.Style:=psTriangle;
    FEndPointer.ParentChart:=SubChartTChart;
  end;

  result:=FEndPointer;
end;

function TScrollPagerTool.GetStartLinePointer: TSeriesPointer;
begin
  if not Assigned(FStartPointer) then
  begin
    FStartPointer:=TScrollPagerPointer.Create(SubChartSeries);
    FStartPointer.Style:=psTriangle;
    FStartPointer.ParentChart:=SubChartTChart;
  end;

  result:=FStartPointer;
end;

function TScrollPagerTool.GetSubChartTChart: TChart;
begin
  if SubChartTool.Charts.Count>0 then
     result:=SubChartTool.Charts[0].Chart
  else
  begin
    result:=SubChartTool.Charts.AddChart(''); // SubChartTChart');

    result.MarginLeft:=TeeDefHorizMargin;
    result.MarginTop:=TeeDefVerticalMargin;
    result.MarginRight:=TeeDefHorizMargin;
    result.MarginBottom:=TeeDefVerticalMargin;

    result.View3D:=False;
    result.Title.Visible:=False;
    result.AllowPanning:=pmNone;
    result.Zoom.Allow:=False;

    HookSubChart(result);
  end;
end;

function TScrollPagerTool.GetSubChartTool: TSubChartTool;
begin
  if not Assigned(FSubChartTool) then
  begin
    FSubChartTool:=TSubChartTool.Create(Self);

    // Ugly trick to recognize band tool when loading.
    // This should be done better, using a read/write property.
    //FSubChartTool.Tag:=1;
    FSubChartTool.IsScroller := True;

    FSubChartTool.ShowInEditor:=False;
    FSubChartTool.ParentChart:=ParentChart;

    CreateColorBand;
  end;

  result:=FSubChartTool;
end;

class function TScrollPagerTool.LongDescription: String;
begin
  result:=TeeMsg_ScrollPagerDesc;
end;

function TScrollPagerTool.SeriesPointerClick(X, Y: Integer;
  const Point: TSeriesPointer; Start: Boolean): Boolean;
var tmpBand,
    tmpX,
    tmpY,
    X1,
    Y1: TCoordinate;
    tmpS: Double;
    tmpVert : Boolean;
    tmpColorBand : TColorBandTool;
begin
  tmpColorBand:=ColorBandTool;

  if Assigned(tmpColorBand.Axis) then
  begin
    if Start then tmpS:=tmpColorBand.StartValue
             else tmpS:=tmpColorBand.EndValue;

    tmpBand:=tmpColorBand.Axis.CalcPosValue(tmpS);

    tmpVert:=Assigned(Series) and (not Series.YMandatory);

    if tmpVert then
    begin
      tmpX:=SubChartTChart.Width - (ParentChart.Width - SubChartNotMandatoryAxis.PosAxis);
      X1:=SubChartTChart.Width - (ParentChart.Width - X);

      result:=(Abs(tmpBand - Y) < Point.VertSize) and (Abs(tmpX - X1) < Point.HorizSize);
    end
    else
    begin
      tmpY:=SubChartTChart.Height - (ParentChart.Height - SubChartNotMandatoryAxis.PosAxis);
      Y1:=SubChartTChart.Height - (ParentChart.Height - Y);

      result:=(Abs(tmpBand - X) < Point.HorizSize) and (Abs(tmpY - Y1) < Point.VertSize);
    end;
  end
  else
    result:=False;
end;

procedure TScrollPagerTool.SetNoLimitDrag(const Value:Boolean);
begin
  if not (csLoading in ComponentState) then
     ColorBandTool.NoLimitDrag:=Value;
end;

procedure TScrollPagerTool.SetAlign(const Value:TScrollPagerAlign);
begin
  if FAlign<>Value then
  begin
    FAlign:=Value;
    SetUpChartLayout;
  end;
end;

procedure TScrollPagerTool.SetDivisionRatio(const Value: Double);
begin
  if Value <> FDivisionRatio then
  begin
    FDivisionRatio:=Max(1,Value);
    SetUpChartLayout;
    ParentChart.Invalidate;
  end;
end;

procedure TScrollPagerTool.SetPointerHighlightColor(Value: TColor);
begin
  SetColorProperty(FPointHLColor,Value);
end;

type
  TSeriesAccess=class(TChartSeries);

procedure TScrollPagerTool.SetupSeries(const Value: TChartSeries);

  // Duplicates "Value" series and adds it to the SubChart:
  procedure CopySeries(const Value: TChartSeries);
  var s : TChartSeries;
      Old : Boolean;
  begin
    // Pending: Set Value.ComponentState + [csDesign] to skip assigning Value Data to "s"
    Old:=Value.ManualData;
    Value.ManualData:=False;
    try
      s:=CloneChartSeries(Value,Value.Owner,nil);
      TSeriesAccess(s).DontSerialize:=True;
    finally
      Value.ManualData:=Old;
    end;

    // Link both series to allow automatic refresh whenever "Value" data is changed:
    s.DataSource:=Value;

    //s.ParentChart:=nil; <-- exception at editor listbox

    s.ParentChart:=SubChartTChart;
    s.Color:=Value.Color;
  end;

begin
  if SeriesLinkExists(Value)=nil then
  begin
    CopySeries(Value);
    SetUpScrollPager;
    Repaint;
  end;
end;

procedure TScrollPagerTool.ResetZoomPanning;
begin
  if Series.YMandatory then
  begin
    ParentChart.Zoom.Direction:=tzdHorizontal;
    ParentChart.AllowPanning:=pmHorizontal;
  end
  else
  begin
    ParentChart.Zoom.Direction:=tzdVertical;
    ParentChart.AllowPanning:=pmVertical;
  end;
end;

procedure TScrollPagerTool.SetSeries(const Value: TChartSeries);

  // Destroy series from the scrollpager chart, only the ones that have been
  // "cloned" from main chart.
  // This is done instead of simply calling FreeAllSeries, to allow custom
  // additional series inserted into the subchart.
  procedure FreeClonedSeries;
  var t : Integer;
      tmp : TChartSeries;
  begin
    t:=0;

    while t<SubChartTChart.SeriesCount do
    begin
      tmp:=SubChartTChart[t];

      if TSeriesAccess(tmp).DontSerialize and (tmp.DataSource<>nil) then
         tmp.Free
      else
         Inc(t);
    end;
  end;

var tmp : TChartSeries;
begin
  tmp:=Series;  // Remember old value

  inherited;

  if Assigned(Value) then
  begin
    if Assigned(FSubChartTool) or (not (csLoading in ComponentState)) then
    begin
      FreeClonedSeries;
      SetupSeries(Value);
    end;

    if Assigned(ParentChart) then
       ResetZoomPanning
    else
       ParentChart:=Value.ParentChart;
  end
  else
    RemoveSeries(tmp);
end;

procedure TScrollPagerTool.SetUpChartLayout;

  Function GetMargin({$IFDEF FMX}const {$ENDIF}Value,Range:TCoordinate):TCoordinate;
  begin
    if ParentChart.MarginUnits=muPercent then
       result:=Value*Range {$IFDEF FMX}*0.01{$ELSE}div 100{$ENDIF}
    else
       result:=Value;
  end;

  procedure SetupChartRect;
  var tmpChart : TSubChart;
  begin
    tmpChart:=SubChartTool.Charts[0];

    tmpChart.Chart.MarginUnits:=ParentChart.MarginUnits;

    if Assigned(Series) and Series.YMandatory then
    begin
      tmpChart.Width:={$IFDEF FMX}Round{$ENDIF}(ParentChart.Width);
      tmpChart.Height:=Round(ParentChart.Height / FDivisionRatio);

      tmpChart.Left:=0;

      tmpChart.Chart.MarginLeft:=ParentChart.MarginLeft;
      tmpChart.Chart.MarginRight:=ParentChart.MarginRight;

      if FAlign=saAfter then
      begin
        tmpChart.Top:={$IFDEF FMX}Round{$ENDIF}(ParentChart.Height - tmpChart.Height);
        ParentChart.ChartRect.Bottom:=tmpChart.Top-GetMargin(ParentChart.MarginBottom,tmpChart.Top);
      end
      else
      begin
        tmpChart.Top:=0;
        ParentChart.ChartRect.Top:=tmpChart.Bounds.Bottom+GetMargin(ParentChart.MarginTop,tmpChart.Bounds.Bottom);
      end;
    end
    else
    begin
      tmpChart.Height:={$IFDEF FMX}Round{$ENDIF}(ParentChart.Height);
      tmpChart.Width:=Round(ParentChart.Width / FDivisionRatio);

      tmpChart.Top:=0;

      tmpChart.Chart.MarginTop:=ParentChart.MarginTop;
      tmpChart.Chart.MarginBottom:=ParentChart.MarginBottom;

      if FAlign=saAfter then
      begin
        tmpChart.Left:={$IFDEF FMX}Round{$ENDIF}(ParentChart.Width - tmpChart.Width);
        ParentChart.ChartRect.Right:=tmpChart.Left-GetMargin(ParentChart.MarginRight,tmpChart.Left);
      end
      else
      begin
        tmpChart.Left:=0;
        ParentChart.ChartRect.Left:=tmpChart.Width+GetMargin(ParentChart.MarginLeft,tmpChart.Width);
      end;
    end;
  end;

begin
  if Assigned(ParentChart) then
  begin
    if FAlign=saCustom then
       Repaint
    else
    if Active then
       SetupChartRect;
  end;
end;

// Initial setup of pager band, centered in the middle:
procedure TScrollPagerTool.SetUpColorBand;
const
  OneDiv3=1.0/3.0;

var tmpSize : Double;
    tmpList : TChartValueList;
    tmpBand : TColorBandTool;
begin
  tmpBand:=ColorBandTool;

  tmpBand.Axis:=SubChartNotMandatoryAxis;

  tmpList:=Series.NotMandatoryValueList;
  tmpSize:=tmpList.Range * OneDiv3;

  tmpBand.StartValue:=tmpList.MinValue + tmpSize;
  tmpBand.EndValue:=tmpList.MaxValue - tmpSize;

  tmpBand.Color:=Series.Color;

  ParentNotMandatoryAxis.SetMinMax(tmpBand.StartValue, tmpBand.EndValue);
end;

procedure TScrollPagerTool.SetUpScrollPager;
begin
  SetUpChartLayout;
  SetUpColorBand;
end;

function TScrollPagerTool.SubChartNotMandatoryAxis:TChartAxis;
begin
  if Assigned(Series) then
     if Series.YMandatory then
        result:=SubChartTChart.Axes.Bottom
     else
        result:=SubChartTChart.Axes.Left
  else
    result:=SubChartTChart.Axes.Bottom
end;

procedure TScrollPagerTool.SubChartTChart_AfterDraw(Sender: TObject);
var tmpAxis : TChartAxis;

  procedure DrawPointer(const APointer:TSeriesPointer; APos:Integer);
  begin
    if (APos > tmpAxis.IStartPos) and (APos < tmpAxis.IEndPos) and APointer.Visible then
    begin
      APointer.PrepareCanvas(SubChartTChart.Canvas, APointer.Brush.BackColor);

      if Series.YMandatory then
         APointer.Draw(APos, SubChartNotMandatoryAxis.PosAxis)
      else
         APointer.Draw(SubChartNotMandatoryAxis.PosAxis, APos);
    end;
  end;

var tmpBand : TColorBandTool;
begin
  if Active and Assigned(Series) then
  begin
    tmpBand:=ColorBandTool;

    tmpAxis:=tmpBand.Axis;

    DrawPointer(StartLinePointer,tmpAxis.CalcPosValue(tmpBand.StartValue));
    DrawPointer(EndLinePointer,tmpAxis.CalcPosValue(tmpBand.EndValue));
  end;
end;

procedure TScrollPagerTool.SubChartTChart_MouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: TCoordinate);
var tmpX,
    tmpY : Integer;
    tmpBand : TColorBandTool;
begin
  if not Active then
     Exit;

  tmpX:={$IFDEF FMX}Round{$ENDIF}(X);
  tmpY:={$IFDEF FMX}Round{$ENDIF}(Y);

  FStartPointerClicked:=SeriesPointerClick(tmpX, tmpY, StartLinePointer, True);

  tmpBand:=ColorBandTool;

  if not TTeeColorLineAccess(tmpBand.StartLine).IDragging then
     TTeeColorLineAccess(tmpBand.StartLine).IDragging:=FStartPointerClicked;

  FEndPointerClicked:=SeriesPointerClick(tmpX, tmpY, EndLinePointer, False);

  if not TTeeColorLineAccess(tmpBand.EndLine).IDragging then
     TTeeColorLineAccess(tmpBand.EndLine).IDragging:=FEndPointerClicked;
end;

procedure TScrollPagerTool.ColorBandChanged(Sender: TObject);
var tmpMin,
    tmpMax : Double;
    tmpAxis : TChartAxis;
begin
  tmpMin:=TColorBandTool(Sender).StartValue;
  tmpMax:=TColorBandTool(Sender).EndValue;

  tmpAxis:=ParentNotMandatoryAxis;

  if (tmpAxis.Minimum<>tmpMin) or (tmpAxis.Maximum<>tmpMax) then
  Begin
     tmpAxis.SetMinMax(tmpMin,tmpMax);
     DoScrolled;
  end;
end;

procedure TScrollPagerTool.SubChartTChart_MouseMove(Sender: TObject;
  Shift: TShiftState; X, Y: TCoordinate);

  procedure HighLight(const Point: TScrollPagerPointer; Start: Boolean);
  begin
    if Assigned(Point) then
    begin
      if SeriesPointerClick({$IFDEF FMX}Round{$ENDIF}(X),
                            {$IFDEF FMX}Round{$ENDIF}(Y), Point, Start)<>Point.FMouseIn then
      begin
        Point.FMouseIn:=not Point.FMouseIn;

        if Point.FMouseIn then
        begin
          Point.FOldColor:=Point.Pen.Color;
          Point.Pen.Color:=FPointHLColor;
          Point.FOldColorSaved:=True;
          Repaint;
        end
        else
        if Point.FOldColorSaved then
        begin
          Point.Pen.Color:=Point.FOldColor;
          Repaint;
        end;
      end;
    end;
  end;

begin
  if Active and (SubChartTChart.SeriesCount>0) then
  begin
    HighLight(FStartPointer, True);
    HighLight(FEndPointer, False);
  end;
end;

procedure TScrollPagerTool.SubChartTChart_MouseUp(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: TCoordinate);
begin
  FStartPointerClicked:=False;
  FEndPointerClicked:=False;
end;

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

