{********************************************}
{ TeeChart Pro                               }
{ Copyright (c) 1995-2020 by Steema Software }
{ All Rights Reserved                        }
{                                            }
{     TChartEditor                           }
{     TChartPreviewer                        }
{     TChartEditorPanel                      }
{********************************************}
unit TeeEdit;
{$I TeeDefs.inc}

interface

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

     {$IFDEF FMX}
     FMX.Types, System.UITypes,
     {$IFDEF D17}
     System.UIConsts,
     {$ENDIF}
     {$ELSE}
     Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls, ComCtrls,
     {$ENDIF}

     {$IFDEF LCL}
     GraphType, // <-- bvLowered
     {$ENDIF}

     {$IFDEF FMX}
     FMXTee.Chart, FMXTee.Editor.Chart, FMXTee.Procs, FMXTee.Engine,
     FMXTee.Print.Preview, FMXTee.Print.PreviewPanel, FMXTee.Canvas,
     FMXTee.Chart.ListBox
     {$ELSE}
     Chart, TeeEditCha, TeeLisB, TeeProcs, TeEngine, TeePrevi, TeePreviewPanel
     {$ENDIF}
     ;

type
  TCustomChartEditor=class(TComponent)
  private
    { Private declarations }
    FChart   : TCustomChart;
    FTitle   : String;
    FOnClose : TNotifyEvent;
    FOnShow  : TNotifyEvent;
  protected
    { Protected declarations }
    procedure Notification( AComponent: TComponent;
                            Operation: TOperation); override;
    procedure SetChart(const Value: TCustomChart); virtual;
  public
    { Public declarations }
    Procedure Execute; virtual; // abstract;

    property Title:String read FTitle write FTitle;
  published
    { Published declarations }
    property Chart:TCustomChart read FChart write SetChart;
    property OnClose: TNotifyEvent read FOnClose write FOnClose;
    property OnShow: TNotifyEvent read FOnShow write FOnShow;
  end;

  {$IFDEF D16}
  [ComponentPlatformsAttribute(pidWin32 or pidWin64 or pidOSX32 {$IFDEF D26}or pidOSX64{$ENDIF})]
  {$ENDIF}
  TChartEditor=class(TCustomChartEditor)
  private
    { Private declarations }
    FAutoRepaint      : Boolean;

    {$IFNDEF FMX}
    FDefaultTab       : TChartEditorTab;
    FHideTabs         : TChartEditorHiddenTabs;
    {$ENDIF}

    FHighLight        : Boolean;

    {$IFNDEF FMX}
    FOnChangeOrder    : TChangeOrderEvent;
    FOptions          : TChartEditorOptions;
    {$ENDIF}

    FPixels           : Integer;
    FRememberPosition : Boolean;
    FSeries           : TChartSeries;
    FTree             : Boolean;

    FGalleryHeight    : Integer;
    FGalleryWidth     : Integer;
    FHeight           : Integer;
    FWidth            : Integer;

    {$IFNDEF FMX}
    procedure ChangeSeriesOrder(Sender:TChartListBox;
                                Series1,Series2:TCustomChartSeries);
    {$ENDIF}
    procedure SetSeries(const Value: TChartSeries);
  protected
    procedure Notification( AComponent: TComponent;
                            Operation: TOperation); override;
    procedure SetChart(const Value: TCustomChart); override;
  public
    { Public declarations }
    Constructor Create(AOwner:TComponent); override;

    Procedure Execute; override;
  published
    { Published declarations }
    property AutoRepaint:Boolean read FAutoRepaint write FAutoRepaint default True;

    {$IFNDEF FMX}
    property DefaultTab:TChartEditorTab read FDefaultTab write FDefaultTab default cetMain;
    property HideTabs:TChartEditorHiddenTabs read FHideTabs write FHideTabs default [];
    {$ENDIF}

    property HighLightTabs:Boolean read FHighLight write FHighLight default False;

    {$IFNDEF FMX}
    property Options:TChartEditorOptions read FOptions write FOptions
                                         default eoAll;
    {$ENDIF}

    property PixelsPerInch:Integer read FPixels write FPixels default 0;
    property RememberPosition:Boolean read FRememberPosition write
                                      FRememberPosition default False;
    property Series:TChartSeries read FSeries write SetSeries;
    property Title;
    property TreeView:Boolean read FTree write FTree default False;

    property GalleryHeight : Integer read FGalleryHeight write FGalleryHeight;
    property GalleryWidth  : Integer read FGalleryWidth write FGalleryWidth;
    property Height        : Integer read FHeight write FHeight;
    property Width         : Integer read FWidth write FWidth;

    { events }
    {$IFNDEF FMX}
    property OnChangeSeriesOrder:TChangeOrderEvent read FOnChangeOrder
                                                   write FOnChangeOrder;
    {$ENDIF}
  end;

  TChartPreviewOption=( cpoChangePrinter,
                        cpoSetupPrinter,
                        cpoResizeChart,
                        cpoMoveChart,
                        cpoChangeDetail,
                        cpoChangePaperOrientation,
                        cpoChangeMargins,
                        cpoProportional,
                        cpoDragChart,
                        cpoPrintPanel,
                        cpoAsBitmap );

  TChartPreviewOptions=set of TChartPreviewOption;

Const DefaultChartPreviewOptions=[ cpoChangePrinter,
                                   cpoSetupPrinter,
                                   cpoResizeChart,
                                   cpoMoveChart,
                                   cpoChangeDetail,
                                   cpoChangePaperOrientation,
                                   cpoChangeMargins,
                                   cpoProportional ];


type
  {$IFDEF D16}
  [ComponentPlatformsAttribute(pidWin32 or pidWin64 or pidOSX32 {$IFDEF D26}or pidOSX64{$ENDIF})]
  {$ENDIF}
  TChartPreviewer=class(TCustomChartEditor)
  private
    FOnAfterDraw: TNotifyEvent;
    FOptions    : TChartPreviewOptions;
    FPaperColor : TColor;
    FWindowState: TWindowState;

    TheForm     : TChartPreview;
    function GetPreview: TTeePreviewPanel;
    { Private declarations }
  protected
    { Protected declarations }
  public
    { Public declarations }
    Constructor Create(AOwner:TComponent); override;
    Procedure Execute; override;
    property PreviewPanel : TTeePreviewPanel read GetPreview;
  published
    { Published declarations }
    property Options:TChartPreviewOptions read FOptions write FOptions
             default DefaultChartPreviewOptions;
    property PaperColor:TColor read FPaperColor write FPaperColor default {$IFDEF FMX}claWhite{$ELSE}clWhite{$ENDIF};
    property Title;
    property WindowState:TWindowState read FWindowState write FWindowState
                                      default {$IFDEF FMX}TWindowState.{$ENDIF}wsNormal;

    property OnAfterDraw:TNotifyEvent read FOnAfterDraw write FOnAfterDraw;
  end;

  {$IFDEF D16}
  [ComponentPlatformsAttribute(pidWin32 or pidWin64 or pidOSX32 {$IFDEF D26}or pidOSX64{$ENDIF})]
  {$ENDIF}
  TChartEditorPanel=class(TCustomPanelNoCaption)
  private
    FChart  : TCustomChart;
    FEditor : TChartEditForm;
    FSeries : TChartSeries;

    {$IFNDEF TEEOCXNOEDITOR}
    FChartEditor : TChartEditor;
    {$ENDIF}

    {$IFNDEF LCL}
    {$IFNDEF FMX}
    procedure CMShowingChanged(var Message: TMessage); message CM_SHOWINGCHANGED;
    {$ENDIF}
    {$ENDIF}

    Procedure SetChart(const Value:TCustomChart);
    Procedure SetSeries(const Value:TChartSeries);

    {$IFNDEF TEEOCXNOEDITOR}
    procedure SetChartEditor(const Value: TChartEditor);
    {$ENDIF}

  protected
    procedure Notification( AComponent: TComponent;
                            Operation: TOperation); override;
  public
    { Public declarations }
    Constructor Create(AOwner:TComponent); override;
    Destructor Destroy; override;

    {$IFNDEF FMX}
    Procedure SelectUnderMouse;
    {$ENDIF}

    property Editor:TChartEditForm read FEditor;
  published
    property Align;
    {$IFNDEF FMX}
    property BevelOuter default bvLowered;
    {$ENDIF}

    property Chart:TCustomChart read FChart write SetChart;

    {$IFNDEF TEEOCXNOEDITOR}
    property ChartEditor:TChartEditor read FChartEditor write SetChartEditor;
    {$ENDIF}

    property Series:TChartSeries read FSeries write SetSeries;

    {$IFNDEF FMX}
    property UseDockManager default True;
    property DockSite;
    property DragCursor;
    {$ENDIF}
    property DragMode;
    property Enabled;

    {$IFDEF FMX}
    {$IFDEF D23}
    property ParentShowHint;
    {$ENDIF}
    {$ELSE}
    property ParentColor;
    property ParentShowHint;
    {$ENDIF}

    property ShowHint;
    property PopupMenu;
    property TabOrder;

    {$IFNDEF FMX}
    property TabStop;
    {$ENDIF}

    property Visible;

    {$IFDEF FMX}
    {$IFDEF D17}
    property Action;
    property Anchors;
    {$ENDIF}
    {$ELSE}
    property Anchors;
    {$ENDIF}
    
    {$IFNDEF FMX}
    property AutoSize;
    property Constraints;
    {$ENDIF}

    {$IFNDEF FMX}
    property DragKind;
    {$ENDIF}
    {$IFNDEF LCL}
    property Locked;
    {$ENDIF}

    { TPanel events }
    property OnClick;

    {$IFNDEF FMX}
    property OnContextPopup;
    {$ENDIF}

    property OnDblClick;
    property OnDragDrop;
    property OnDragOver;
    {$IFNDEF FMX}
    property OnEndDrag;
    {$ENDIF}

    property OnEnter;
    property OnExit;
    property OnKeyDown;
    {$IFNDEF FMX}
    property OnKeyPress;
    {$ENDIF}
    property OnKeyUp;
    property OnMouseDown;

    {$IFDEF D10}
    property OnMouseEnter;
    property OnMouseLeave;
    {$ENDIF}

    property OnMouseMove;
    property OnMouseUp;
    property OnResize;
    property OnMouseWheel;

    {$IFNDEF FMX}
    property OnMouseWheelDown;
    property OnMouseWheelUp;
    property OnStartDrag;
    property OnConstrainedResize;

    {$IFNDEF LCL}
    property OnCanResize;
    {$ENDIF}

    property OnDockDrop;
    property OnDockOver;
    property OnEndDock;
    property OnGetSiteInfo;
    property OnStartDock;
    property OnUnDock;
    {$ENDIF}
  end;

implementation

uses
  {$IFDEF D9}
  Types,
  {$ENDIF}

  {$IFDEF FMX}
  FMXTee.ProConstants, FMXTee.Editor.Axis, FMXTee.Editor.Title,
  FMXTee.Editor.Stroke
  {$ELSE}
  TeeProCo, TeePenDlg, EditChar, TeeEdiAxis, TeeEdiTitl
  {$ENDIF}
  ;

{ TCustomChartEditor }

procedure TCustomChartEditor.Notification(AComponent: TComponent; Operation: TOperation);
begin
  inherited;

  if (Operation=opRemove) and Assigned(FChart) and (AComponent=FChart) then
     Chart:=nil;
end;

Procedure TCustomChartEditor.Execute;
begin
end;

procedure TCustomChartEditor.SetChart(const Value: TCustomChart);
begin
  if FChart<>Value then
  begin
    if Assigned(FChart) then
       FChart.RemoveFreeNotification(Self);

    FChart:=Value;

    if Assigned(FChart) then
       FChart.FreeNotification(Self);
  end;
end;

{ TChartEditor }

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

  {$IFNDEF FMX}
  FHideTabs:=[];
  FOptions:=eoAll;
  FDefaultTab:=cetMain;
  {$ENDIF}

  FAutoRepaint:=True;

  FGalleryHeight:=0;
  FGalleryWidth:=0;
  FHeight:=0;
  FWidth:=0;
end;

{$IFNDEF FMX}
procedure TChartEditor.ChangeSeriesOrder(Sender:TChartListBox;
                                         Series1,Series2:TCustomChartSeries);
begin
  if Assigned(FOnChangeOrder) then
     FOnChangeOrder(Sender,Series1,Series2);
end;
{$ENDIF}

procedure TChartEditor.Execute;
Var TheForm : TChartEditForm;
    OldAuto : Boolean;
begin
  if Assigned(FChart) then
  begin
    TheForm:=TChartEditForm.Create(nil);

    With TheForm do
    try
      {$IFNDEF FMX}
      Tree.Visible:=FTree;
      {$ENDIF}
      
      RememberPosition:=Self.RememberPosition;  // set before setting chart
      Caption:=Self.Title;

      {$IFNDEF FMX}
      EditorOptions:=Self.Options;  // Before setting Chart !
      {$ENDIF}

      Chart:=Self.Chart;

      HighLightTabs:=Self.FHighLight;

      {$IFNDEF FMX}
      TheEditSeries:=Self.Series;

      CheckHelpFile;
      TheActivePageIndex:=Ord(FDefaultTab);
      TheHiddenTabs:=FHideTabs;
      LBSeries.OnChangeOrder:=ChangeSeriesOrder;
      {$ENDIF}

      if Assigned(Self.FOnShow) then
         Self.FOnShow(TheForm);

      OldAuto:=True;
      if not Self.FAutoRepaint then
      begin
        OldAuto:=FChart.AutoRepaint;
        FChart.AutoRepaint:=False;
      end;

      TeeTranslateControl(TheForm);

      if (FPixels<>0) and (FPixels<>PixelsPerInch) then
      begin
        {$IFNDEF FMX}
        {$IFNDEF LCL}
        TheForm.ScaleBy(FPixels,TheForm.PixelsPerInch);
        {$ENDIF}

        TheForm.PixelsPerInch:=FPixels;
        {$ENDIF}
      end;

      if (FHeight>0) and (FWidth>0) then
      begin
        RememberSize:=False;
        Height:=FHeight;
        Width:=FWidth;
      end;

      GalleryHeight:=FGalleryHeight;
      GalleryWidth:=FGalleryWidth;

      ShowModal;

      if not Self.FAutoRepaint then
      begin
        FChart.AutoRepaint:=OldAuto;
        FChart.Repaint;
      end;
    finally
      if Assigned(Self.FOnClose) then
         Self.FOnClose(TheForm);

      Free;
    end;

    FChart.CancelMouse:=True;
  end;
end;

procedure TChartEditor.SetSeries(const Value: TChartSeries);
begin
  if FSeries<>Value then
  begin
    if Assigned(FSeries) then
       FSeries.RemoveFreeNotification(Self);

    FSeries:=Value;

    if Assigned(Series) then
    begin
      FSeries.FreeNotification(Self);

      if Assigned(Chart) and (Series.ParentChart<>Chart) then
         Chart:=TCustomChart(Series.ParentChart);
    end;
  end;
end;

procedure TChartEditor.Notification( AComponent: TComponent;
                                     Operation: TOperation);
begin
  inherited;
  if (Operation=opRemove) and Assigned(FSeries) and (AComponent=FSeries) then
     Series:=nil;
end;

procedure TChartEditor.SetChart(const Value: TCustomChart);
begin
  inherited;

  if Assigned(Chart) and Assigned(Series) and (Series.ParentChart<>Chart) then
     Series:=nil;
end;

{ TChartPreviewer }
Constructor TChartPreviewer.Create(AOwner:TComponent);
begin
  inherited;
  FOptions:=DefaultChartPreviewOptions;
  FPaperColor:={$IFDEF FMX}claWhite{$ELSE}clWhite{$ENDIF};
  FWindowState:={$IFDEF FMX}TWindowState.{$ENDIF}wsNormal;
end;

procedure TChartPreviewer.Execute;
var OldPrintTeePanel : Boolean;
begin
  if Assigned(FChart) then
  begin
    TheForm:=TChartPreview.Create(nil);

    with TheForm do
    try
      if Self.FTitle<>'' then
         Caption:=Self.FTitle;

      TeePreviewPanel1.Panel:=Self.FChart;
      TeePreviewPanel1.OnAfterDraw:=Self.OnAfterDraw;
      WindowState:=Self.FWindowState;

      if not (cpoChangePrinter in Self.FOptions) then
         CBPrinters.Enabled:=False;

      if not (cpoSetupPrinter in Self.FOptions) then
         BSetupPrinter.Enabled:=False;

      TeePreviewPanel1.AllowResize:=(cpoResizeChart in Self.FOptions);
      TeePreviewPanel1.AllowMove:=(cpoMoveChart in Self.FOptions);

      if not (cpoChangeDetail in Self.FOptions) then
         ChangeDetailGroup.Enabled:=False;

      if not (cpoChangePaperOrientation in Self.FOptions) then
         Orientation.Enabled:=False;

      if not (cpoChangeMargins in Self.FOptions) then
      begin
        GBMargins.Enabled:=False;
        BReset.Enabled:=False;
      end;

      With TeePreviewPanel1.Panel do
      if PrintProportional then
         PrintProportional:=(cpoProportional in Self.FOptions);

      TeePreviewPanel1.PaperColor:=Self.FPaperColor;
      TeePreviewPanel1.DragImage:=(cpoDragChart in Self.FOptions);

      OldPrintTeePanel:=PrintTeePanel;
      PrintTeePanel:=(cpoPrintPanel in Self.FOptions);

      TeePreviewPanel1.AsBitmap:=(cpoAsBitmap in Self.FOptions);

      if Assigned(Self.FOnShow) then
         Self.FOnShow(TheForm);

      ShowModal;

      PrintTeePanel:=OldPrintTeePanel;
    finally
      if Assigned(Self.FOnClose) then
         Self.FOnClose(TheForm);

      Free;
      TheForm:=nil;
      Self.FChart.Repaint;
    end;

    Self.FChart.CancelMouse:=True;
  end;
end;

function TChartPreviewer.GetPreview: TTeePreviewPanel;
begin
  if Assigned(TheForm) then
     result:=TheForm.TeePreviewPanel1
  else
     result:=nil;
end;

{ TChartEditorPanel }

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

  {$IFNDEF FMX}
  BevelOuter:=bvLowered;
  {$ENDIF}

  Width :=409;
  Height:=291;

  if not (csDesigning in ComponentState) then
  begin
    FEditor:=TChartEditForm.Create(Self);

    {$IFNDEF FMX}
    FEditor.Align:=alClient;
    {$ENDIF}

    TeeTranslateControl(FEditor);

    FEditor.RememberPosition:=False;
    FEditor.RememberSize:=False;
    FEditor.PanBottom.Visible:=False;

    {$IFDEF FMX}
    EmbeddForm(FEditor,Self);
    {$ELSE}
    AddFormTo(FEditor,Self);
    {$ENDIF}
  end;
end;

Destructor TChartEditorPanel.Destroy;
begin
  Series:=nil;
  Chart:=nil;

  inherited;
end;

procedure TChartEditorPanel.Notification( AComponent: TComponent;
                                          Operation: TOperation);
begin
  inherited;

  if Operation=opRemove then
  begin
    if Assigned(FSeries) and (AComponent=FSeries) then
       Series:=nil;

    if Assigned(FChart) and (AComponent=FChart) then
       Chart:=nil;

    if Assigned(FChartEditor) and (AComponent=FChartEditor) then
       ChartEditor:=nil;
  end;
end;

{$IFNDEF FMX}

type
  TChartEditFormAccess=class(TChartEditForm);

procedure TChartEditorPanel.SelectUnderMouse;
Var P : TChartClickedPart;

  Procedure Select(const ATab:TTabSheet);
  begin
    if ATab.Visible then
    With Editor do
    begin
      MainPage.ActivePage:=TabChart;
      SubPage.ActivePage:=ATab;
      SubPageChange(Self);
    end;
  end;

begin
  if Assigned(Chart) then
  begin
    Chart.CalcClickedPart(Chart.GetCursorPos,P);

    Case P.Part of
      cpLegend: TChartEditFormAccess(Editor).SelectTreeNodeData(Editor.TabLegend);
      cpSeriesMarks,
      cpSeriesPointer,
      cpSeries : TChartEditFormAccess(Editor).SelectTreeNodeData(P.ASeries);
        cpAxis : TChartEditFormAccess(Editor).SelectTreeNodeData(P.AAxis);
       cpTitle : TChartEditFormAccess(Editor).SelectTreeNodeData(Chart.Title);
    cpSubTitle : TChartEditFormAccess(Editor).SelectTreeNodeData(Chart.SubTitle);
        cpFoot : TChartEditFormAccess(Editor).SelectTreeNodeData(Chart.Foot);
     cpSubFoot : TChartEditFormAccess(Editor).SelectTreeNodeData(Chart.SubFoot);
    else
      Select(Editor.TabPanel);
    end;
  end;
end;
{$ENDIF}

{$IFNDEF FMX}
{$IFNDEF LCL}
procedure TChartEditorPanel.CMShowingChanged(var Message: TMessage);
begin
  inherited;

  if Showing and Assigned(FEditor) then
     FEditor.Visible:=True;

  if Assigned(Parent) then
     Parent.UpdateControlState;
end;
{$ENDIF}
{$ENDIF}

Procedure TChartEditorPanel.SetChart(const Value:TCustomChart);
begin
  if FChart<>Value then
  begin
    if Assigned(FChart) then
       FChart.RemoveFreeNotification(Self);

    FChart:=Value;

    if Assigned(FChart) then
       FChart.FreeNotification(Self);

    if Assigned(FEditor) then
       FEditor.Chart:=FChart;
  end;
end;

Procedure TChartEditorPanel.SetSeries(const Value:TChartSeries);
begin
  if FSeries<>Value then
  begin
    if Assigned(FSeries) then
       FSeries.RemoveFreeNotification(Self);

    FSeries:=Value;

    if Assigned(FSeries) then
       FSeries.FreeNotification(Self);

    if Assigned(FEditor) then
    begin
      if Assigned(FSeries) then
         Chart:=TCustomChart(FSeries.ParentChart);

      {$IFNDEF FMX}
      Editor.TheEditSeries:=FSeries;
      TChartEditFormAccess(Editor).SelectTreeNodeData(FSeries);
      {$ENDIF}
    end;
  end;
end;

procedure TChartEditorPanel.SetChartEditor(const Value: TChartEditor);
begin
  if FChartEditor<>Value then
  begin
    if Assigned(FChartEditor) then
       FChartEditor.RemoveFreeNotification(Self);

    FChartEditor:=Value;

    if Assigned(FChartEditor) then
       FChartEditor.FreeNotification(Self);
  end;

  if Assigned(FChartEditor) then
  begin
    with FEditor do
    begin
      {$IFNDEF FMX}
      EditorOptions:=FChartEditor.Options;
      {$ENDIF}

      // Force repaint
      Visible:=False;
      Visible:=True;
    end;
  end;
end;

end.
