{**********************************************}
{   TSeriesPointer Component Editor Dialog     }
{   Copyright (c) 1996-2020 by Steema Software }
{**********************************************}
unit TeePoEdi;
{$I TeeDefs.inc}

interface

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

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

     Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls, ComCtrls, Buttons,

     TeeProcs, Chart, TeEngine, TeCanvas, Series, TeePenDlg, TeeVisualsEditor,
     TeeGalleryPanel, TeeEdiGrad, TeeShadowEditor;

type
  TSeriesPointerEditor = class(TForm)
    PanelBottom: TPanel;
    Panel1: TPanel;
    Button1: TButton;
    PageControl1: TPageControl;
    TabFormat: TTabSheet;
    TabSize: TTabSheet;
    CBInflate: TCheckBox;
    CBDrawPoint: TCheckBox;
    CB3dPoint: TCheckBox;
    CBPoDark: TCheckBox;
    CBColorEach: TCheckBox;
    CBIgnoreNulls: TCheckBox;
    LTransp: TLabel;
    TBTransp: TTrackBar;
    TabVisual: TTabSheet;
    TabStyle: TTabSheet;
    Panel2: TPanel;
    Label3: TLabel;
    CBStyle: TComboFlat;
    StyleGallery: TChartGalleryPanel;
    TabPattern: TTabSheet;
    TabBorder: TTabSheet;
    TabShadow: TTabSheet;
    TabEmboss: TTabSheet;
    LColorTransp: TLabel;
    GroupBox1: TGroupBox;
    Label1: TLabel;
    Label2: TLabel;
    SEPointHorizSize: TEdit;
    SEPointVertSize: TEdit;
    UDPointHorizSize: TUpDown;
    UDPointVertSize: TUpDown;
    Label5: TLabel;
    ESize: TEdit;
    UDSize: TUpDown;
    Panel3: TPanel;
    CBDefBrushColor: TCheckBox;
    CBFullGradient: TCheckBox;
    CBPointUnits: TComboFlat;
    Label4: TLabel;
    SEPointDepth: TEdit;
    UDPointDepth: TUpDown;
    Label6: TLabel;
    TabPicture: TTabSheet;
    Panel4: TPanel;
    Label7: TLabel;
    TBDarkPen: TTrackBar;
    procedure FormShow(Sender: TObject);
    procedure CBDrawPointClick(Sender: TObject);
    procedure CB3dPointClick(Sender: TObject);
    procedure SEPointHorizSizeChange(Sender: TObject);
    procedure CBStyleChange(Sender: TObject);
    procedure SEPointVertSizeChange(Sender: TObject);
    procedure CBInflateClick(Sender: TObject);
    procedure CBPoDarkClick(Sender: TObject);
    procedure CBDefBrushColorClick(Sender: TObject);
    procedure CBStyleDrawItem(Control: TWinControl; Index: Integer;
      Rect: TRect; State: TOwnerDrawState);
    procedure CBColorEachClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure CBIgnoreNullsClick(Sender: TObject);
    procedure TBTranspChange(Sender: TObject);
    procedure SEPointDepthChange(Sender: TObject);
    procedure PageControl1Change(Sender: TObject);
    procedure StyleGalleryChangeChart(Sender: TObject);
    procedure StyleGalleryResize(Sender: TObject);
    procedure CBFullGradientClick(Sender: TObject);
    procedure ESizeChange(Sender: TObject);
    procedure CBPointUnitsChange(Sender: TObject);
    procedure PageControl1GetImageIndex(Sender: TObject; TabIndex: Integer;
      var ImageIndex: Integer);
    procedure TBDarkPenChange(Sender: TObject);
  private
    { Private declarations }

    IChanging  : Boolean;
    ISelecting : Boolean;

    procedure ChangedVisual(Sender:TObject);
    Procedure CheckDefColor;
    function CustomSeries:TCustomSeries;
    Procedure Enable3DPoint;
    procedure SetPointerStyle;
    procedure SetPointerVisible(Value:Boolean);
  protected
    ThePointer : TSeriesPointer;
  public
    { Public declarations }

    class function InsertForm(const APointer:TSeriesPointer; const AParent:TWinControl):TSeriesPointerEditor;
    procedure HideSizeOptions;
  end;

// Modally show the Pointer editor dialog
function EditSeriesPointer(AOwner:TComponent; APointer:TSeriesPointer):Boolean;

{ Adds a new sub-tab Form into the Series tab at EditChart dialog }
Function TeeInsertPointerForm( AParent:TControl;
                               APointer:TSeriesPointer;
                               Const Title:String):TCustomForm;

implementation

{$IFNDEF LCL}
{$R *.DFM}
{$ELSE}
{$R *.lfm}
{$ENDIF}

uses TypInfo,
     TeeBrushDlg, TeeConst, TeeEdiSeri, TeeBackImage;

function EditSeriesPointer(AOwner:TComponent; APointer:TSeriesPointer):Boolean;
var tmp : TSeriesPointerEditor;
begin
  tmp:=TSeriesPointerEditor(TeeCreateForm(TSeriesPointerEditor,AOwner));

  with tmp do
  try
    PositionToCenter(tmp);
    Caption:='Pointer'; // <-- do not translate
    Tag:=ObjectToTag(APointer);
    CBInflate.Hide;
    CBColorEach.Hide;
    PanelBottom.Visible:=True;

    TeeTranslateControl(tmp);
    ShowModal;

    result:=True;
  finally
    Free;
  end;
end;

Function TeeInsertPointerForm( AParent:TControl;
                               APointer:TSeriesPointer;
                               Const Title:String):TCustomForm;

begin
  result:=TFormTeeSeries.InsertSeriesForm(AParent,TSeriesPointerEditor,1,Title,APointer);
end;

Procedure TSeriesPointerEditor.Enable3DPoint;
begin
  With ThePointer do
  CB3DPoint.Enabled:= Assigned(ParentChart) and
                      ParentChart.View3D and
                      ( (Style=psRectangle) or
                        (Style=psTriangle) or
                        (Style=psDownTriangle) or
                        (ParentChart.Canvas.SupportsFullRotation
                         and (Style=psCircle))
                      );

  CBPoDark.Enabled:=CB3DPoint.Enabled and CB3DPoint.Checked;
end;

procedure TSeriesPointerEditor.SetPointerStyle;
begin
  CBStyle.ItemIndex:=CBStyle.Items.IndexOfObject(TObject(Ord(ThePointer.Style)));
end;

type
  TPointerAccess=class(TSeriesPointer);
  TCustomChartAccess=class(TCustomChart);

procedure TSeriesPointerEditor.FormShow(Sender: TObject);
begin
  if Tag<>0 then
  begin
    if TPersistent(Tag) is TSeriesPointer then
    begin
      ThePointer:=TSeriesPointer(Tag);

      CBColorEach.Enabled:=False;
      CBColorEach.Visible:=False;

      CBIgnoreNulls.Enabled:=False;
      CBIgnoreNulls.Visible:=False;
    end
    else
    begin
      ThePointer:=CustomSeries.Pointer;
      CBColorEach.Visible:=True;
      CBColorEach.Checked:=CustomSeries.ColorEachPoint;

      CBIgnoreNulls.Visible:=True;
      CBIgnoreNulls.Checked:= CustomSeries.TreatNulls=tnIgnore;
    end;

    With ThePointer do
    Begin
      SetPointerVisible(Visible);
      CBDrawPoint.Checked:=Visible;
      CB3DPoint.Checked:=Draw3D;

      Enable3DPoint;

      IChanging:=True;

      UDSize.Position:=Size;
      UDPointHorizSize.Position:=HorizSize;
      UDPointVertSize.Position :=VertSize;
      UDPointDepth.Position:=Depth;

      CBPointUnits.ItemIndex:=Ord(SizeUnits);

      IChanging:=False;

      SetPointerStyle;

      CBInflate.Checked:=InflateMargins;
      CBPoDark.Checked:=Dark3D;
      TBDarkPen.Position:=DarkPen;

      CheckDefColor;

      TBTransp.Position:=Transparency;
      TBTranspChange(Self);

      if not TPointerAccess(ThePointer).AllowChangeSize then
         ShowControls(False,[ Label1,Label2,SEPointHorizSize,
                              SEPointVertSize,UDPointHorizSize,UDPointVertSize]);

      TabVisual.TabVisible:=Assigned(TeeOnChangeVisual) and
                           (TCustomChartAccess(ParentChart).Form3DClass<>nil);
    end;
  end;

  TeeTranslateControl(Self);
end;

Procedure TSeriesPointerEditor.CheckDefColor;
begin
  if Assigned(ThePointer) then
     CBDefBrushColor.Checked:=(ThePointer.Color=clTeeColor) and (ThePointer.Pen.Color=clTeeColor);
end;

procedure TSeriesPointerEditor.SetPointerVisible(Value:Boolean);
begin
  ThePointer.Visible:=Value;

  if Value then Enable3DPoint
  else
  begin
    CB3DPoint.Enabled:=False;
    CBPoDark.Enabled:=False;
  end;

  EnableControls(Value,[ CBInflate,SEPointHorizSize,SEPointVertSize,
                         UDPointHorizSize,UDPointVertSize,
                         CBStyle,CBDefBrushColor] );
end;

procedure TSeriesPointerEditor.CBDrawPointClick(Sender: TObject);
begin
  SetPointerVisible(CBDrawPoint.Checked);
end;

procedure TSeriesPointerEditor.CB3dPointClick(Sender: TObject);
begin
  ThePointer.Draw3D:=CB3DPoint.Checked;
  CBPoDark.Enabled:=CB3DPoint.Checked;
end;

procedure TSeriesPointerEditor.SEPointHorizSizeChange(Sender: TObject);
begin
  if Showing then
  begin
    ThePointer.HorizSize:=UDPointHorizSize.Position;

    if ThePointer.HorizSize=ThePointer.VertSize then
       UDSize.Position:=ThePointer.Size;
  end;
end;

procedure TSeriesPointerEditor.CBStyleChange(Sender: TObject);
begin
  if CBStyle.ItemIndex>-1 then
  begin
    ThePointer.Style:=TSeriesPointerStyle(CBStyle.Items.Objects[CBStyle.ItemIndex]);

    Enable3DPoint;

    if StyleGallery.Charts.Count>0 then
    begin
      ISelecting:=True;
      StyleGallery.SelectedChart:=StyleGallery.Charts[CBStyle.ItemIndex];
      ISelecting:=False;
    end;
  end;
end;

procedure TSeriesPointerEditor.SEPointVertSizeChange(Sender: TObject);
begin
  if Showing then
  begin
    ThePointer.VertSize:=UDPointVertSize.Position;

    if ThePointer.HorizSize=ThePointer.VertSize then
       UDSize.Position:=ThePointer.Size;
  end;
end;

procedure TSeriesPointerEditor.CBInflateClick(Sender: TObject);
begin
  ThePointer.InflateMargins:=CBInflate.Checked;
end;

procedure TSeriesPointerEditor.CBPoDarkClick(Sender: TObject);
begin
  ThePointer.Dark3D:=CBPoDark.Checked;
end;

procedure TSeriesPointerEditor.CBDefBrushColorClick(Sender: TObject);
begin
  if CBDefBrushColor.Checked then
  begin
    ThePointer.Color:=clTeeColor;
    ThePointer.Pen.Color:=clTeeColor;
  end
  else
  if ThePointer.Pen.Color=clTeeColor then
     ThePointer.Pen.Color:=clBlack;

  CBStyle.Repaint;
end;

procedure TSeriesPointerEditor.CBStyleDrawItem(Control: TWinControl;
  Index: Integer; Rect: TRect; State: TOwnerDrawState);
var tmp : TColor;
    Old : TColor;
    ACanvas  : TTeeCanvas3D;
    tmpStyle : TSeriesPointerStyle;
    OldUnits : TPointerSizeUnits;

begin
  Old:=CBStyle.Canvas.Brush.Color;

  // background
  CBStyle.Canvas.FillRect(Rect);

  // pointer shape
  With TPointerAccess(ThePointer) do
  begin
    ACanvas:=TTeeCanvas3D.Create;
    try
      ACanvas.ReferenceCanvas:=CBStyle.Canvas;

      tmp:=Brush.Color;
      if (tmp=clTeeColor) and Assigned(ParentSeries) then
         tmp:=ParentSeries.SeriesColor;

      PrepareCanvas(ACanvas,tmp);

      tmpStyle:=TSeriesPointerStyle(CBStyle.Items.Objects[Index]);

      case tmpStyle of
        psCross,
        psDiagCross,
        psStar,
        psSmallDot:
            if not Pen.Visible then
            with ACanvas.Pen do
            begin
              Style:=psSolid;
              Width:=1;
              Color:=tmp;
            end;
      end;

      OldUnits:=SizeUnits;
      SizeUnits:=suPixels;

      DrawPointer(ACanvas,False,Rect.Left+6,Rect.Top+6+2,4,4,tmp,tmpStyle);

      SizeUnits:=OldUnits;
    finally
      ACanvas.Free;
    end;
  end;

  // text
  With CBStyle,Canvas do
  begin
    Brush.Style:=bsClear;
    Brush.Color:=Old;

    {$IFNDEF LCL}
    TControlCanvas(CBStyle.Canvas).UpdateTextFlags;
    {$ENDIF}

    TextOut(Rect.Left+14,Rect.Top+2,Items[Index]);
  end;
end;

function TSeriesPointerEditor.CustomSeries:TCustomSeries;
begin
  if TPersistent(Tag) is TSeriesPointer then
     result:=TSeriesPointer(Tag).ParentSeries as TCustomSeries
  else
     result:=TCustomSeries(Tag);
end;

procedure TSeriesPointerEditor.CBColorEachClick(Sender: TObject);
begin
  CustomSeries.ColorEachPoint:=CBColorEach.Checked;
end;

procedure TSeriesPointerEditor.FormCreate(Sender: TObject);
var t : Integer;
begin
  Align:=alClient;

  PageControl1.ActivePage:=TabFormat;

  // Sort Style combobox items:

  with CBStyle.Items do
  for t:=0 to Count-1 do
      Objects[t]:=TObject(t);

  CBStyle.Sorted:=True;
end;

procedure TSeriesPointerEditor.HideSizeOptions;
begin
  Label1.Visible:=False;
  SEPointHorizSize.Visible:=False;
  UDPointHorizSize.Visible:=False;
  Label2.Visible:=False;
  SEPointVertSize.Visible:=False;
  UDPointVertSize.Visible:=False;
end;

procedure TSeriesPointerEditor.Button1Click(Sender: TObject);
begin
  Close;
end;

procedure TSeriesPointerEditor.CBIgnoreNullsClick(Sender: TObject);
begin
  if CBIgnoreNulls.Checked then
     CustomSeries.TreatNulls:=tnIgnore
  else
     CustomSeries.TreatNulls:=tnDontPaint;
end;

procedure TSeriesPointerEditor.TBTranspChange(Sender: TObject);
begin
  ThePointer.Transparency:=TBTransp.Position;
  LColorTransp.Caption:=IntToStr(TBTransp.Position)+' %';
end;

procedure TSeriesPointerEditor.SEPointDepthChange(Sender: TObject);
begin
  if Showing then
     ThePointer.Depth:=UDPointDepth.Position;
end;

procedure TSeriesPointerEditor.PageControl1Change(Sender: TObject);
var t : Integer;
    tmp : TGalleryChart;
    tmpColor : TColor;
    IVisualEditor:TVisualsEditor;
begin
  if not Assigned(ThePointer) then
     Exit;

  if (PageControl1.ActivePage=TabVisual) and (TabVisual.ControlCount=0) then
  begin
    if Assigned(ThePointer.ParentSeries) then
    begin
      IVisualEditor:=TVisualsEditor.Create(Self);
      IVisualEditor.Align:=alClient;
      IVisualEditor.OnChangedVisual:=ChangedVisual;

      AddFormTo(IVisualEditor,TabVisual,ThePointer.ParentSeries.Visuals);
    end;
  end
  else
  if (PageControl1.ActivePage=TabPattern) and (TabPattern.ControlCount<2) then
     TBrushDialog.AddDialog(ThePointer.Brush,TabPattern)
  else
  if PageControl1.ActivePage=TabStyle then
  begin
    if StyleGallery.Charts.Count=0 then
    begin
      for t:=0 to CBStyle.Items.Count-1 do
      begin
        tmp:=TGalleryChart.Create(StyleGallery);
        tmp.AddSeries(TPointSeries).Add(0);

        tmp.View3DOptions.Orthogonal:=True;

        tmp.Axes.Hide;
        tmp.Walls.Hide;

        TPointSeries(tmp[0]).Pointer.Style:=TSeriesPointerStyle(CBStyle.Items.Objects[t]);
        TPointSeries(tmp[0]).Pointer.Size:=14;

        tmpColor:=ThePointer.Color;

        if (tmpColor=clDefault) and Assigned(ThePointer.ParentSeries) then
           tmpColor:=ThePointer.ParentSeries.Color;

        if tmpColor<>StyleGallery.Color then
           TPointSeries(tmp[0]).Pointer.Color:=tmpColor;

        tmp.Hint:=CBStyle.Items[t];
        tmp.ShowHint:=True;
        tmp.Title.Caption:=tmp.Hint;

        StyleGallery.Charts.Add(tmp);
        tmp.Parent:=StyleGallery;
        StyleGallery.FinishAdd(tmp);
      end;

      StyleGallery.ResizeCharts;

      StyleGallery.View3D:=ThePointer.ParentChart.View3D and ThePointer.Draw3D;

      CBStyleChange(Self);
    end
    else
      CBStyle.Repaint;
  end
  else
  if (PageControl1.ActivePage=TabBorder) and (TabBorder.ControlCount=1) then
     TPenDialog.InsertForm(ThePointer.Pen,TabBorder)
  else
  if PageControl1.ActivePage=TabFormat then
     CheckDefColor
  else
  if (PageControl1.ActivePage=TabShadow) and (TabShadow.ControlCount=0) then
     TTeeShadowEditor.InsertForm(ThePointer.Shadow,TabShadow)
  else
  if (PageControl1.ActivePage=TabEmboss) and (TabEmboss.ControlCount=0) then
     TTeeShadowEditor.InsertForm(ThePointer.Emboss,TabEmboss)
  else
  if (PageControl1.ActivePage=TabPicture) and (TabPicture.ControlCount=0) then
     TBackImageEditor.InsertForm(TabPicture,ThePointer.Picture);
end;

procedure TSeriesPointerEditor.ChangedVisual(Sender:TObject);
begin
  if Assigned(ThePointer.ParentSeries.Visuals.Template) then
     ThePointer.Style:=psVisual
  else
     ThePointer.Style:=psCircle;

  SetPointerStyle;
end;

procedure TSeriesPointerEditor.StyleGalleryChangeChart(Sender: TObject);
begin
  CBStyle.ItemIndex:=StyleGallery.Charts.IndexOf(StyleGallery.SelectedChart);
  CBStyleChange(Self);
end;

procedure TSeriesPointerEditor.StyleGalleryResize(Sender: TObject);
var tmp,t : Integer;
begin
  tmp:=Round(0.25*(StyleGallery.Width/StyleGallery.NumCols));

  for t:=0 to StyleGallery.Charts.Count-1 do
      TCustomSeries(StyleGallery.Charts[t].Series[0]).Pointer.Size:=tmp;
end;

procedure TSeriesPointerEditor.CBFullGradientClick(Sender: TObject);
begin
  ThePointer.FullGradient:=CBFullGradient.Checked;
end;

class function TSeriesPointerEditor.InsertForm(const APointer:TSeriesPointer; const AParent:TWinControl):TSeriesPointerEditor;
begin
  result:=TSeriesPointerEditor.Create(AParent.Owner);
  result.ThePointer:=APointer;
  AddFormTo(result,AParent,APointer);
end;

procedure TSeriesPointerEditor.ESizeChange(Sender: TObject);
begin
  if Showing and (not IChanging) and (ThePointer.Size<>UDSize.Position) then
  begin
    ThePointer.Size:=UDSize.Position;
    UDPointHorizSize.Position:=ThePointer.Size;
    UDPointVertSize.Position:=ThePointer.Size;
  end;
end;

procedure TSeriesPointerEditor.CBPointUnitsChange(Sender: TObject);
begin
  if Showing and (not IChanging) then
     ThePointer.SizeUnits:=TPointerSizeUnits(CBPointUnits.ItemIndex);
end;

procedure TSeriesPointerEditor.PageControl1GetImageIndex(Sender: TObject;
  TabIndex: Integer; var ImageIndex: Integer);
begin
// Dummy to avoid AV
end;

procedure TSeriesPointerEditor.TBDarkPenChange(Sender: TObject);
begin
  ThePointer.DarkPen:=TBDarkPen.Position;
end;

initialization
  RegisterSeriesEditor(TSeriesPointerEditor);
end.
