unit Vis3D_AxesSettings;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, TextEditor, Vcl.StdCtrls, rgl,
  UxPanel, Vcl.ExtCtrls, ColorContainer, ScrollBoxEx, Vcl.Menus;

type
  TVis3D_AxesSettingsFrm = class(TDrawableOptionsFrm3D)
    pnGeneral: TPanel;
    pnToolbar: TUxClient;
    btnX: TUxButton;
    btnY: TUxButton;
    btnGeneral: TUxButton;
    btnZ: TUxButton;
    pnX: TPanel;
    pnY: TPanel;
    pnZ: TPanel;
    btnGrids: TUxButton;
    pnGrids: TPanel;
    lblGrids: TLabel;
    lbGrids: TListBox;
    btnAddGrid: TUxButton;
    btnDelGrid: TUxButton;
    pnGridCtlCntr: TPanel;
    pmGrids: TPopupMenu;
    mnuAddGrid: TMenuItem;
    mnuRenameGrid: TMenuItem;
    mnuDeleteGrid: TMenuItem;
    procedure btnApplyClick(Sender: TObject);
    procedure SetPage(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure lbGridsClick(Sender: TObject);
    procedure btnDelGridClick(Sender: TObject);
    procedure lbGridsKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure btnAddGridClick(Sender: TObject);
    procedure mnuDeleteGridClick(Sender: TObject);
    procedure mnuAddGridClick(Sender: TObject);
    procedure mnuRenameGridClick(Sender: TObject);
    procedure pmGridsPopup(Sender: TObject);
  strict private
    FPageButtons: TArray<TUxButton>;
    FGeneral, FX, FY, FZ: TDrawableOptionsFrm3D;
    FGridCtl: TDrawableOptionsFrm3D;
    procedure InitializeGrids;
    procedure RenameGrid;
  public
    procedure Initialize; override;
    procedure UpdateDrawable; override;
  end;

implementation

{$R *.dfm}

uses
  Vis3D_AxisSettings, Vis3D_GeoObjSettings, MultiInput;

procedure TVis3D_AxesSettingsFrm.btnAddGridClick(Sender: TObject);
begin

  var Axes := FDrawable as TAxes;
  var S: string := 'New grid';

  if TMultiInputBox.TextInputBox(Screen.ActiveCustomForm, 'New Grid', 'Please enter the name of the new grid:', S, ecNormal, False) then
  begin
    var NewGrid := Axes.CreateChild<TGrid>;
    NewGrid.Name := S;
    InitializeGrids;
  end;

end;

procedure TVis3D_AxesSettingsFrm.btnApplyClick(Sender: TObject);
begin
  UpdateDrawable;
end;

procedure TVis3D_AxesSettingsFrm.btnDelGridClick(Sender: TObject);
begin

  if lbGrids.ItemIndex = -1 then
  begin
    btnDelGrid.Enabled := False;
    Exit;
  end;

  var LGrid := lbGrids.Items.Objects[lbGrids.ItemIndex] as TDrawable3D;

  if LGrid = nil then
    Exit;

  if not TDrawable3D.Verify(LGrid) then
  begin
    InitializeGrids;
    Exit;
  end;

  var Axes := FDrawable as TAxes;

  Axes.DeleteChild(LGrid);
  InitializeGrids;

end;

procedure TVis3D_AxesSettingsFrm.FormCreate(Sender: TObject);
begin

  var Axes := FDrawable as TAxes;

  btnGeneral.Tag := NativeInt(pnGeneral);
  btnX.Tag := NativeInt(pnX);
  btnY.Tag := NativeInt(pnY);
  btnZ.Tag := NativeInt(pnZ);
  btnGrids.Tag := NativeInt(pnGrids);
  FPageButtons := [btnGeneral, btnX, btnY, btnZ, btnGrids];

  SetPage(btnX);

  FGeneral := TVis3D_GeoObjSettingsFrm.Create(Self, Axes);
  (FGeneral as TVis3D_GeoObjSettingsFrm).Customize(False, True, True);
  FGeneral.Parent := pnGeneral;
  FGeneral.BorderStyle := bsNone;
  FGeneral.Align := alClient;
  FGeneral.Show;

  FX := TVis3D_AxisSettingsFrm.Create(Self, Axes.X);
  FX.Parent := pnX;
  FX.BorderStyle := bsNone;
  FX.Align := alClient;
  FX.Show;

  FY := TVis3D_AxisSettingsFrm.Create(Self, Axes.Y);
  FY.Parent := pnY;
  FY.BorderStyle := bsNone;
  FY.Align := alClient;
  FY.Show;

  FZ := TVis3D_AxisSettingsFrm.Create(Self, Axes.Z);
  FZ.Parent := pnZ;
  FZ.BorderStyle := bsNone;
  FZ.Align := alClient;
  FZ.Show;

end;

procedure TVis3D_AxesSettingsFrm.Initialize;
begin
  inherited;
  InitializeGrids;
end;

procedure TVis3D_AxesSettingsFrm.InitializeGrids;
begin

  var Axes := FDrawable as TAxes;

  FreeAndNil(FGridCtl);
  btnDelGrid.Enabled := False;

  lbGrids.Items.BeginUpdate;
  try
    lbGrids.Clear;
    for var i := 0 to Axes.ChildCount - 1 do
    begin
      var Child := Axes.Children[i];
      if Child is TGrid then
        lbGrids.Items.AddObject(Child.Name, TObject(Child));
    end;
  finally
    lbGrids.Items.EndUpdate;
  end;

end;

procedure TVis3D_AxesSettingsFrm.lbGridsClick(Sender: TObject);
begin

  pnGridCtlCntr.Perform(WM_SETREDRAW, 0, 0);
  try

    var LGrid := TDrawable3D(nil);
    if lbGrids.ItemIndex <> -1 then
      LGrid := lbGrids.Items.Objects[lbGrids.ItemIndex] as TDrawable3D;

    btnDelGrid.Enabled := lbGrids.ItemIndex <> -1;

    if LGrid = nil then
    begin
      FreeAndNil(FGridCtl);
      Exit;
    end;

    if not TDrawable3D.Verify(LGrid) then
      raise ERglError.Create('This object has been removed.');

    if Assigned(FGridCtl) and (FGridCtl.Drawable = LGrid) then
      Exit;

    FreeAndNil(FGridCtl);
    FGridCtl := LGrid.OptionsFormClass.Create(Self, LGrid);
    FGridCtl.Parent := pnGridCtlCntr;
    FGridCtl.BorderStyle := bsNone;
    FGridCtl.Align := alClient;
    FGridCtl.Show;

  finally
    pnGridCtlCntr.Perform(WM_SETREDRAW, 1, 0);
    RedrawWindow(pnGridCtlCntr.Handle, nil, 0,
      RDW_ERASE or RDW_FRAME or RDW_INVALIDATE or RDW_ALLCHILDREN);
  end;

end;

procedure TVis3D_AxesSettingsFrm.lbGridsKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  case Key of
    VK_DELETE:
      btnDelGridClick(Sender);
    VK_F2:
      RenameGrid;
  end;
end;

procedure TVis3D_AxesSettingsFrm.mnuAddGridClick(Sender: TObject);
begin
  btnAddGridClick(Sender)
end;

procedure TVis3D_AxesSettingsFrm.mnuDeleteGridClick(Sender: TObject);
begin
  btnDelGridClick(Sender)
end;

procedure TVis3D_AxesSettingsFrm.mnuRenameGridClick(Sender: TObject);
begin
  RenameGrid;
end;

procedure TVis3D_AxesSettingsFrm.pmGridsPopup(Sender: TObject);
begin
  mnuRenameGrid.Enabled := lbGrids.ItemIndex <> -1;
  mnuDeleteGrid.Enabled := lbGrids.ItemIndex <> -1;
end;

procedure TVis3D_AxesSettingsFrm.RenameGrid;
begin
  var LGrid := TDrawable3D(nil);
  if lbGrids.ItemIndex <> -1 then
    LGrid := lbGrids.Items.Objects[lbGrids.ItemIndex] as TDrawable3D;
  if Assigned(LGrid) then
  begin
    if not TDrawable3D.Verify(LGrid) then
      raise ERglError.Create('This object has been removed.');
    var S: string := LGrid.Name;
    if TMultiInputBox.TextInputBox(Screen.ActiveCustomForm, 'Rename Grid', 'Please enter the new name of the grid:', S, ecNormal, False) then
    begin
      LGrid.Name := S;
      InitializeGrids;
    end;
  end;
end;

procedure TVis3D_AxesSettingsFrm.SetPage(Sender: TObject);
begin
  LockDrawing;
  try
    for var B in FPageButtons do
    begin
      if B.Tag = 0 then
        Continue;
      var P := TObject(B.Tag) as TWinControl;
      P.Align := alClient;
      P.Visible := B = Sender;
      B.Down := B = Sender;
      if (B = Sender) and Visible and P.Visible and P.CanFocus then
      begin
        if (P.ControlCount = 1) and (P.Controls[0] is TCustomForm) then
        begin
          P.Controls[0].ScaleForPPI(Self.CurrentPPI);
          P.Realign;
        end;
        P.SetFocus;
      end;
    end;
  finally
    UnlockDrawing;
  end;
end;

procedure TVis3D_AxesSettingsFrm.UpdateDrawable;
begin
  inherited;
end;

end.
