{**********************************************}
{  TChartObject (or derived) Editor Dialog     }
{  Copyright (c) 1999-2020 by Steema Software  }
{**********************************************}
unit TeeCustomShapeEditor;
{$I TeeDefs.inc}

interface

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

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

     TeeProcs, TeeEdiGrad, TeeEdiFont, TeCanvas, TeePenDlg, TeeShadowEditor,
     TeeBackImage, TeeBrushDlg;

type
  TFormTeeShape = class(TForm)
    PC1: TPageControl;
    TabFormat: TTabSheet;
    BBackColor: TButtonColor;
    CBTransparent: TCheckBox;
    TabPattern: TTabSheet;
    TabText: TTabSheet;
    TabShadow: TTabSheet;
    Label4: TLabel;
    TabImage: TTabSheet;
    TabBorder: TTabSheet;
    TabEmboss: TTabSheet;
    TBTransp: TTrackBar;
    LTransp: TLabel;
    PageBorder: TPageControl;
    TabSheet2: TTabSheet;
    TabBorderPen: TTabSheet;
    Label3: TLabel;
    EBevWidth: TEdit;
    UDBevW: TUpDown;
    TabSheet3: TTabSheet;
    Label5: TLabel;
    CBSide: TComboFlat;
    Label6: TLabel;
    TBSize: TTrackBar;
    LSize: TLabel;
    Label7: TLabel;
    TBPosition: TTrackBar;
    LPosition: TLabel;
    Label8: TLabel;
    TBWidth: TTrackBar;
    LWidth: TLabel;
    TabSheet4: TTabSheet;
    RGBevel: TRadioGroup;
    Label1: TLabel;
    CBRound: TCheckBox;
    ERoundSize: TEdit;
    UDRoundSize: TUpDown;
    GroupCorners: TGroupBox;
    TabChildren: TTabSheet;
    Panel1: TPanel;
    Panel2: TPanel;
    CBLayout: TComboFlat;
    Splitter1: TSplitter;
    LBChildren: TListBox;
    BAdd: TSpeedButton;
    BDelete: TSpeedButton;
    CBVisible: TCheckBox;
    CBLeftTop: TComboFlat;
    CBLeftBottom: TComboFlat;
    CBRightTop: TComboFlat;
    CBRightBottom: TComboFlat;
    Panel3: TPanel;
    CBDefaultFont: TCheckBox;
    PanelFont: TPanel;
    procedure BColorClick(Sender: TObject);
    procedure CBRoundClick(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure CBTransparentClick(Sender: TObject);
    procedure EBevWidthChange(Sender: TObject);
    procedure CBVisibleChecked(Sender: TObject);
    procedure ERoundSizeChange(Sender: TObject);
    procedure PC1Change(Sender: TObject);
    procedure TBTranspChange(Sender: TObject);
    procedure PageBorderChange(Sender: TObject);
    procedure CBSideChange(Sender: TObject);
    procedure TBSizeChange(Sender: TObject);
    procedure TBPositionChange(Sender: TObject);
    procedure TBWidthChange(Sender: TObject);
    procedure RGBevelClick(Sender: TObject);
    procedure LBChildrenClick(Sender: TObject);
    procedure BAddClick(Sender: TObject);
    procedure BDeleteClick(Sender: TObject);
    procedure CBLayoutChange(Sender: TObject);
    procedure CBVisibleClick(Sender: TObject);
    procedure PC1GetImageIndex(Sender: TObject; TabIndex: Integer;
      var ImageIndex: Integer);
    procedure CBLeftTopChange(Sender: TObject);
    procedure CBLeftBottomChange(Sender: TObject);
    procedure CBRightTopChange(Sender: TObject);
    procedure CBRightBottomChange(Sender: TObject);
    procedure CBDefaultFontClick(Sender: TObject);
  private
    { Private declarations }
    CreatingForm    : Boolean;

    FBorderEditor   : TPenDialog;
    FEmbossEditor   : TTeeShadowEditor;
    FFontEditor     : TTeeFontEditor;
    FBrushEditor    : TBrushDialog;
    FImageEditor    : TBackImageEditor;
    FShadowEditor   : TTeeShadowEditor;

    IChildEditor    : TForm;

    procedure AddChildItem(Index:Integer);
    Procedure EnableBevel;
  public
    { Public declarations }
    TheShape : TTeeCustomShape;

    Constructor Create(AOwner:TComponent); override;

    class Function CreateForm(const AOwner:TComponent;
                              const AShape:TTeeCustomShape;
                              const AParent:TWinControl=nil):TFormTeeShape;

    procedure RefreshControls(const AShape:TTeeCustomShape);

    class procedure InsertTeeForm(const Source,Dest:TPageControl);
  end;

Function InsertTeeObjectForm(const APageControl:TPageControl; const AShape:TTeeCustomShape):TFormTeeShape;

function EditTeeCustomShape(const AOwner:TComponent; const AShape:TTeeCustomShape;
                            HideText:Boolean=False; const ACaption:String=''):Boolean;

implementation

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

Uses
  {$IFDEF LCL}
  GraphType,
  {$ENDIF}
  TeeConst, TeeFiltersEditor;

type
  TWinControlAccess=class(TWinControl);
  
class Function TFormTeeShape.CreateForm( const AOwner:TComponent;
                                         const AShape:TTeeCustomShape;
                                         const AParent:TWinControl=nil):TFormTeeShape;
begin
  result:=TFormTeeShape.Create(AOwner);
  result.TheShape:=AShape;

  if Assigned(AParent) then
  with result do
  begin
    BorderStyle:=TeeFormBorderStyle;
    Parent:=AParent;
    TeeTranslateControl(result);

    Align:=alClient;

    if ParentFont and Assigned(Parent) then
       Font:=TWinControlAccess(Parent).Font;

    Show;
  end;
end;

class procedure TFormTeeShape.InsertTeeForm(const Source,Dest:TPageControl);
var tmp : TTabSheet;
    tmpForm : TForm;
begin
  tmpForm:=Source.Parent as TForm;
  tmpForm.BorderStyle:=TeeFormBorderStyle;

  {$IFNDEF LCL}
  tmpForm.Parent:=Dest;
  {$ENDIF}

  tmpForm.Align:=alClient;

  TeeScaleForm(tmpForm);

  while Source.PageCount>0 do
  begin
    tmp:=Source.Pages[0];
    tmp.PageControl:=Dest;
  end;

  Dest.ActivePage:=Dest.Pages[0];

  TeeTranslateControl(tmpForm);
end;

Function InsertTeeObjectForm(const APageControl:TPageControl; const AShape:TTeeCustomShape):TFormTeeShape;
begin
  // Speed optimization, pass "nil" as owner. (VCL bottleneck)
  result:=TFormTeeShape.CreateForm(nil {APageControl.Owner} ,AShape);
  TFormTeeShape.InsertTeeForm(result.PC1,APageControl);
end;

function EditTeeCustomShape(const AOwner:TComponent; const AShape:TTeeCustomShape;
                            HideText:Boolean=False; const ACaption:String=''):Boolean;
var tmp : TFormTeeShape;
    tmpPanel : TPanel;
begin
  tmp:=TFormTeeShape.CreateForm(AOwner,AShape);
  with tmp do
  try
    Caption :=ACaption;
    BorderStyle:=TeeBorderStyle;
    Height:=Height+30;

    tmpPanel:=TPanel.Create(tmp);
    with tmpPanel do
    begin
      Height:=34;
      BevelOuter:=bvNone;
      Align:=alBottom;
      Parent:=tmp;
    end;

    with TButton.Create(tmp) do
    begin
      Left:=tmp.Width-98;
      Top:=4;
      Caption:='OK'; // Do not localize
      ModalResult:=mrOk;
      Parent:=tmpPanel;
    end;

    if HideText then
    begin
      TabText.Visible:=False;
      TabShadow.Visible:=False;
    end;

    PositionToCenter(tmp);

    result:=ShowModal=mrOk;
  finally
    Free;
  end;
end;

Constructor TFormTeeShape.Create(AOwner:TComponent);
begin
  CreatingForm:=True;
  inherited;
end;

procedure TFormTeeShape.BColorClick(Sender: TObject);
begin
  CBTransparent.Checked:=False;
end;

procedure TFormTeeShape.CBRoundClick(Sender: TObject);
begin
  if CBRound.Checked then TheShape.ShapeStyle:=fosRoundRectangle
                     else TheShape.ShapeStyle:=fosRectangle;

  UDRoundSize.Enabled:=CBRound.Checked;
  ERoundSize.Enabled:=UDRoundSize.Enabled;

  GroupCorners.Enabled:=CBRound.Checked;
end;

type
  TShapeAccess=class(TTeeCustomShape);

procedure TFormTeeShape.RefreshControls(const AShape:TTeeCustomShape);
begin
  CreatingForm:=True;
  TheShape:=AShape;

  with TShapeAccess(TheShape) do
  begin
    CBVisible.Checked      :=Visible;

    CBRound.Checked        :=ShapeStyle=fosRoundRectangle;
    UDRoundSize.Position   :=RoundSize;
    GroupCorners.Enabled   :=CBRound.Checked;

    if HasCorners then
    begin
      CBLeftTop.ItemIndex  :=Ord(Corners.LeftTop.Style);
      CBRightTop.ItemIndex :=Ord(Corners.RightTop.Style);
      CBRightBottom.ItemIndex:=Ord(Corners.RightBottom.Style);
      CBLeftBottom.ItemIndex:=Ord(Corners.LeftBottom.Style);
    end;

    CBTransparent.Checked  :=Transparent;

    RGBevel.ItemIndex      :=Ord(Bevel);
    UDBevW.Position        :=BevelWidth;

    TBTransp.Position      :=Transparency;
    LTransp.Caption        :=TeeStr(TBTransp.Position);

    if Assigned(FBorderEditor) then
       FBorderEditor.RefreshPen(Pen);

    if Assigned(FBrushEditor) then
       FBrushEditor.RefreshBrush(Brush);

    CBDefaultFont.Checked:=Font.DefaultFont;

    if Assigned(FFontEditor) then
       FFontEditor.RefreshControls(Font);

    if Assigned(FShadowEditor) then
       FShadowEditor.RefreshControls(Shadow);

    if Assigned(FEmbossEditor) then
       FEmbossEditor.RefreshControls(Emboss);

    if Assigned(FImageEditor) then
       FImageEditor.RefreshControls(Picture);

    // Callout

    CBSide.ItemIndex:=Ord(ShapeCallout.Side);

    TBSize.Position:=ShapeCallout.Size;
    LSize.Caption:=IntToStr(TBSize.Position);

    TBPosition.Position:=ShapeCallout.Position;
    LPosition.Caption:=IntToStr(TBPosition.Position);

    TBWidth.Position:=ShapeCallout.Width;
    LWidth.Caption:=IntToStr(TBWidth.Position);
  end;

  BBackColor.LinkProperty(TheShape,'Color'); // Do not localize

  EnableBevel;
  CreatingForm:=False;
end;

Procedure TFormTeeShape.EnableBevel;
begin
  EnableControls(TheShape.Bevel<>bvNone,[EBevWidth,UDBevW]);
end;

procedure TFormTeeShape.FormShow(Sender: TObject);
begin
  PC1.ActivePage:=TabFormat;

  if not Assigned(TheShape) then
     TheShape:=TTeeCustomShape(Tag);

  if Assigned(TheShape) then
     RefreshControls(TheShape);

  TeeTranslateControl(Self);
end;

procedure TFormTeeShape.FormCreate(Sender: TObject);
begin
  CreatingForm:=True;

  {$IFDEF D7}
  PC1.DoubleBuffered:=True;
  PageBorder.DoubleBuffered:=True;
  {$ENDIF}

  PositionToCenter(Self);
end;

procedure TFormTeeShape.CBTransparentClick(Sender: TObject);
begin
  TheShape.Transparent:=CBTransparent.Checked;
end;

procedure TFormTeeShape.EBevWidthChange(Sender: TObject);
begin
  if not CreatingForm then TheShape.BevelWidth:=UDBevW.Position
end;

procedure TFormTeeShape.CBVisibleChecked(Sender: TObject);
begin
  TheShape.Visible:=(Sender as TCheckBox).Checked;
end;

procedure TFormTeeShape.ERoundSizeChange(Sender: TObject);
begin
  if not CreatingForm then
     TheShape.RoundSize:=UDRoundSize.Position;
end;

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

procedure TFormTeeShape.PC1Change(Sender: TObject);

  procedure TryFillChildren;
  var t : Integer;
  begin
    if LBChildren.Items.Count=0 then
    begin
      CBLayout.ItemIndex:=Ord(TheShape.ChildLayout);

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

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

begin
  if Assigned(TheShape) then
  with TPageControl(Sender) do
  if ActivePage=TabChildren then
     TryFillChildren
  else
  if ActivePage=TabBorder then
     PageBorderChange(Self)
  else
  if ActivePage=TabText then
  begin
    if PanelFont.ControlCount=0 then
    begin
      FFontEditor:=InsertTeeFontEditor(PanelFont);
      FFontEditor.RefreshControls(TheShape.Font);
    end;
  end
  else
  if ActivePage.ControlCount=0 then
     if ActivePage=TabPattern then
        FBrushEditor:=TBrushDialog.AddDialog(TheShape.Brush,TabPattern)
     else
     if ActivePage=TabShadow then
        FShadowEditor:=TTeeShadowEditor.InsertForm(TheShape.Shadow,TabShadow)
     else
     if ActivePage=TabEmboss then
        FEmbossEditor:=TTeeShadowEditor.InsertForm(TheShape.Emboss,TabEmboss)
     else
     if ActivePage=TabImage then
        FImageEditor:=TBackImageEditor.InsertForm(TabImage,TheShape.Picture);
end;

procedure TFormTeeShape.TBTranspChange(Sender: TObject);
begin
  if not CreatingForm then
  begin
    TShapeAccess(TheShape).Transparency:=TBTransp.Position;
    LTransp.Caption:=TeeStr(TBTransp.Position);
  end;
end;

procedure TFormTeeShape.PageBorderChange(Sender: TObject);
begin
  if Assigned(TheShape) then
     if (PageBorder.ActivePage=TabBorderPen) and (not Assigned(FBorderEditor)) then
         FBorderEditor:=TPenDialog.InsertForm(TheShape.Frame,TabBorderPen);
end;

procedure TFormTeeShape.CBSideChange(Sender: TObject);
begin
  TheShape.ShapeCallout.Side:=TShapeCalloutSide(CBSide.ItemIndex);
end;

procedure TFormTeeShape.TBSizeChange(Sender: TObject);
begin
  TheShape.ShapeCallout.Size:=TBSize.Position;
  LSize.Caption:=IntToStr(TBSize.Position);
end;

procedure TFormTeeShape.TBPositionChange(Sender: TObject);
begin
  TheShape.ShapeCallout.Position:=TBPosition.Position;
  LPosition.Caption:=IntToStr(TBPosition.Position);
end;

procedure TFormTeeShape.TBWidthChange(Sender: TObject);
begin
  TheShape.ShapeCallout.Width:=TBWidth.Position;
  LWidth.Caption:=IntToStr(TBWidth.Position);
end;

procedure TFormTeeShape.RGBevelClick(Sender: TObject);
begin
  TheShape.Bevel:=TPanelBevel(RGBevel.ItemIndex);
  EnableBevel;
end;

function GetCorner(const Value:Integer):TTeeCornerStyle;
begin
  result:=TTeeCornerStyle(Value);
end;

procedure TFormTeeShape.LBChildrenClick(Sender: TObject);
var tmp : TTeeCustomShape;
    tmpClass : TFormClass;
begin
  BDelete.Enabled:=LBChildren.ItemIndex<>-1;

  if BDelete.Enabled then
  begin
    tmp:=TheShape.Children[LBChildren.ItemIndex].Shape;

    FreeAndNil(IChildEditor);

    {if Assigned(IChildEditor) then
       IChildEditor.RefreshControls(tmp)
    else
    }
    begin
      tmpClass:=TFormClass(TeeGetClass(TShapeAccess(tmp).GetEditorClass));

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

      IChildEditor:=tmpClass.Create(Self);
      IChildEditor.Align:=alClient;
      AddFormTo(IChildEditor,TabChildren,tmp);
    end;
  end
  else
  if Assigned(IChildEditor) then
     FreeAndNil(IChildEditor);
end;

procedure TFormTeeShape.BAddClick(Sender: TObject);
var tmp : Integer;
begin
  TheShape.Children.Add;
  tmp:=TheShape.Children.Count-1;
  AddChildItem(tmp);
  LBChildren.ItemIndex:=tmp;
  LBChildrenClick(Self);
end;

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

  if TeeYesNoDelete(TeeMsg_Item+' '+IntToStr(tmp)) then
  begin
    LBChildren.Items.Delete(tmp);
    TheShape.Children.Delete(tmp);

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

    LBChildrenClick(Self);
  end;
end;

procedure TFormTeeShape.CBLayoutChange(Sender: TObject);
begin
  TheShape.ChildLayout:=TTeeShapeLayout(CBLayout.ItemIndex);
end;

procedure TFormTeeShape.CBVisibleClick(Sender: TObject);
begin
  TheShape.Visible:=CBVisible.Checked;
end;

procedure TFormTeeShape.PC1GetImageIndex(Sender: TObject;
  TabIndex: Integer; var ImageIndex: Integer);
begin
  // Dummy, to avoid RTL AV
end;

procedure TFormTeeShape.CBLeftTopChange(Sender: TObject);
begin
  TheShape.Corners.LeftTop.Style:=GetCorner(CBLeftTop.ItemIndex);
end;

procedure TFormTeeShape.CBLeftBottomChange(Sender: TObject);
begin
  TheShape.Corners.LeftBottom.Style:=GetCorner(CBLeftBottom.ItemIndex);
end;

procedure TFormTeeShape.CBRightTopChange(Sender: TObject);
begin
  TheShape.Corners.RightTop.Style:=GetCorner(CBRightTop.ItemIndex);
end;

procedure TFormTeeShape.CBRightBottomChange(Sender: TObject);
begin
  TheShape.Corners.RightBottom.Style:=GetCorner(CBRightBottom.ItemIndex);
end;

procedure TFormTeeShape.CBDefaultFontClick(Sender: TObject);
begin
  TheShape.Font.DefaultFont:=CBDefaultFont.Checked;
end;

end.
