{**************************************************}
{  TCustomChartSeries (or derived) Editor Dialog   }
{  Copyright (c) 1996-2020 by Steema Software      }
{**************************************************}
unit TeeEdiSeri;
{$I TeeDefs.inc}

interface

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

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

     {$IFDEF MSWINDOWS}
     TeeGDIPlus,
     {$ENDIF}

     {$IFDEF LINUX}
     Types,
     {$ENDIF}
     TeEngine, TeeCustomShapeEditor, TeeProcs, TeCanvas, TeePenDlg,
     Chart, TeeSourceEdit, TeeChartGrid, TeeNavigator, TeeLisB, TeeMargins,
     TeeGalleryPanel, Series, TeeBackImage, TeeTextShapeEditor;

type
  TFormTeeSeries=class;

  // Note: These two types should be here, before TFormTeeSeries declaration,
  //       to workaround a BCB bug. QC109128 / QC88686
  // Used by TeeChart Pro ActiveX and TeeChartOffice:
  TOnCreateEditSeries=Procedure(Sender:TFormTeeSeries; AChart:TCustomChart);
  TOnCreateEditSeriesObj=Procedure(Sender:TFormTeeSeries; AChart:TCustomChart) of object;

  TNotifyTeeEvent=procedure(Sender:TFormTeeSeries; Event:TTeeEvent) of object;

  TFormTeeSeries = class(TForm,ITeeEventListener)
    CBPersistent: TCheckBox;
    PageSeries: TPageControl;
    TheTabSheet: TTabSheet;
    TabGeneral: TTabSheet;
    TabMarks: TTabSheet;
    TabDataSource: TTabSheet;
    PageControlMarks: TPageControl;
    TabSheet1: TTabSheet;
    CBMarksVisible: TCheckBox;
    CBMarkClip: TCheckBox;
    L23: TLabel;
    Label3: TLabel;
    EMarksEvery: TEdit;
    UDEvery: TUpDown;
    CBMultiLine: TCheckBox;
    CBSeries: TComboFlat;
    ImageSeries: TImage;
    LabelSeriesClass: TLabel;
    PanelTop: TPanel;
    Panel2: TPanel;
    PanTop: TPanel;
    CBDataSourcestyle: TComboFlat;
    CBAllVisible: TCheckBox;
    PaintBox1: TPaintBox;
    Panel3: TPanel;
    NewDataButton: TButton;
    EditDataButton: TButton;
    DeleteDataButton: TButton;
    ChartGrid1: TChartGrid;
    ChartGridNavigator1: TChartGridNavigator;
    PanelRandomSource: TPanel;
    PanelSeriesSource: TPanel;
    Label2: TLabel;
    ESamples: TEdit;
    CBSamplesDefault: TCheckBox;
    BApplyRandom: TButton;
    TabSheet2: TTabSheet;
    Timer1: TTimer;
    TabSymbol: TTabSheet;
    Button3: TButton;
    Label5: TLabel;
    CBSeriesSource: TComboFlat;
    BApplySource: TButton;
    BClearSource: TButton;
    TabMargins: TTabSheet;
    CBFontSeriesColor: TCheckBox;
    CBAutoPos: TCheckBox;
    TabMarksText: TTabSheet;
    TabMarksGallery: TTabSheet;
    MarksGallery: TChartGalleryPanel;
    ChartMarks: TChart;
    Series1: TBarSeries;
    Series2: TBarSeries;
    Series3: TBarSeries;
    Series4: TBarSeries;
    Series5: TBarSeries;
    Series6: TBarSeries;
    Series7: TBarSeries;
    Series8: TBarSeries;
    Series9: TBarSeries;
    PageArrows: TPageControl;
    TabSheet3: TTabSheet;
    TabArrowBorder: TTabSheet;
    TabArrowPointer: TTabSheet;
    L32: TLabel;
    Label4: TLabel;
    Label11: TLabel;
    Label12: TLabel;
    SEArrowLength: TEdit;
    UDArrowsLength: TUpDown;
    EArrowDist: TEdit;
    UDArrowDist: TUpDown;
    CBHead: TComboFlat;
    Edit1: TEdit;
    UDHeadSize: TUpDown;
    PageMarksItems: TPageControl;
    TabSheet4: TTabSheet;
    TabMarksFormat: TTabSheet;
    Panel1: TPanel;
    Splitter1: TSplitter;
    Panel4: TPanel;
    BAdd: TSpeedButton;
    BDelete: TSpeedButton;
    CBLayout: TComboFlat;
    LBChildren: TListBox;
    Label1: TLabel;
    RGMarkStyle: TComboFlat;
    CBMarkChildVisible: TCheckBox;
    Label6: TLabel;
    CBTextAlign: TComboFlat;
    CBOnTop: TCheckBox;
    TBAngle: TTrackBar;
    LAngle: TLabel;
    CBSoftClip: TCheckBox;
    CBSeriesTransp: TCheckBox;
    CBTransparent: TCheckBox;
    PageControl1: TPageControl;
    TabOptions: TTabSheet;
    TabLegend: TTabSheet;
    GB5: TGroupBox;
    L27: TLabel;
    LDepth: TLabel;
    SpeedButton1: TSpeedButton;
    CBCursor: TComboFlat;
    EDepth: TEdit;
    UDDepth: TUpDown;
    CBDepth: TCheckBox;
    GB2: TGroupBox;
    L15: TLabel;
    L21: TLabel;
    Button1: TSpeedButton;
    Button2: TSpeedButton;
    EPercentFormat: TEdit;
    CBFormat: TComboFlat;
    GBHorizAxis: TGroupBox;
    CBHorizAxis: TComboFlat;
    CBXDateTime: TCheckBox;
    GBVertAxis: TGroupBox;
    CBVertAxis: TComboFlat;
    CBYDateTime: TCheckBox;
    CBZDateTime: TCheckBox;
    CBShowInEditor: TCheckBox;
    GroupBox1: TGroupBox;
    CBSortBy: TComboFlat;
    CBSortOrder: TComboFlat;
    BVisual: TButton;
    CBCaseSensitive: TCheckBox;
    Panel5: TPanel;
    CBShowInLegend: TCheckBox;
    Label7: TLabel;
    ELegendText: TEdit;
    TabHover: TTabSheet;
    PanelDetail: TPanel;
    DetailGrid: TChartGrid;
    CBAggregate: TComboFlat;
    Splitter2: TSplitter;
    PanelDetailTotal: TPanel;
    LabelDetail: TLabel;
    LabelDetailTotal: TLabel;
    TabTail: TTabSheet;
    CBTailVisible: TCheckBox;
    Label8: TLabel;
    Label9: TLabel;
    ETailHeight: TEdit;
    UDTailHeight: TUpDown;
    ETailWidth: TEdit;
    UDTailWidth: TUpDown;
    Label10: TLabel;
    ETailMargin: TEdit;
    UDTailMargin: TUpDown;
    GroupBox2: TGroupBox;
    LHorizAlign: TLabel;
    CBTailEdge: TComboBox;
    CBAlign: TCheckBox;
    LVertAlign: TLabel;
    CBTailAlign: TComboBox;
    procedure EPercentFormatChange(Sender: TObject);
    procedure PageSeriesChange(Sender: TObject);
    procedure CBSeriesChange(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure RGMarkStyleClick(Sender: TObject);
    procedure CBPersistentClick(Sender: TObject);
    procedure CBYDateTimeClick(Sender: TObject);
    procedure CBXDateTimeClick(Sender: TObject);
    procedure CBDataSourcestyleChange(Sender: TObject);
    procedure CBCursorChange(Sender: TObject);
    procedure SEArrowLengthChange(Sender: TObject);
    procedure CBMarkClipClick(Sender: TObject);
    procedure CBMarksVisibleClick(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure CBHorizAxisChange(Sender: TObject);
    procedure CBVertAxisChange(Sender: TObject);
    procedure EMarksEveryChange(Sender: TObject);
    procedure CBMultiLineClick(Sender: TObject);
    procedure CBSortOrderChange(Sender: TObject);
    procedure CBFormatChange(Sender: TObject);
    procedure PageSeriesChanging(Sender: TObject;
      var AllowChange: Boolean);
    procedure CBDepthClick(Sender: TObject);
    procedure EDepthChange(Sender: TObject);
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
    procedure CBAllVisibleClick(Sender: TObject);
    procedure PaintBox1Paint(Sender: TObject);
    procedure PaintBox1Click(Sender: TObject);
    procedure CBSamplesDefaultClick(Sender: TObject);
    procedure ESamplesChange(Sender: TObject);
    procedure BApplyRandomClick(Sender: TObject);
    procedure EArrowDistChange(Sender: TObject);
    procedure CBHeadChange(Sender: TObject);
    procedure Edit1Change(Sender: TObject);
    procedure ChartGrid1SetEditText(Sender: TObject; ACol, ARow: Integer;
      const Value: String);
    procedure Timer1Timer(Sender: TObject);
    procedure CBZDateTimeClick(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure CBShowInEditorClick(Sender: TObject);
    procedure CBSeriesSourceChange(Sender: TObject);
    procedure BApplySourceClick(Sender: TObject);
    procedure BClearSourceClick(Sender: TObject);
    procedure PageControlMarksChange(Sender: TObject);
    procedure CBTextAlignChange(Sender: TObject);
    procedure SpeedButton1Click(Sender: TObject);
    procedure CBFontSeriesColorClick(Sender: TObject);
    procedure CBSortByChange(Sender: TObject);
    procedure BVisualClick(Sender: TObject);
    procedure CBCaseSensitiveClick(Sender: TObject);
    procedure CBAutoPosClick(Sender: TObject);
    procedure MarksGalleryChangeChart(Sender: TObject);
    procedure PageArrowsChange(Sender: TObject);
    procedure PageMarksItemsChange(Sender: TObject);
    procedure BAddClick(Sender: TObject);
    procedure CBLayoutChange(Sender: TObject);
    procedure BDeleteClick(Sender: TObject);
    procedure LBChildrenClick(Sender: TObject);
    procedure CBMarkChildVisibleClick(Sender: TObject);
    procedure TBAngleChange(Sender: TObject);
    procedure CBOnTopClick(Sender: TObject);
    procedure CBSoftClipClick(Sender: TObject);
    procedure CBSeriesTranspClick(Sender: TObject);
    procedure CBTransparentClick(Sender: TObject);
    procedure PageControl1Change(Sender: TObject);
    procedure CBShowInLegendClick(Sender: TObject);
    procedure ELegendTextChange(Sender: TObject);
    procedure ChartGrid1Click(Sender: TObject);
    procedure PanTopResize(Sender: TObject);
    procedure CBAggregateChange(Sender: TObject);
    procedure DetailGridClick(Sender: TObject);
    procedure DetailGridSetEditText(Sender: TObject; ACol, ARow: Integer;
      const Value: String);
    procedure CBTailVisibleClick(Sender: TObject);
    procedure ETailHeightChange(Sender: TObject);
    procedure ETailWidthChange(Sender: TObject);
    procedure ETailMarginChange(Sender: TObject);
    procedure CBTailEdgeChange(Sender: TObject);
    procedure CBAlignClick(Sender: TObject);
    procedure CBTailAlignChange(Sender: TObject);
  private
    { Private declarations }
    TheChart        : TCustomAxisPanel;
    CreatingForm    : Boolean;
    ChangingPage    : Boolean;
    IHover          : TFormTeeShape;
    ILegend         : TBackImageEditor;
    IMarksMargins   : TMarginsEditor;
    IMarksObject    : TForm;
    IMarksSymbol    : TFormTeeShape;
    LastSeries      : TChartSeries;
    FOnTeeEvent     : TNotifyTeeEvent;

    IChangingMarks  : Boolean;

    procedure AddChildItem(Index:Integer);
    Function AddToTab(AForm:TForm; ATab:TTabSheet; AObject:TPersistent):TForm;
    Function AllSeriesMarksVisible:Boolean;
    Function CanModifySeries:Boolean;
    Function CheckCanClose:Boolean;
    procedure CheckCBSamples;
    procedure DestroyDataSourceForm;
    procedure EnableMultiLine;
    procedure EnableTailAlign;
    procedure FillAxis(Items:TStrings; Horizontal:Boolean);
    Function FindZList:TChartValueList;
    procedure SetTabDataSource;
    procedure SetTabSeriesMarks;
    procedure SetTailProperties(const ATail:TMarksTail);
    procedure TeeEvent(Event: TTeeEvent);  { interface }

  protected
    procedure CreateDataSourceForm;
  public
    { Public declarations }
    TheSeries             : TChartSeries;
    IsDssGraph            : Boolean;
    ShowTabDataSource     : Boolean;
    ShowTabGeneral        : Boolean;
    ShowTabMarks          : Boolean;
    DataSourceStyle       : TBaseSourceEditor;
    TheListBox            : TChartListBox;

    procedure DestroySeriesForms;
    Procedure FillAxes;

    class function InsertSeriesForm( AParent:TControl;
                                     EditorClass:TFormClass;
                                     Position:Integer;
                                     Const EditorTabName:String;
                                     AnObject:TPersistent):TCustomForm;

    class procedure FillMarksStyle(const AItems:TStrings);
    class Function MarkSymbolsForm(AOwner: TComponent;
                              Symbol:TSeriesMarksSymbol;
                              AParent:TWinControl=nil):TFormTeeShape;
    Procedure SetCBSeries;

    property OnTeeEvent:TNotifyTeeEvent read FOnTeeEvent write FOnTeeEvent;
  end;

// These internal global variables are used by TeeChartOffice to
// detect and setup the "New", "Edit" and "Delete" datasource toolbar buttons
var
  InternalOnCreateEditSeries:TOnCreateEditSeries=nil;
  InternalOnCreateEditSeriesObj:TOnCreateEditSeriesObj=nil;

Function SeriesEditorForm(Series:TChartSeries):TFormClass;

// Modally shows the Series editor dialog for ASeries
procedure EditSeriesDialog(AOwner:TComponent; ASeries:TChartSeries);

implementation

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

Uses TeeConst, TeeGally, TeeBrushDlg, TeeFuncEdit, TeePoEdi, TeeFormatting,
     TeeVisualsEditor, TeeMouseCursor;

procedure EditSeriesDialog(AOwner:TComponent; ASeries:TChartSeries);
var tmp : TFormTeeSeries;
begin
  tmp := TeeCreateForm(TFormTeeSeries,AOwner) as TFormTeeSeries;
  with tmp do
  try
    TeeTranslateControl(tmp);

    BorderIcons:=[biSystemMenu];
    BorderStyle:=bsSizeable;

    {$IFNDEF LCL}
    Scaled:=False;
    {$ENDIF}
    Caption:=Format(TeeMsg_Editing,[ASeries.Name]);
    Tag:=ObjectToTag(ASeries);

    PanelTop.Hide;

    ShowTabDataSource:=False;
    TheSeries:=ASeries;
    CBSeries.AddItem(ASeries.Name,TheSeries);
    CBSeries.ItemIndex:=0;
    CBSeriesChange(CBSeries);

    ShowModal;
  finally
    Free;
  end;
end;

{ TFormTeeSeries}
procedure TFormTeeSeries.EPercentFormatChange(Sender: TObject);
begin
  TheSeries.PercentFormat:=LocalToDelphiFormat(EPercentFormat.Text);
end;

Procedure TFormTeeSeries.SetCBSeries;
begin
  if Assigned(TheSeries) then
  begin
    CBSeries.ItemIndex:=CBSeries.Items.IndexOfObject(TheSeries);
    CBSeriesChange(Self);
  end
  else
    PageSeries.Visible:=False;
end;

procedure TFormTeeSeries.EnableMultiLine;
begin
  CBMultiLine.Enabled:=TheSeries.Marks.Style in
    [smsLabelPercent,smsLabelValue,smsPercentTotal,smsLabelPercentTotal,smsXY];
end;

procedure TFormTeeSeries.FillAxis(Items:TStrings; Horizontal:Boolean);
var t : Integer;
begin
  With Items do While Count>3 do Delete(Count-1);

  With TheSeries.ParentChart do
  begin
    for t:=TeeInitialCustomAxis to Axes.Count-1 do
    if (Axes[t].Horizontal and Horizontal) or
       ((not Axes[t].Horizontal) and (not Horizontal)) then
         Items.AddObject(TeeMsg_CustomAxesEditor+' '+IntToStr(t-TeeInitialCustomAxis),Axes[t]);
  end;
end;

Function TFormTeeSeries.AllSeriesMarksVisible:Boolean;
var t : Integer;
begin
  result:=True;
  With TheSeries.ParentChart do
  for t:=0 to SeriesCount-1 do
  if not Series[t].Marks.Visible then
  begin
    result:=False;
    exit;
  end;
end;

class Function TFormTeeSeries.MarkSymbolsForm(AOwner: TComponent;
              Symbol:TSeriesMarksSymbol; AParent:TWinControl=nil):TFormTeeShape;
begin
  // Speed optimization, pass "nil" as owner.
  result:=TFormTeeShape.CreateForm(nil {AOwner},Symbol,AParent);

  with result do
  begin
    BBackColor.Hide;
    PC1.HandleNeeded;
    TabText.TabVisible:=False;
  end;
end;

procedure TFormTeeSeries.EnableTailAlign;
begin
  EnableControls(not CBAlign.Checked,[LHorizAlign,LVertAlign,CBTailEdge,CBTailAlign]);
end;

procedure TFormTeeSeries.SetTailProperties(const ATail:TMarksTail);
begin
  CBTailVisible.Checked:=ATail.Visible;
  if (TheSeries is TPieSeries) and (TheSeries.Marks.Tail.CustomPoint) then
  Begin
    TheSeries.Marks.Tail.CustomPoint := TheSeries.Marks.Tail.AutoAlign;
    UDTailHeight.Position:=TheSeries.Marks.Callout.Length;
  end
  else
    UDTailHeight.Position:=ATail.Height;
  UDTailWidth.Position:=ATail.Width;
  UDTailMargin.Position:=ATail.Margin;

  CBAlign.Checked:=ATail.AutoAlign;
  CBTailEdge.ItemIndex:=Ord(ATail.Edge);
  CBTailAlign.ItemIndex:=Ord(ATail.Align);
end;

procedure TFormTeeSeries.SetTabSeriesMarks;
begin
  if Assigned(IMarksObject) and (IMarksObject is TFormTeeShape) then
     TFormTeeShape(IMarksObject).RefreshControls(TheSeries.Marks);

  With TheSeries.Marks do
  begin
    RGMarkStyle.ItemIndex  :=Ord(Style);
    UDArrowsLength.Position:=Callout.Length;
    UDArrowDist.Position   :=Callout.Distance;

    TBAngle.Position       :=Angle;
    LAngle.Caption         :=IntToStr(Angle);

    CBMarkClip.Checked     :=Clip;
    CBOnTop.Checked        :=OnTop;
    CBSoftClip.Checked     :=SoftClip;
    CBTransparent.Checked  :=Transparent;
    CBAutoPos.Checked      :=AutoPosition;
    UDEvery.Position       :=DrawEvery;
    CBMultiLine.Checked    :=MultiLine;
    CBMarksVisible.Checked :=Visible;
    CBHead.ItemIndex       :=Ord(Callout.ArrowHead);
    UDHeadSize.Position    :=Callout.ArrowHeadSize;

    CBSeriesTransp.Checked :=UseSeriesTransparency;

    //CBTextAlign.ItemIndex  :=Ord(TextAlign);

    CBFontSeriesColor.Checked := FontSeriesColor;
  end;

  SetTailProperties(TheSeries.Marks.Tail);

  EnableTailAlign;

  CBAllVisible.Checked:=AllSeriesMarksVisible;
  EnableMultiLine;

  if Assigned(IMarksSymbol) then
     IMarksSymbol.RefreshControls(TheSeries.Marks.Symbol);

  if Assigned(IMarksMargins) then
     IMarksMargins.RefreshControls(TheSeries.Marks.Margins);
end;

type
  TCustomChartAccess=class(TCustomChart);

procedure TFormTeeSeries.PageSeriesChange(Sender: TObject);

  procedure SetTabSeriesGeneral;

    procedure AddSortByItems;
    var t : Integer;
    begin
      while CBSortBy.Items.Count>2 do
            CBSortBy.Items.Delete(2);

      CBSortBy.ItemIndex:=0;

      with TheSeries.ValuesList do
      for t:=0 to Count-1 do
      if ValueList[t].Name<>'' then
      begin
        CBSortBy.Items.AddObject(ValueList[t].Name,ValueList[t]);

        if ValueList[t].Order<>loNone then
        begin
          CBSortBy.ItemIndex:=CBSortBy.Items.Count-1;

          if ValueList[t].Order=loAscending then
             CBSortOrder.ItemIndex:=0
          else
             CBSortOrder.ItemIndex:=1;
        end;
      end;

      CBSortOrder.Enabled:=CBSortBy.ItemIndex<>0;
    end;

  var tmpSt     : String;
      tmpCursor : TCursor;
      tmpList   : TChartValueList;
  begin
    if Assigned(TheSeries) then
    With TheSeries do
    begin
      CBShowInLegend.Checked   :=Legend.Visible;
      ELegendText.Text         :=Legend.Text;

      CBDepth.Checked          :=Depth=-1;
      if Depth=-1 then UDDepth.Position:=0
                  else UDDepth.Position:=Depth;

      TFormatEditor.AddDefaultFormats(CBFormat.Items);

      tmpSt:=DelphiToLocalFormat(ValueFormat);
      With CBFormat.Items do if IndexOf(tmpSt)=-1 then Add(tmpSt);
      CBFormat.Text:=tmpSt;

      EPercentFormat.Text:=DelphiToLocalFormat(PercentFormat);

      FillAxes;

      With CBHorizAxis do
      Case TheSeries.HorizAxis of
        aTopAxis:       ItemIndex:=0;
        aBottomAxis:    ItemIndex:=1;
        aBothHorizAxis: ItemIndex:=2;
      else
        ItemIndex:=Items.IndexOfObject(TheSeries.CustomHorizAxis);
      end;

      With CBVertAxis do
      Case TheSeries.VertAxis of
        aLeftAxis:     ItemIndex:=0;
        aRightAxis:    ItemIndex:=1;
        aBothVertAxis: ItemIndex:=2;
      else
        ItemIndex:=Items.IndexOfObject(TheSeries.CustomVertAxis);
      end;

      CBXDateTime.Checked:=XValues.DateTime;
      CBYDateTime.Checked:=YValues.DateTime;

      tmpList:=FindZList;
      CBZDateTime.Visible:=Assigned(tmpList);
      if CBZDateTime.Visible then
         CBZDateTime.Checked:=tmpList.DateTime;

      AddSortByItems;

      CBCaseSensitive.Checked:=Labels.CaseSensitive;
      CBCaseSensitive.Enabled:=false;

      ShowControls(ValuesList.Count<=2,[LDepth,EDepth,UDDepth,CBDepth]);

      if Assigned(ILegend) then
         ILegend.RefreshControls(Legend.Picture);
         
      tmpCursor:=Cursor;
    end
    else tmpCursor:=crDefault;

    TeeFillCursors(CBCursor,tmpCursor);

    BVisual.Visible:=Assigned(TheSeries) and Assigned(TeeOnChangeVisual) and
                     (TCustomChartAccess(TheSeries.ParentChart).Form3DClass<>nil);
  end;

begin
  With PageSeries do
  if ActivePage=TabGeneral then SetTabSeriesGeneral else
  if ActivePage=TabMarks then SetTabSeriesMarks     else
  if ActivePage=TabDataSource then SetTabDataSource;

  ChangingPage:=False;
end;

Procedure TFormTeeSeries.FillAxes;
begin
  FillAxis(CBHorizAxis.Items,True);
  FillAxis(CBVertAxis.Items,False);
end;

type
   TChartSeriesAccess=class(TChartSeries);

procedure TFormTeeSeries.SetTabDataSource;
var tmp : Integer;
    t   : Integer;
    tmpSource : TTeeSeriesSourceClass;
begin
  tmp:=CBDataSourceStyle.ItemIndex;

  if Assigned(TheSeries.FunctionType) then
     CBDataSourceStyle.ItemIndex:=3
  else
  if not Assigned(TheSeries.DataSource) then
  begin
    if (TheSeries.Count>0) and (not TChartSeriesAccess(TheSeries).ManualData) then
       CBDataSourceStyle.ItemIndex:=1
    else
       CBDataSourceStyle.ItemIndex:=0;
  end
  else
  if TheSeries.DataSource is TChartSeries then
     CBDataSourceStyle.ItemIndex:=2
  else
  begin
    tmpSource:=nil;
    for t:=0 to TeeSources.Count-1 do
    if TTeeSeriesSourceClass(TeeSources[t]).HasSeries(TheSeries) then
    begin
      tmpSource:=TTeeSeriesSourceClass(TeeSources[t]);
      break;
    end;

    With CBDataSourceStyle do
    if Assigned(tmpSource) then
       ItemIndex:=Items.IndexOfObject(TObject(tmpSource))
    else
       ItemIndex:=0;
  end;

  if CBDataSourceStyle.ItemIndex<>tmp then
     CreateDataSourceForm;
end;

Function TFormTeeSeries.AddToTab(AForm:TForm; ATab:TTabSheet; AObject:TPersistent):TForm;
begin
  result:=AForm;
  result.Align:=alClient;
  TeeTranslateControl(result);
  AddFormTo(result,ATab,AObject);
end;

class function TFormTeeSeries.InsertSeriesForm(AParent:TControl;
                                               EditorClass:TFormClass;
                                               Position:Integer;
                                               Const EditorTabName:String;
                                               AnObject:TPersistent):TCustomForm;
var tmpPage  : TTabSheet;
begin
  if Assigned(AParent) and Assigned(AParent.Owner) and
     (AParent.Owner is TFormTeeSeries) then
  begin
    tmpPage:=TTabSheet.Create(AParent.Owner);

    With tmpPage do
    begin
      PageControl:=TFormTeeSeries(AParent.Owner).PageSeries;
      PageIndex:=Position;
      Caption:=EditorTabName;
    end;

    result:=TFormTeeSeries(AParent.Owner).AddToTab(EditorClass.Create(AParent.Owner),tmpPage,AnObject);
  end
  else
  begin
    result:=EditorClass.Create(AParent);
    result.Caption:=EditorTabName;
    result.Tag:=ObjectToTag(AnObject);
  end;
end;

type
  TTeePanelAccess=class(TCustomTeePanel);

procedure TFormTeeSeries.DestroySeriesForms;
var t       : Integer;
    tmpPage : TTabSheet;
begin
  RemoveControls(TheTabSheet);

  t:=0;

  while t<PageSeries.PageCount do
  begin
    tmpPage:=PageSeries.Pages[t];

    if (tmpPage<>TheTabSheet) and (tmpPage<>TabGeneral) and
       (tmpPage<>TabMarks) and (tmpPage<>TabDataSource) then
    begin
      RemoveControls(tmpPage);

      if (tmpPage.PageIndex>0) and
         (not (csDestroying in tmpPage.PageControl.ComponentState)) and
         (not (csDestroying in tmpPage.ComponentState)) then
              tmpPage.Free
      else
         Inc(t);
    end
    else Inc(t);
  end;

  DestroyDataSourceForm;
end;

Function SeriesEditorForm(Series:TChartSeries):TFormClass;
begin
  result:=TFormClass(TeeGetClass(Series.EditorClass));
end;

procedure TFormTeeSeries.CBSeriesChange(Sender: TObject);

  Procedure CreateTheSeriesForm;
  var tmpClass : TFormClass;
  begin
    tmpClass:=SeriesEditorForm(TheSeries);

    if Assigned(tmpClass) then
       AddToTab(tmpClass.Create(Self),TheTabSheet,TheSeries)
    else
    begin
      DestroySeriesForms;
      TheTabSheet.TabVisible:=False;
    end;
  end;

  Procedure HideSeriesPage;
  begin
    ImageSeries.Visible:=False;
    LabelSeriesClass.Caption:='';
    PageSeries.Visible:=False;
  end;

  Function FindTab(Const ATab:String):TTabSheet;
  var t : Integer;
  begin
    with PageSeries do
    begin
      result:=nil;
      for t:=0 to PageCount-1 do
      if Pages[t].Caption=ATab then
      begin
        result:=Pages[t];
        break;
      end;
    end;
  end;

  Procedure AddTeeSources;
  var t: Integer;
      tmpSource : TTeeSeriesSourceClass;
  begin
    { remove source styles from combobox }
    with CBDataSourceStyle.Items do
         while Count>4 do Delete(Count-1);

    { add sources that are available for this chart type }
    for t:=0 to TeeSources.Count-1 do
    begin
      tmpSource:=TTeeSeriesSourceClass(TeeSources[t]);

      if CBDataSourceStyle.Items.IndexOfObject(TObject(tmpSource))=-1 then
         if tmpSource.Available(TheSeries.ParentChart) then
            CBDataSourceStyle.Items.AddObject(tmpSource.Description,TObject(tmpSource));
    end;
  end;

  procedure ChangeSeriesForms(OldTab:String);
  const
    MenuShortCut='&';  // Do not localize

  var tmpBitmap : TBitmap;
      tmpString : string;
      Index: Integer;
  begin
    TheChart:=TheSeries.ParentChart;

    if Assigned(TheChart) then
       TTeePanelAccess(TheChart).AddListener(Self);

    AddTeeSources;

    tmpBitmap:=TBitmap.Create;
    try
      TeeGetBitmapEditor(TheSeries,tmpBitmap);
      ImageSeries.Picture.Assign(tmpBitmap);
    finally
      tmpBitmap.Free;
    end;

    PaintBox1.Visible:=TChartSeriesAccess(TheSeries).IUseSeriesColor;

    tmpString := GetGallerySeriesName(TheSeries);

    // Example: Replace "Point & Figure" with --> "Point && Figure"

    Index := Pos(MenuShortCut, tmpString);

    if Index > 0 then
       Insert(MenuShortCut, tmpString, Index + 1);

    LabelSeriesClass.Caption:=tmpString+': '+SeriesTitleOrName(TheSeries,True); // Do not localize

    ImageSeries.Visible:=True;
    PageSeries.Visible:=True;
    TabGeneral.TabVisible:=ShowTabGeneral;
    TabMarks.TabVisible:=ShowTabMarks;
    TabDataSource.TabVisible:=ShowTabDataSource and
                              ( (not (tssIsTemplate in TheSeries.Style)) and
                                (not (tssHideDataSource in TheSeries.Style)) );

    if (OldTab='') or
       ((OldTab=TabDataSource.Caption) and (not TabDataSource.TabVisible)) then
         OldTab:=TheTabSheet.Caption;

    ShowControls(TheSeries.UseAxis,[ GBHorizAxis,GBVertAxis ]);
    CBPersistent.Visible:=IsDssGraph and (not (tssIsTemplate in TheSeries.Style));
    if CBPersistent.Visible then
       CBPersistent.Checked:=(tssIsPersistent in TheSeries.Style);

    DestroySeriesForms;
    CreateTheSeriesForm;

    PageSeries.ActivePage:=FindTab(OldTab);
    if (OldTab='') or (PageSeries.ActivePage=nil) then
       PageSeries.ActivePage:=TheTabSheet;

    if not PageSeries.ActivePage.TabVisible then
       PageSeries.ActivePage:=TabGeneral;

    CBDataSourceStyle.ItemIndex:=-1;
    PageSeriesChange(Self);

    PaintBox1.Repaint;
  end;

var OldTab : String;
begin
  CreatingForm:=True;

  if Assigned(PageSeries.ActivePage) then OldTab:=PageSeries.ActivePage.Caption
                                     else OldTab:='';

  With CBSeries do
  if ItemIndex<>-1 then
  begin
    TheSeries:=TChartSeries(SelectedObject);

    if Assigned(TheSeries) then
    begin
      if Assigned(TheListBox) then
      begin
        TheListBox.ClearSelection;
        TheListBox.SelectedSeries:=TheSeries;
      end;

      if (TheSeries<>LastSeries) or (TheTabSheet.ControlCount=0) then
      begin
        ChangeSeriesForms(OldTab);
        LastSeries:=TheSeries;
      end;
    end
    else HideSeriesPage;
  end
  else HideSeriesPage;

  CreatingForm:=False;
end;

type
  TElementAccess=class(TCustomChartElement);
  
procedure TFormTeeSeries.FormCreate(Sender: TObject);

  procedure HideMarksGallerySeries;
  var t : Integer;
  begin
    for t:=0 to ChartMarks.SeriesCount-1 do
        TElementAccess(ChartMarks[t]).IInternalUse:=True;
  end;

begin
  ChangingPage:=False;
  CreatingForm:=True;

  {$IFDEF D7}
  PageArrows.DoubleBuffered:=True;
  PageSeries.DoubleBuffered:=True;
  PageControlMarks.DoubleBuffered:=True;
  {$ENDIF}

  ShowTabDataSource:=True;
  ShowTabGeneral:=True;
  ShowTabMarks:=True;
  IsDssGraph:=False;

  HideMarksGallerySeries;

  CBDataSourceStyle.DropDownCount:=12;
  CBDataSourceStyle.Items.Objects[3]:=TObject(TTeeFuncEditor);
  PageSeries.ActivePage:=TheTabSheet;
  PageControlMarks.ActivePage:=TabSheet1;

  PageControl1.ActivePage:=TabOptions;
end;

procedure TFormTeeSeries.RGMarkStyleClick(Sender: TObject);
var tmp : TSeriesMarksStyle;
begin
  if CanModifySeries then
  begin
    tmp:=TSeriesMarksStyle(RGMarkStyle.ItemIndex);

    if LBChildren.ItemIndex=0 then
       TheSeries.Marks.Style:=tmp
    else
       TSeriesMarkShape(TheSeries.Marks.Children[LBChildren.ItemIndex-1].Shape).Style:=tmp;

    EnableMultiLine;
  end;
end;

procedure TFormTeeSeries.CBPersistentClick(Sender: TObject);
begin
  With TheSeries do
  if CBPersistent.Checked then Style:=Style+[tssIsPersistent]
                          else Style:=Style-[tssIsPersistent];
end;

procedure TFormTeeSeries.CBYDateTimeClick(Sender: TObject);
begin
  if Assigned(TheSeries) then
     TheSeries.YValues.DateTime:=CBYDateTime.Checked;
end;

procedure TFormTeeSeries.CBXDateTimeClick(Sender: TObject);
begin
  if Assigned(TheSeries) then
     TheSeries.XValues.DateTime:=CBXDateTime.Checked;
end;

procedure TFormTeeSeries.CBDataSourcestyleChange(Sender: TObject);

  Procedure CheckOldSource;
  var tmpSource : TTeeSeriesSource;
  begin
    { if the datasource is an internal "Series Source",
      remove and free it ! }
    if Assigned(TheSeries.DataSource) and
       (TheSeries.DataSource is TTeeSeriesSource) and
       (TheSeries.DataSource.Owner=TheSeries) then
    begin
      tmpSource:=TTeeSeriesSource(TheSeries.DataSource);
      tmpSource.Series:=nil;
      tmpSource.Free;

      // Dont remove data. Leave current values.
      // TheSeries.Clear;
    end;

    // B945
    TheSeries.DataSource:=nil;

    TheSeries.SetFunction(nil);
  end;

begin
  if Assigned(DataSourceStyle) then
     DataSourceStyle.BApply.Enabled:=False;

  { change datasource form }
  Case CBDataSourceStyle.ItemIndex of
     0: begin  // Manual data. No source.

          // Set to True *before* clearing datasource,
          // to preserve old current existing values.
          TChartSeriesAccess(TheSeries).ManualData:=True;

          CheckOldSource;
        end;

     1: CheckOldSource; // Random values.
  end;

  CreateDataSourceForm;
end;

procedure TFormTeeSeries.DestroyDataSourceForm;
begin
  if Assigned(DataSourceStyle) and DataSourceStyle.CloseQuery then
     FreeAndNil(DataSourceStyle);
end;

procedure TFormTeeSeries.CreateDataSourceForm;

  Procedure EnableButton(const AButton:TButton);
  begin
    AButton.Visible:=Assigned(AButton.OnClick);
  end;

var tmpForm   : TCustomForm;
    tmpSource : TTeeSeriesSourceClass;
    tmpNum    : Integer;
    tmpFormClass : TCustomFormClass;
begin
  DestroyDataSourceForm;

  if not Assigned(DataSourceStyle) then
  begin
    NewDataButton.Visible:=False;
    EditDataButton.Visible:=False;
    DeleteDataButton.Visible:=False;

    ChartGrid1.Visible:=False;
    ChartGridNavigator1.Visible:=False;

    PanelRandomSource.Visible:=False;
    PanelSeriesSource.Visible:=False;

    PanelDetail.Visible:=False;
    CBAggregate.Visible:=False;

    case CBDataSourceStyle.ItemIndex of
      0: begin
           ChartGrid1.Chart:=TCustomChart(TheSeries.ParentChart);
           ChartGrid1.Series:=TheSeries;
           ChartGrid1.Visible:=True;
           ChartGridNavigator1.Visible:=True;

           PanelDetail.Visible:=TheSeries.Detail.Count>0;
           CBAggregate.Visible:=PanelDetail.Visible;

           ChartGrid1.ReadOnly:=PanelDetail.Visible;

           if PanelDetail.Visible then
           begin
             CBAggregate.ItemIndex:=Ord(TheSeries.Detail.Aggregate);

             LabelDetail.Caption:=CBAggregate.Items[CBAggregate.ItemIndex];

             //DetailGrid.AllowAppend:=False;
             DetailGrid.AllowInsertSeries:=False;

             ChartGrid1Click(Self);
           end;
         end;

      1: begin
           PanelRandomSource.Visible:=True;
           tmpNum:=TChartSeriesAccess(TheSeries).INumSampleValues;

           CheckCBSamples;

           if tmpNum=0 then
              tmpNum:=TheSeries.NumSampleValues;

           ESamples.Text:=IntToStr(tmpNum);

           PanelRandomSource.BringToFront;
         end;

      2: begin
           PanelSeriesSource.Align:=alClient;
           PanelSeriesSource.Visible:=True;

           CBSeriesSource.Clear;

           FillSeriesSources(nil,CBSeriesSource.Items,TheSeries,False);

           CBSeriesSource.ItemIndex:=CBSeriesSource.Items.IndexOfObject(TheSeries.DataSource);

           PanelSeriesSource.BringToFront;

           BClearSource.Enabled:=CBSeriesSource.ItemIndex<>-1;

           BApplySource.Enabled:=False;
         end;
    else
    begin
      With CBDataSourceStyle do
      if ItemIndex=3 then
         tmpForm:=TFormClass(SelectedObject).Create(Self)
      else
      begin
        tmpSource:=TTeeSeriesSourceClass(SelectedObject);

        if tmpSource.HasNew then
        begin
          EnableButton(NewDataButton);
          EnableButton(EditDataButton);
          EnableButton(DeleteDataButton);
        end;

        tmpFormClass:=TFormClass(tmpSource.Editor);

        if Assigned(tmpFormClass) then
           tmpForm:=tmpFormClass.Create(Self)
        else
           tmpForm:=nil;
      end;

      DataSourceStyle:=TBaseSourceEditor(tmpForm);

      if Assigned(DataSourceStyle) then
      begin
        DataSourceStyle.Align:=alClient;
        AddFormTo(DataSourceStyle,Panel2,TheSeries);

        DataSourceStyle.Translate;

        // Hack.
        Timer1.Enabled:=True;
      end;
    end;
    end;
  end;
end;

procedure TFormTeeSeries.CBCursorChange(Sender: TObject);
begin
  with TheSeries do
       Cursor:=TeeSetCursor(Cursor,CBCursor.CurrentItem);
end;

procedure TFormTeeSeries.SEArrowLengthChange(Sender: TObject);
begin
  if CanModifySeries then
     TheSeries.Marks.Callout.Length:=UDArrowsLength.Position;
end;

procedure TFormTeeSeries.CBMarkClipClick(Sender: TObject);
begin
  TheSeries.Marks.Clip:=CBMarkClip.Checked;
end;

procedure TFormTeeSeries.CBMarksVisibleClick(Sender: TObject);
var Old : Boolean;
begin
  TheSeries.Marks.Visible:=CBMarksVisible.Checked;
  Old:=ChangingPage;
  ChangingPage:=True;
  CBAllVisible.Checked:=AllSeriesMarksVisible;
  ChangingPage:=Old;
end;

procedure TFormTeeSeries.FormDestroy(Sender: TObject);
begin
  DestroySeriesForms;

  if Assigned(TheChart) then
     TTeePanelAccess(TheChart).RemoveListener(Self);
end;

procedure TFormTeeSeries.FormShow(Sender: TObject);
begin
  CreatingForm:=False;

  // These internal global variables are used by TeeChartOffice to
  // detect and setup the "New", "Edit" and "Delete" datasource toolbar buttons

  if Assigned(InternalOnCreateEditSeries) and Assigned(TheSeries) then
     InternalOnCreateEditSeries(Self,TCustomChart(TheSeries.ParentChart));

  if Assigned(InternalOnCreateEditSeriesObj) and Assigned(TheSeries) then
     InternalOnCreateEditSeriesObj(Self,TCustomChart(TheSeries.ParentChart));

  if Assigned(TheSeries) then
  begin
    CBShowInEditor.Visible:=csDesigning in TheSeries.ComponentState;
    CBShowInEditor.Checked:=TheSeries.ShowInEditor;
  end;
end;

procedure TFormTeeSeries.CBHorizAxisChange(Sender: TObject);
begin
  With CBHorizAxis do
  if ItemIndex<3 then
     TheSeries.HorizAxis:=THorizAxis(ItemIndex)
  else
  begin
    TheSeries.HorizAxis:=aCustomHorizAxis;
    TheSeries.CustomHorizAxis:=TChartAxis(SelectedObject);
  end;
end;

procedure TFormTeeSeries.CBVertAxisChange(Sender: TObject);
begin
  With CBVertAxis do
  if ItemIndex<3 then
     TheSeries.VertAxis:=TVertAxis(ItemIndex)
  else
  begin
    TheSeries.VertAxis:=aCustomVertAxis;
    TheSeries.CustomVertAxis:=TChartAxis(SelectedObject);
  end;
end;

procedure TFormTeeSeries.EMarksEveryChange(Sender: TObject);
begin
  if CanModifySeries then
     TheSeries.Marks.DrawEvery:=UDEvery.Position;
end;

procedure TFormTeeSeries.CBMultiLineClick(Sender: TObject);
begin
  TheSeries.Marks.MultiLine:=CBMultiLine.Checked;
end;

procedure TFormTeeSeries.CBSortOrderChange(Sender: TObject);
var t : Integer;
    tmpSortedList : TChartValueList;
begin // Change sorting order...

  if CanModifySeries then
  begin
    tmpSortedList:=TChartValueList(CBSortBy.Items.Objects[CBSortBy.ItemIndex]);

    for t:=0 to TheSeries.ValuesList.Count-1 do
      if (CBSortBy.ItemIndex<2) or (TheSeries.ValuesList[t]<>tmpSortedList) then
         TheSeries.ValuesList[t].Order:=loNone
      else
      if CBSortOrder.ItemIndex=0 then
         TheSeries.ValuesList[t].Order:=loAscending
      else
         TheSeries.ValuesList[t].Order:=loDescending;

    CBSortOrder.Enabled:=CBSortBy.ItemIndex<>0;
    CBCaseSensitive.Enabled:=CBSortBy.ItemIndex=1;

    if CBSortBy.ItemIndex<>0 then
       if CBSortBy.ItemIndex=1 then
       begin
         // Sort points by Series Text
         if CBSortOrder.ItemIndex=0 then
            TheSeries.SortByLabels(loAscending)
         else
            TheSeries.SortByLabels(loDescending)
       end
       else
         TheSeries.CheckOrder;
  end;
end;

procedure TFormTeeSeries.CBFormatChange(Sender: TObject);
begin
  TheSeries.ValueFormat:=LocalToDelphiFormat(CBFormat.Text);
end;

Function TFormTeeSeries.CheckCanClose:Boolean;
begin
  if Assigned(DataSourceStyle) then result:=DataSourceStyle.CloseQuery
                               else result:=True;
end;

procedure TFormTeeSeries.PageSeriesChanging(Sender: TObject;
  var AllowChange: Boolean);
begin
  AllowChange:=CheckCanClose;

  if Sender<>Owner then
     ChangingPage:=AllowChange;
end;

procedure TFormTeeSeries.CBDepthClick(Sender: TObject);
begin
  if CanModifySeries then
     if CBDepth.Checked then TheSeries.Depth:=-1
                        else TheSeries.Depth:=UDDepth.Position;
end;

Function TFormTeeSeries.CanModifySeries:Boolean;
begin
  result:=(not CreatingForm) and (not ChangingPage) and Assigned(TheSeries);
end;

procedure TFormTeeSeries.EDepthChange(Sender: TObject);
begin
  if CanModifySeries and UDDepth.Showing then
  begin
    TheSeries.Depth:=UDDepth.Position;
    CBDepth.Checked:=False;
  end;
end;

procedure TFormTeeSeries.FormCloseQuery(Sender: TObject;
  var CanClose: Boolean);
begin
  CanClose:=CheckCanClose;
end;

procedure TFormTeeSeries.CBAllVisibleClick(Sender: TObject);
var t : Integer;
begin
  if CanModifySeries then
  begin
    With TheSeries.ParentChart do
    for t:=0 to SeriesCount-1 do
      Series[t].Marks.Visible:=CBAllVisible.Checked;
    CBMarksVisible.Checked:=CBAllVisible.Checked;
  end;
end;

procedure TFormTeeSeries.PaintBox1Paint(Sender: TObject);
var R : TRect;
begin
  if Assigned(TheSeries) then
  begin
    with PaintBox1.Canvas do
    begin
      Brush.Style:=bsSolid;
      Brush.Color:=PaintBox1.Color;
      R:=PaintBox1.ClientRect;
      InflateRect(R,0,-4);
      FillRect(R);
    end;

    PaintSeriesLegend(TheSeries,PaintBox1.Canvas,R);
  end;
end;

procedure TFormTeeSeries.PaintBox1Click(Sender: TObject);
var tmp : TColor;
begin
  if Assigned(TheSeries) then
  begin
    tmp:=TheSeries.SeriesColor;
    if EditColorDialog(Self,tmp) then
    begin
      TheSeries.SeriesColor:=tmp;
      PaintBox1.Repaint;
    end;
  end;
end;

procedure TFormTeeSeries.CBSamplesDefaultClick(Sender: TObject);
begin
  if CBSamplesDefault.Checked then
  begin
    ESamples.Text:=IntToStr(TheSeries.NumSampleValues);
    CBSamplesDefault.Enabled:=False;
  end;
end;

procedure TFormTeeSeries.CheckCBSamples;
var tmpNum : Integer;
begin
  tmpNum:=TChartSeriesAccess(TheSeries).INumSampleValues;
  CBSamplesDefault.Checked:=(tmpNum=0) or (tmpNum=TheSeries.NumSampleValues);
  CBSamplesDefault.Enabled:=not CBSamplesDefault.Checked;
end;

procedure TFormTeeSeries.ESamplesChange(Sender: TObject);
var tmpNum : Integer;
begin
  tmpNum:=StrToIntDef(ESamples.Text,0);
  TChartSeriesAccess(TheSeries).INumSampleValues:=tmpNum;
  CheckCBSamples;
  BApplyRandom.Enabled:=True;
end;

procedure TFormTeeSeries.BApplyRandomClick(Sender: TObject);
var tmpNum : Integer;
begin
  TheSeries.DataSource:=nil;
  
  tmpNum:=TChartSeriesAccess(TheSeries).INumSampleValues;
  if tmpNum=0 then TheSeries.FillSampleValues
              else TheSeries.FillSampleValues(tmpNum);
end;

procedure TFormTeeSeries.TeeEvent(Event:TTeeEvent);
begin
  if not (csDestroying in ComponentState) then
  begin
    if Event is TTeeSeriesEvent then
       with TTeeSeriesEvent(Event) do
       if Event=seChangeColor then
          PaintBox1.Invalidate
       else
       if (Event=seRemove) and (Series=TheSeries) then
       begin
         DestroySeriesForms;
         TheSeries:=nil;
         CBSeriesChange(Self);
       end;

    if Assigned(OnTeeEvent) then
       OnTeeEvent(Self,Event);
  end;
end;

procedure TFormTeeSeries.EArrowDistChange(Sender: TObject);
begin
  if CanModifySeries then
     TheSeries.Marks.Callout.Distance:=UDArrowDist.Position;
end;

procedure TFormTeeSeries.CBHeadChange(Sender: TObject);
begin
  if CanModifySeries then
     TheSeries.Marks.Callout.ArrowHead:=TArrowHeadStyle(CBHead.ItemIndex);
end;

procedure TFormTeeSeries.Edit1Change(Sender: TObject);
begin
  if CanModifySeries then
     TheSeries.Marks.Callout.ArrowHeadSize:=UDHeadSize.Position;
end;

procedure TFormTeeSeries.ChartGrid1SetEditText(Sender: TObject; ACol,
  ARow: Integer; const Value: String);
begin
  if ChartGrid1.Series<>nil then
     ChartGrid1.Series.RefreshSeries;
end;

procedure TFormTeeSeries.Timer1Timer(Sender: TObject);
begin
  // VCL bug workaround:
  // Force pagecontrol to re-show again our tab with the correct controls on it.
  // This must be done using a timer to delay until parent form is totally
  // visible. Anybody knows a better solution?
  Timer1.Enabled:=False;

  PageSeries.ActivePage:=nil;
  PageSeries.ActivePage:=TabDataSource;
end;

Function TFormTeeSeries.FindZList:TChartValueList;
begin
  result:=TChartSeriesAccess(TheSeries).ValueListOfAxis(TheSeries.ParentChart.DepthAxis);
  if not Assigned(result) then
     result:=TChartSeriesAccess(TheSeries).ValueListOfAxis(TheSeries.ParentChart.DepthTopAxis);
end;

procedure TFormTeeSeries.CBZDateTimeClick(Sender: TObject);
var tmpList : TChartValueList;
begin
  tmpList:=FindZList;
  if Assigned(tmpList) then
     tmpList.DateTime:=CBZDateTime.Checked
  else
     CBZDateTime.Hide;
end;

procedure TFormTeeSeries.Button1Click(Sender: TObject);
begin
  CBFormat.Text:=TFormatEditor.Change(Self,CBFormat.Text);
  CBFormatChange(Self);
end;

procedure TFormTeeSeries.Button2Click(Sender: TObject);
begin
  EPercentFormat.Text:=TFormatEditor.Change(Self,EPercentFormat.Text);
  EPercentFormatChange(Self);
end;

procedure TFormTeeSeries.Button3Click(Sender: TObject);
begin
  TheSeries.Clear;
  CBDataSourcestyle.ItemIndex:=0;
  CBDataSourcestyleChange(Self);
end;

procedure TFormTeeSeries.CBShowInEditorClick(Sender: TObject);
begin
  TheSeries.ShowInEditor:=CBShowInEditor.Checked;
end;

procedure TFormTeeSeries.CBSeriesSourceChange(Sender: TObject);
begin
  BApplySource.Enabled:=True;
end;

procedure TFormTeeSeries.BApplySourceClick(Sender: TObject);
begin
  TheSeries.DataSource:=TComponent(CBSeriesSource.SelectedObject);
  BApplySource.Enabled:=False;
  BClearSource.Enabled:=CBSeriesSource.ItemIndex<>-1;
end;

procedure TFormTeeSeries.BClearSourceClick(Sender: TObject);
begin
  CBSeriesSource.ItemIndex:=-1;
  BApplySourceClick(Self);
end;

procedure TFormTeeSeries.PageControlMarksChange(Sender: TObject);

  procedure CreateMarksGallery;

    procedure AddNewMark(const AMarks:TSeriesMarks; const ATitle:String);
    var tmp : TGalleryChart;
        tmpList : TChartValueList;
    begin
      tmp:=TGalleryChart.Create(Self);

      tmp.View3D:=False;
      tmp.Axes.Hide;
      tmp.Walls.Hide;

      tmp.AddSeries(TPointSeries).Marks:=AMarks;

      TElementAccess(tmp[0]).IInternalUse:=True;

      tmp[0].Marks.Visible:=True;

      tmpList:=AMarks.ParentSeries.MandatoryValueList;

      if tmpList.Count=0 then
         tmp[0].Add(123,'Text')
      else
         tmp[0].Add(tmpList[0],AMarks.ParentSeries.XLabel[0]);

      tmp[0].Color:=clSilver;
      TPointSeries(tmp[0]).Pointer.Style:=psNothing;

      //tmp[0].Marks.ArrowLength:=0;

      MarksGallery.Charts.Add(tmp);
      tmp.Parent:=MarksGallery;

      tmp.Hint:=ATitle;
      tmp.Title.Caption:=tmp.Hint;
      tmp.ShowHint:=True;

      MarksGallery.FinishAdd(tmp);
    end;

  var t : Integer;
  begin
    MarksGallery.View3D:=False;

    AddNewMark(TheSeries.Marks,TeeMsg_Default);

    for t:=0 to ChartMarks.SeriesCount-1 do
    if ChartMarks[t].Visible then
       AddNewMark(ChartMarks[t].Marks,SeriesTitleOrName(ChartMarks[t]));

    IChangingMarks:=True;
    MarksGallery.SelectedChart:=MarksGallery.Charts[0];
    IChangingMarks:=False;

    MarksGallery.ResizeCharts;
  end;

  procedure TryFillChildren;
  var t : Integer;
  begin
    if LBChildren.Items.Count<=1 then
    begin
      CBLayout.ItemIndex:=Ord(TheSeries.Marks.ChildLayout);

      for t:=0 to TheSeries.Marks.Children.Count-1 do
          AddChildItem(t);

      if LBChildren.Items.Count>0 then
      begin
        LBChildren.ItemIndex:=0;
        LBChildrenClick(Self);
      end;
    end;
  end;

begin
  if PageControlMarks.ActivePage=TabMarksText then
  begin
    TryFillChildren;
    PageMarksItemsChange(Self);
  end
  else
  if PageControlMarks.ActivePage=TabSymbol then
  begin
    if not Assigned(IMarksSymbol) then
    begin
      IMarksSymbol:=MarkSymbolsForm(Self,TheSeries.Marks.Symbol,TabSymbol);
      IMarksSymbol.RefreshControls(TheSeries.Marks.Symbol);
    end;
  end
  else
  if PageControlMarks.ActivePage=TabMargins then
  begin
    if not Assigned(IMarksMargins) then
    begin
      IMarksMargins:=TMarginsEditor.Create(Self);
      AddFormTo(IMarksMargins,TabMargins);

      IMarksMargins.RefreshControls(TheSeries.Marks.Margins);
    end;
  end
  else
  if PageControlMarks.ActivePage=TabMarksGallery then
  begin
    if MarksGallery.Charts.Count=0 then
       CreateMarksGallery
    else
       MarksGallery.Charts[0].Series[0].Marks:=TheSeries.Marks;
  end;
end;

procedure TFormTeeSeries.CBTextAlignChange(Sender: TObject);
var tmp : TAlignment;
begin
  if CanModifySeries then
  begin
    tmp:=TAlignment(CBTextAlign.ItemIndex);

    if LBChildren.ItemIndex=0 then
       TheSeries.Marks.TextAlign:=tmp
    else
       TSeriesMarkShape(TheSeries.Marks.Children[LBChildren.ItemIndex-1].Shape).TextAlignment:=tmp;
  end;
end;

procedure TFormTeeSeries.SpeedButton1Click(Sender: TObject);
begin
  TheSeries.Cursor:=TMouseCursorEdit.Choose(TheSeries,TheSeries.Cursor);
  TMouseCursorEdit.SetComboCursor(CBCursor,TheSeries.Cursor);
end;

procedure TFormTeeSeries.CBFontSeriesColorClick(Sender: TObject);
begin
  TheSeries.Marks.FontSeriesColor:=CBFontSeriesColor.Checked;
end;

procedure TFormTeeSeries.CBSortByChange(Sender: TObject);
begin // Change sorting order...
  CBSortOrderChange(Self);
end;

procedure TFormTeeSeries.BVisualClick(Sender: TObject);
begin
  TVisualsEditor.ModalShow(Self,TheSeries.Visuals);
end;

procedure TFormTeeSeries.CBCaseSensitiveClick(Sender: TObject);
begin
  with TheSeries do
  begin
    Labels.CaseSensitive:=CBCaseSensitive.Checked;

    if CBSortOrder.ItemIndex=0 then
      SortByLabels(loAscending)
    else
      SortByLabels(loDescending);
  end;
end;

class procedure TFormTeeSeries.FillMarksStyle(const AItems: TStrings);
var tmp : TFormTeeSeries;
begin
  tmp:=TFormTeeSeries.Create(nil);
  try
    // Translate form before assigning RGMarkStyle
    TeeTranslateControl(tmp);

    AItems.Assign(tmp.RGMarkStyle.Items);
  finally
    tmp.Free;
  end;
end;

procedure TFormTeeSeries.CBAutoPosClick(Sender: TObject);
begin
  TheSeries.Marks.AutoPosition:=CBAutoPos.Checked;
end;

procedure TFormTeeSeries.MarksGalleryChangeChart(Sender: TObject);
var Old : Boolean;
begin
  if not IChangingMarks then
  begin
    Old:=TheSeries.Marks.Visible;
    TheSeries.Marks:=MarksGallery.SelectedChart[0].Marks;
    TheSeries.Marks.Visible:=Old;

    SetTabSeriesMarks;
  end;
end;

procedure TFormTeeSeries.PageArrowsChange(Sender: TObject);
begin
  if (PageArrows.ActivePage=TabArrowBorder) and (TabArrowBorder.ControlCount=0) then
     TPenDialog.InsertForm(TheSeries.Marks.Callout.Arrow,TabArrowBorder)
  else
  if (PageArrows.ActivePage=TabArrowPointer) and (TabArrowPointer.ControlCount=0) then
     TSeriesPointerEditor.InsertForm(TheSeries.Marks.Callout,TabArrowPointer);
end;

type
  TShapeAccess=class(TTeeCustomShape);

procedure TFormTeeSeries.PageMarksItemsChange(Sender: TObject);
var tmp : TTeeCustomShape;
    tmpClass : TFormClass;
begin
  if PageMarksItems.ActivePage=TabMarksFormat then
  begin
    if not Assigned(IMarksObject) then
    begin
      if LBChildren.ItemIndex=0 then
      begin
        IMarksObject:=TFormTeeShape.CreateForm(Self,TheSeries.Marks,TabMarksFormat);
        TFormTeeShape(IMarksObject).TabChildren.TabVisible:=False;
      end
      else
      begin
        tmp:=TheSeries.Marks.Children[LBChildren.ItemIndex-1].Shape;
        tmpClass:=TFormClass(TeeGetClass(TShapeAccess(tmp).GetEditorClass));

        if not Assigned(tmpClass) then
           tmpClass:=TFormTeeShape;

        IMarksObject:=tmpClass.Create(Self);
        IMarksObject.Align:=alClient;

        if IMarksObject is TTextShapeEditor then
           TTextShapeEditor(IMarksObject).TabText.TabVisible:=False;

        AddFormTo(IMarksObject,TabMarksFormat,tmp);
      end;
    end;
  end;
end;

procedure TFormTeeSeries.AddChildItem(Index:Integer);
begin
  LBChildren.Items.Add(TeeMsg_Item+' '+IntToStr(Index));
end;

procedure TFormTeeSeries.BAddClick(Sender: TObject);
var tmp : Integer;
begin
  TheSeries.Marks.Children.Add;
  tmp:=TheSeries.Marks.Children.Count-1;
  AddChildItem(tmp);

  LBChildren.ItemIndex:=tmp+1;
  LBChildrenClick(Self);
end;

procedure TFormTeeSeries.CBLayoutChange(Sender: TObject);
begin
  TheSeries.Marks.ChildLayout:=TTeeShapeLayout(CBLayout.ItemIndex);
end;

procedure TFormTeeSeries.BDeleteClick(Sender: TObject);
var tmp : Integer;
begin
  tmp:=LBChildren.ItemIndex;

  if TeeYesNoDelete(TeeMsg_Item+' '+IntToStr(tmp)) then
  begin
    LBChildren.Items.Delete(tmp);
    TheSeries.Marks.Children.Delete(tmp-1);

    if tmp>=LBChildren.Items.Count then
       LBChildren.ItemIndex:=LBChildren.Items.Count-1;

    LBChildrenClick(Self);
  end;
end;

procedure TFormTeeSeries.LBChildrenClick(Sender: TObject);
var tmp : TTeeCustomShape;
begin
  FreeAndNil(IMarksObject);

  BDelete.Enabled:=LBChildren.ItemIndex>0;

  CBMarkChildVisible.Enabled:=BDelete.Enabled;

  if BDelete.Enabled then
  begin
    tmp:=TheSeries.Marks.Children[LBChildren.ItemIndex-1].Shape;
    RGMarkStyle.ItemIndex:=Ord(TSeriesMarkShape(tmp).Style);
    CBTextAlign.ItemIndex:=Ord(TSeriesMarkShape(tmp).TextAlignment);

    CBMarkChildVisible.Checked:=tmp.Visible;
  end
  else
  begin
    RGMarkStyle.ItemIndex:=Ord(TheSeries.Marks.Style);
    CBTextAlign.ItemIndex:=Ord(TheSeries.Marks.TextAlignment);
  end;

  PageMarksItemsChange(Self);
end;

procedure TFormTeeSeries.CBMarkChildVisibleClick(Sender: TObject);
begin
  if LBChildren.ItemIndex>0 then
     TheSeries.Marks.Children[LBChildren.ItemIndex-1].Shape.Visible:=CBMarkChildVisible.Checked;
end;

procedure TFormTeeSeries.TBAngleChange(Sender: TObject);
begin
  if CanModifySeries then
     TheSeries.Marks.Angle:=TBAngle.Position;

  LAngle.Caption:=IntToStr(TBAngle.Position);
end;

procedure TFormTeeSeries.CBOnTopClick(Sender: TObject);
begin
  if CanModifySeries then
     TheSeries.Marks.OnTop:=CBOnTop.Checked;
end;

procedure TFormTeeSeries.CBSoftClipClick(Sender: TObject);
begin
  if CanModifySeries then
     TheSeries.Marks.SoftClip:=CBSoftClip.Checked;
end;

procedure TFormTeeSeries.CBSeriesTranspClick(Sender: TObject);
begin
  if CanModifySeries then
     TheSeries.Marks.UseSeriesTransparency:=CBSeriesTransp.Checked;
end;

procedure TFormTeeSeries.CBTransparentClick(Sender: TObject);
begin
  if CanModifySeries then
     TheSeries.Marks.Transparent:=CBTransparent.Checked;
end;

procedure TFormTeeSeries.PageControl1Change(Sender: TObject);
begin
  if (PageControl1.ActivePage=TabLegend) and (not Assigned(ILegend)) then
  begin
    ILegend:=TBackImageEditor.InsertForm(TabLegend,TheSeries.Legend.Picture);
    ILegend.TabBounds.TabVisible:=False;
  end
  else
  if (PageControl1.ActivePage=TabHover) and (not Assigned(IHover)) then
     IHover:=TFormTeeShape.CreateForm(Self,TheSeries.Selected.Hover,TabHover);
end;

procedure TFormTeeSeries.CBShowInLegendClick(Sender: TObject);
begin
  if Showing then
     TheSeries.Legend.Visible:=CBShowInLegend.Checked;
end;

procedure TFormTeeSeries.ELegendTextChange(Sender: TObject);
begin
  if CanModifySeries then
     TheSeries.Legend.Text:=ELegendText.Text;
end;

procedure TFormTeeSeries.ChartGrid1Click(Sender: TObject);
var tmp : Integer;
begin
  if Assigned(ChartGrid1.Series) and
     (ChartGrid1.Series.Detail.Count>0) then
  begin
    tmp:=ChartGrid1.Row-2;

    if (tmp>=0) and (tmp<ChartGrid1.Series.Detail.Count) then
        DetailGrid.Series:=ChartGrid1.Series.Detail[tmp]
    else
        DetailGrid.Series:=nil;

    DetailGridClick(Self);
  end;
end;

procedure TFormTeeSeries.PanTopResize(Sender: TObject);
begin
  if CBAggregate.Visible then
     CBAggregate.Left:=PanTop.Width-CBAggregate.Width-6;
end;

procedure TFormTeeSeries.CBAggregateChange(Sender: TObject);
begin
  TheSeries.Detail.Aggregate:=TDetailAggregate(CBAggregate.ItemIndex);

  LabelDetail.Caption:=CBAggregate.Items[CBAggregate.ItemIndex];
  DetailGridClick(Self);
end;

procedure TFormTeeSeries.DetailGridClick(Sender: TObject);
var tmp : Integer;
    tmpS : String;
begin
  tmp:=ChartGrid1.Row-2;

  if (tmp>=0) and (tmp<ChartGrid1.Series.Count) then
     tmpS:=FormatFloat(ChartGrid1.Series.ValueFormat,ChartGrid1.Series.MandatoryValueList[tmp])
  else
     tmpS:='';

  LabelDetailTotal.Caption:=tmpS;
end;

procedure TFormTeeSeries.DetailGridSetEditText(Sender: TObject; ACol,
  ARow: Integer; const Value: String);
begin
  DetailGridClick(Self);
end;

procedure TFormTeeSeries.CBTailVisibleClick(Sender: TObject);
begin
  TheSeries.Marks.Tail.Visible:=CBTailVisible.Checked;
  TheSeries.Repaint;
end;

procedure TFormTeeSeries.ETailHeightChange(Sender: TObject);
begin
  if not IChangingMarks then
  Begin
     if (TheSeries is TPieSeries) and (TheSeries.Marks.Tail.CustomPoint) then
       TheSeries.Marks.Callout.Length:=UDTailHeight.Position
     else
       TheSeries.Marks.Tail.Height:=UDTailHeight.Position;
  end;
end;

procedure TFormTeeSeries.ETailWidthChange(Sender: TObject);
begin
  if not IChangingMarks then
     TheSeries.Marks.Tail.Width:=UDTailWidth.Position;
end;

procedure TFormTeeSeries.ETailMarginChange(Sender: TObject);
begin
  if not IChangingMarks then
     TheSeries.Marks.Tail.Margin:=UDTailMargin.Position;
  TheSeries.Repaint;
end;

procedure TFormTeeSeries.CBTailEdgeChange(Sender: TObject);
begin
  TheSeries.Marks.Tail.Edge:=TTailEdge(CBTailEdge.ItemIndex);
end;

procedure TFormTeeSeries.CBAlignClick(Sender: TObject);
begin
  TheSeries.Marks.Tail.AutoAlign:=CBAlign.Checked;

  if (TheSeries is TPieSeries) then
    TheSeries.Marks.Tail.CustomPoint := TheSeries.Marks.Tail.AutoAlign;

  EnableTailAlign;
end;

procedure TFormTeeSeries.CBTailAlignChange(Sender: TObject);
begin
  TheSeries.Marks.Tail.Align:=TTailAlign(CBTailAlign.ItemIndex);
end;

end.

