unit TeeDoubleHorizBar;
{$I TeeDefs.inc}

interface

uses
  {$IFNDEF FMX}
  {$IFDEF MSWINDOWS}
  Windows,
  {$ENDIF}
  {$ENDIF}

  Classes,

  {$IFDEF FMX}
  FMX.Types,
  System.UITypes,
  FMXTee.Canvas, FMXTee.Engine, FMXTee.Chart, FMXTee.Series, FMXTee.Tools.SubChart
  {$ELSE}

  Graphics,

  TeCanvas, TeEngine, Chart, Series, TeeSubChart
  {$ENDIF}
  ;

type
  TDoubleHorizBarSeries=class(THorizBarSeries)
  private
    FChart : TSubChartTool;
    FSplit : Integer;

    ILeft  : THorizBarSeries;

    procedure AdjustAxes;
    procedure Assign3D;
    procedure DoReposition;
    Procedure GetEmptyLabel(  Sender:TChartAxis; Series:TChartSeries;
                             ValueIndex:Integer; var LabelText:String);
    procedure SetSplit(const Value: Integer);
    procedure SetInvHoriz(const Value: Boolean);
    procedure SetInvVert(const Value: Boolean);
    function GetInvHoriz: Boolean;
    function GetInvVert: Boolean;
  protected
    Procedure AddSampleValues(NumValues:Integer; Sequential:Boolean=False); override;
    procedure AssignFormatting(Source:TChartSeries); override;
    procedure BeforeCalcAxis; override;
    procedure DoBeforeDrawChart; override;
    Procedure GalleryChanged3D(Is3D:Boolean); override;
    class Function GetEditorClass:String; override;
    procedure Loaded; override;
    Procedure PrepareForGallery; override;
    Procedure SetActive(Value:Boolean); override;
    Procedure SetColorEachPoint(Value:Boolean); override;
    Procedure SetParentChart(Const Value:TCustomAxisPanel); override;
  public
    Constructor Create(AOwner: TComponent); override;
    Destructor Destroy; override;

    procedure Add(const Left,Right:Double; const Text:String=''; const Color:TColor=clTeeColor);
    Procedure Clear; override;
    Procedure Delete(ValueIndex:Integer); override;

    function LeftChart:TCustomChart;
    function LeftSeries:THorizBarSeries;
    function RightSeries:THorizBarSeries;
  published
    property InvertedHoriz:Boolean read GetInvHoriz write SetInvHoriz default False;
    property InvertedVert:Boolean read GetInvVert write SetInvVert default False;
    property SplitSize:Integer read FSplit write SetSplit default 50; // %
  end;

implementation

uses
  SysUtils,
  {$IFDEF D6}
  Types,
  {$ENDIF}
  TeeProcs, TeeConst, TeeProCo;

{ TDoubleHorizBarSeries }

Constructor TDoubleHorizBarSeries.Create(AOwner: TComponent);
begin
  inherited;
  FSplit:=50;
end;

Destructor TDoubleHorizBarSeries.Destroy;
begin
  FreeAndNil(ILeft);

  if Assigned(FChart) then
  begin
    FChart.Charts.Clear;
    FreeAndNil(FChart);
  end;

  inherited;
end;

procedure TDoubleHorizBarSeries.SetSplit(const Value: Integer);
begin
  SetIntegerProperty(FSplit,Value);

  if Assigned(ParentChart) then
     ParentChart.MarginLeft:=SplitSize;
end;

function TDoubleHorizBarSeries.LeftChart: TCustomChart;
begin
  result:=LeftSeries.ParentChart as TCustomChart;
end;

procedure TDoubleHorizBarSeries.Add(const Left, Right: Double;
  const Text: String=''; const Color: TColor=clTeeColor);
begin
  inherited Add(Right,Text,Color);

  LeftSeries.Add(Left,Text,Color);
end;

procedure TDoubleHorizBarSeries.Assign3D;

  procedure AssignAxis(const Source,Dest:TChartAxis);
  var Old,
      OldPos : Double;
      OldOther : Boolean;
  begin
    Old:=Dest.ZPosition;
    OldPos:=Dest.PositionPercent;
    OldOther:=Dest.OtherSide;

    Dest.Assign(Source);

    Dest.ZPosition:=Old;
    Dest.PositionPercent:=OldPos;
    Dest.OtherSide:=OldOther;
  end;

var tmp : TCustomChart;
begin
  if Assigned(FChart) then
  begin
    tmp:=FChart.Charts[0].Chart;

    tmp.View3DOptions:=ParentChart.View3DOptions;
    tmp.View3D:=ParentChart.View3D;
    tmp.Chart3DPercent:=ParentChart.Chart3DPercent;

    tmp.Walls:=(ParentChart as TCustomChart).Walls;

    tmp.Walls.Left.Hide;
    tmp.Walls.Right.Hide;

    AssignAxis(GetVertAxis,ILeft.GetVertAxis);
    AssignAxis(GetHorizAxis,ILeft.GetHorizAxis);

    AdjustAxes;

    ILeft.Marks.Assign(Marks);
  end;
end;

procedure TDoubleHorizBarSeries.DoBeforeDrawChart;
begin
  inherited;

  Assign3D;
end;

procedure TDoubleHorizBarSeries.BeforeCalcAxis;
begin
  inherited;
  DoReposition;
end;

procedure TDoubleHorizBarSeries.DoReposition;
var R : TRect;
    tmp : TSubChart;
begin
  if Visible and Assigned(ParentChart) and Assigned(FChart) then
  begin
    R:=ParentChart.ChartRect;
    tmp:=FChart.Charts[0];

    tmp.Width:=R.Left-GetVertAxis.LabelsSize;
    tmp.Height:=ParentChart.Height;

    tmp.Chart.CustomChartRect:=True;
    tmp.Chart.ChartRect.Left:=50;
    tmp.Chart.ChartRect.Right:=tmp.Width;
    tmp.Chart.ChartRect.Top:=R.Top;
    tmp.Chart.ChartRect.Bottom:=R.Bottom;

    Assign3D;
  end;

  if Assigned(ParentChart) then
     if Visible then
        ParentChart.MarginLeft:=SplitSize
     else
        ParentChart.MarginLeft:=TeeDefHorizMargin;
end;

Procedure TDoubleHorizBarSeries.GetEmptyLabel(  Sender:TChartAxis; Series:TChartSeries;
                             ValueIndex:Integer; var LabelText:String);
begin
  if Sender=ILeft.GetVertAxis then
     LabelText:=' ';
end;

procedure TDoubleHorizBarSeries.AdjustAxes;
begin
  if Assigned(ILeft) then
  begin
    ILeft.VertAxis:=aRightAxis;
    ILeft.HorizAxis:=HorizAxis;

    ILeft.GetHorizAxis.Inverted:=not InvertedHoriz;
    ILeft.GetVertAxis.Inverted:=InvertedVert;
  end;
end;

function TDoubleHorizBarSeries.LeftSeries: THorizBarSeries;
var tmpChart : TCustomChart;
begin
  if not Assigned(ILeft) then
  begin
    FChart:=TSubChartTool.Create(nil);
    FChart.ShowInEditor:=False;

    FChart.Charts.AddChart('');

    ILeft:=THorizBarSeries.Create(nil);

    tmpChart:=FChart.Charts[0].Chart;

    ILeft.ParentChart:=tmpChart;

    FChart.ParentChart:=ParentChart;

    AdjustAxes;

    FChart.Charts[0].Left:=0;
    FChart.Charts[0].Top:=0;

    ILeft.ParentChart.OnGetAxisLabel:=GetEmptyLabel;

    if ParentChart<>nil then
       tmpChart.ColorPaletteIndex:=TCustomChart(ParentChart).ColorPaletteIndex;
       
    FChart.Visible:=Visible;

    DoReposition;
  end;

  result:=ILeft;
end;

Procedure TDoubleHorizBarSeries.PrepareForGallery;
begin
  inherited;
  LeftSeries.AssignFormat(Self);
  AdjustAxes;
  (ParentChart as TCustomChart).Title.AdjustFrame:=False;
end;

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

  if Assigned(FChart) then
     FChart.ParentChart:=ParentChart;

  if Assigned(ParentChart) then
  begin
    GetVertAxis.Texts.Align:=alCenter;

    if Assigned(FChart) and (ParentChart is TCustomChart) then
       LeftChart.ColorPaletteIndex:=TCustomChart(ParentChart).ColorPaletteIndex;

    DoReposition;
  end;
end;

class function TDoubleHorizBarSeries.GetEditorClass: String;
begin
  result:='TDoubleHorizBarEditor';
end;

function TDoubleHorizBarSeries.RightSeries: THorizBarSeries;
begin
  result:=Self;
end;

procedure TDoubleHorizBarSeries.SetInvHoriz(const Value: Boolean);
begin
  if InvertedHoriz<>Value then
  begin
    if Assigned(ParentChart) then
       GetHorizAxis.Inverted:=Value;

    if Assigned(FChart) then
       LeftSeries.GetHorizAxis.Inverted:=not Value;
  end;
end;

procedure TDoubleHorizBarSeries.SetInvVert(const Value: Boolean);
begin
  if InvertedVert<>Value then
  begin
    if Assigned(ParentChart) then
       GetVertAxis.Inverted:=Value;

    if Assigned(FChart) then
       LeftSeries.GetVertAxis.Inverted:=Value;
  end;
end;

function TDoubleHorizBarSeries.GetInvHoriz: Boolean;
begin
  if Assigned(ParentChart) then
     result:=GetHorizAxis.Inverted
  else
     result:=False;
end;

function TDoubleHorizBarSeries.GetInvVert: Boolean;
begin
  if Assigned(ParentChart) then
     result:=GetVertAxis.Inverted
  else
     result:=False;
end;

procedure TDoubleHorizBarSeries.AddSampleValues(NumValues: Integer;
  Sequential: Boolean);
var t : Integer;
begin
  inherited;

  for t:=0 to Count-1 do
      LeftSeries.Add(Random*MandatoryValueList[t],Labels[t]);
end;

Procedure TDoubleHorizBarSeries.Clear;
begin
  inherited;

  if Assigned(ILeft) then
     ILeft.Clear;
end;

procedure TDoubleHorizBarSeries.Delete(ValueIndex: Integer);
begin
  inherited;

  if Assigned(ILeft) then
     ILeft.Delete(ValueIndex);
end;

procedure TDoubleHorizBarSeries.SetActive(Value: Boolean);
begin
  inherited;

  if Assigned(FChart) then
     FChart.Visible:=Visible;

  DoReposition;
end;

procedure TDoubleHorizBarSeries.Loaded;

   function FindSubChart:TSubChartTool;
   var t : Integer;
       tmp : TTeeCustomTool;
   begin
     result:=nil;

     for t:=0 to ParentChart.Tools.Count-1 do
     begin
       tmp:=ParentChart.Tools[t];

       if tmp is TSubChartTool then
       begin
         result:=TSubChartTool(tmp);
         break;
       end;
     end;
   end;

var tmp : TSubChartTool;
begin
  inherited;

  if Assigned(ParentChart) then
  begin
    tmp:=FindSubChart;

    if Assigned(tmp) and (tmp.Charts.Count>0) then
    begin
      FChart:=tmp;
      ILeft:=FChart.Charts[0].Chart.Series[0] as THorizBarSeries;
    end;
  end;
end;

procedure TDoubleHorizBarSeries.GalleryChanged3D(Is3D: Boolean);
begin
  inherited;

  ParentChart.View3DOptions.Orthogonal:=True;
  DoReposition;
end;

procedure TDoubleHorizBarSeries.SetColorEachPoint(Value: Boolean);
begin
  inherited;
  LeftSeries.ColorEachPoint:=ColorEachPoint;
end;

procedure TDoubleHorizBarSeries.AssignFormatting(Source: TChartSeries);
begin
  inherited;
  AdjustAxes;
end;

initialization
  RegisterTeeSeries( TDoubleHorizBarSeries, @TeeMsg_GalleryDoubleBar,
                                    @TeeMsg_GalleryStandard,1);
finalization
  UnRegisterTeeSeries([TDoubleHorizBarSeries]);
end.
