unit fAddScaledFile;

//{$DEFINE SG_DEBUG}

{$IFDEF SG_DEBUG}
  {$DEFINE MEMCHK}
{$ENDIF}

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
  Dialogs, ExtDlgs, StdCtrls, Spin, ExtCtrls, Buttons, CADImage,
  {$IFDEF MEMCHK}
  MemCheck,
  {$ENDIF}
  sgConsts;

type
  PInsertProp = ^TInsertProp;
  TInsertProp = record
    Position: TFPoint;
    Scale: TFPoint;
    Rotation: Double;
    FileName: string;
  end;

type
  TfmAddScaledFile = class(TForm)
    OpenDialog1: TOpenPictureDialog;
    pnlUp: TPanel;
    cbWithoutBorder: TCheckBox;
    pnlAll: TPanel;
    lblWasAdded: TLabel;
    lblCountWasAdded: TLabel;
    lblRotation: TLabel;
    btnOpenFile: TBitBtn;
    btnApplyDefault: TBitBtn;
    cbAddedFiles: TComboBox;
    gbPosition: TGroupBox;
    lblPosX: TLabel;
    lblPosY: TLabel;
    lblPosZ: TLabel;
    edtPosX: TEdit;
    edtPosY: TEdit;
    edtPosZ: TEdit;
    gbScale: TGroupBox;
    lblScaleZ: TLabel;
    Label3: TLabel;
    lblScaleX: TLabel;
    Label6: TLabel;
    lblScaleY: TLabel;
    Label7: TLabel;
    edtScaleX: TEdit;
    edtScaleY: TEdit;
    edtScaleZ: TEdit;
    edtRotation: TEdit;
    pnlDown: TPanel;
    btnOk: TBitBtn;
    btnCancel: TButton;
    procedure btnOpenFileClick(Sender: TObject);
    procedure btnApplyDefaultClick(Sender: TObject);
    procedure btnOkClick(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure cbAddedFilesCloseUp(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure edtExit(Sender: TObject);
    procedure edtKeyPress(Sender: TObject; var Key: Char);
    procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  private
    { Private declarations }
    FIsInternalChanging: Boolean;
    FFilesCount: Integer;
    FCADFile: TsgCADImage;
    procedure SetFilesCount(const Value: Integer);
    procedure ShowProp(Prop: PInsertProp);
    procedure PropToStruct(P: PInsertProp);
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    { Public declarations }
    property CADFile: TsgCADImage read FCADFile;
    property FilesCount: Integer read FFilesCount write SetFilesCount;
  end;

implementation

uses
  SysConst;

{$R *.dfm}

function stod(const S: string; var AValue: Double): Integer;
begin
  Val(S, AValue, Result);
end;

function CheckEditValue(AEdit: TEdit; var AValue: Double): Boolean;
var
  D: Double;
begin
  Result := False;
  if stod(AEdit.Text, D) <> 0 then
  begin
    MessageDlg(Format(SysConst.SInvalidFloat, [AEdit.Text]), mtError, [mbOK], 0);
    AEdit.SetFocus;
    AEdit.SelectAll;
  end
  else
  begin
    AValue := D;
    Result := True;
  end;
end;

procedure TfmAddScaledFile.SetFilesCount(const Value: Integer);
begin
  FFilesCount := Value;
end;

procedure TfmAddScaledFile.ShowProp(Prop: PInsertProp);
begin
  FIsInternalChanging := True;
  try
    edtPosX.Text := FloatToStr(Prop^.Position.X);
    edtPosY.Text := FloatToStr(Prop^.Position.Y);
    edtPosZ.Text := FloatToStr(Prop^.Position.Z);
    edtScaleX.Text := FloatToStr(Prop^.Scale.X);
    edtScaleY.Text := FloatToStr(Prop^.Scale.Y);
    edtScaleZ.Text := FloatToStr(Prop^.Scale.Z);
    edtRotation.Text := FloatToStr(Prop^.Rotation);
  finally
    FIsInternalChanging := False;
  end;
  {if (cbAddedFiles.Items.Count > 0)and(cbAddedFiles.ItemIndex <> -1) then
  begin
    S := IntToStr(cbAddedFiles.ItemIndex)+'. '+ExtractFileName(P^.FileName);
    cbAddedFiles.Items[cbAddedFiles.ItemIndex] := S;
  end;}
end;

procedure TfmAddScaledFile.PropToStruct(P: PInsertProp);
begin
  if CheckEditValue(edtPosX, P^.Position.X) then
  if CheckEditValue(edtPosY, P^.Position.Y) then
  if CheckEditValue(edtPosZ, P^.Position.Z) then
  if CheckEditValue(edtScaleX, P^.Scale.X) then
  if CheckEditValue(edtScaleY, P^.Scale.Y) then
  if CheckEditValue(edtScaleZ, P^.Scale.Z) then
  if CheckEditValue(edtRotation, P^.Rotation) then
  if (cbAddedFiles.Items.Count > 0) and (cbAddedFiles.ItemIndex <> -1) then
    P^.FileName := PInsertProp(cbAddedFiles.Items.Objects[cbAddedFiles.ItemIndex])^.FileName;
end;

procedure TfmAddScaledFile.btnOpenFileClick(Sender: TObject);
var
  P: PInsertProp;
  S: string;
begin
  OpenDialog1.FileName := '';
  if not OpenDialog1.Execute then Exit;
  New(P);
  PropToStruct(P);
  P^.FileName := OpenDialog1.FileName;
  P^.Scale := MakeFPoint(100, 100, 100);
  S := IntToStr(FFilesCount)+'. '+ExtractFileName(P^.FileName);
  cbAddedFiles.Items.Add(S);
  cbAddedFiles.Items.Objects[cbAddedFiles.Items.Count - 1] := Pointer(P);
  cbAddedFiles.ItemIndex := cbAddedFiles.Items.Count - 1;
  cbAddedFilesCloseUp(Sender);
  Inc(FFilesCount);
  lblCountWasAdded.Caption := IntToStr(FFilesCount);
  cbWithoutBorder.Enabled := True;
end;

procedure TfmAddScaledFile.btnApplyDefaultClick(Sender: TObject);
begin
  edtPosX.Text := '0';
  edtPosY.Text := '0';
  edtPosZ.Text := '0';
  edtScaleX.Text := '100';
  edtScaleY.Text := '100';
  edtScaleZ.Text := '100';
  edtRotation.Text := '0';
end;

procedure TfmAddScaledFile.btnOkClick(Sender: TObject);
var
  I: Integer;
  P: PInsertProp;
  S: string;
  vPicture: TPicture;
  vCADImage: TGraphic;
begin
  if (cbAddedFiles.Items.Count > 0) then
  begin
    vPicture := TPicture.Create;
    try
      FCADFile.Converter.InitializeSections;
      FCADFile.IsWithoutBorder := cbWithoutBorder.Checked;
      for I := 0 to cbAddedFiles.Items.Count - 1 do
      begin
        P := PInsertProp(cbAddedFiles.Items.Objects[I]);
        vPicture.LoadFromFile(P^.FileName);
        if vPicture.Graphic is TsgCADImage then
        begin
          vCADImage := TGraphicClass(vPicture.Graphic.ClassType).Create;
          vCADImage.Assign(vPicture.Graphic);
          TsgCADImage(vCADImage).IsWithoutBorder := cbWithoutBorder.Checked;
          S := ChangeFileExt(ExtractFileName(P^.FileName), '');
          FCADFile.AddScaledDXF(vCADImage, S, P^.Position,
            MakeFPoint(P^.Scale.X / 100.0, P^.Scale.Y / 100.0, P^.Scale.Z / 100.0),
            P^.Rotation);
        end;
      end;
    finally
      vPicture.Free;
    end;
  end;
  FCADFile.GetExtents;
end;

constructor TfmAddScaledFile.Create(AOwner: TComponent);
begin
  inherited;
  FFilesCount := 0;
  FCADFile := TsgCADImage.Create;
  FIsInternalChanging := False;
end;

destructor TfmAddScaledFile.Destroy;
begin
  FCADFile.Free;
  inherited;
end;

procedure TfmAddScaledFile.edtExit(Sender: TObject);
var
  Pt: TPoint;
  P: PInsertProp;
  D: Double;
begin
  if not (GetCursorPos(Pt) and (FindVCLWindow(Pt) = btnCancel) and
     (GetKeyState(VK_LBUTTON) <> 0)) then
    if not FIsInternalChanging and CheckEditValue(TEdit(Sender), D) then
    begin
      if (cbAddedFiles.Items.Count > 0) and (cbAddedFiles.ItemIndex <> -1) then
      begin
        P := PInsertProp(cbAddedFiles.Items.Objects[cbAddedFiles.ItemIndex]);
        PropToStruct(P);
      end;
    end;
end;

procedure TfmAddScaledFile.edtKeyPress(Sender: TObject; var Key: Char);
begin
  if Key in [',', '.', GetDecimalSeparator] then
    Key := '.';
end;

procedure TfmAddScaledFile.FormDestroy(Sender: TObject);
var
  I: Integer;
  P: PInsertProp;
begin
  for I := 0 to cbAddedFiles.Items.Count - 1 do
  begin
    P := PInsertProp(cbAddedFiles.Items.Objects[I]);
    if P <> nil then
      Dispose(P);
  end;
end;

procedure TfmAddScaledFile.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  if Key = VK_ESCAPE then
    Close;
end;

procedure TfmAddScaledFile.cbAddedFilesCloseUp(Sender: TObject);
var
  P: PInsertProp;
begin
  if (cbAddedFiles.Items.Count > 0) then
  begin
    P := PInsertProp(cbAddedFiles.Items.Objects[cbAddedFiles.ItemIndex]);
    ShowProp(P);
  end;
end;

procedure TfmAddScaledFile.FormCreate(Sender: TObject);
begin
  OpenDialog1.Filter := GraphicFilter(TsgCADImage);
end;

initialization
  {$IFDEF MEMCHK}
  MemChk
  {$ENDIF}

end.
