unit Unit1;
{$INCLUDE SGDXF.INC}

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, JPEG,
  ExtCtrls, StdCtrls, DXFImage, DXFConv, ComCtrls, Menus, Printers, MVFont,
  ExtDlgs, Buttons, SGExport, sgConsts,
  {$IFNDEF sgDXFONLY}
  DWG, HPGL2, CGM, SVG,
  {$ENDIF}
  DXFExport, CADtoDXF,
  ShellAPI,
  fLayers,
  Spin, sgLines,
  ShlObj, ActiveX, IniFiles, SHX, Math, sgDrawingNavigator, sgTools
  {$IFDEF SGDEL_4}
  ,ActnList
  {$ENDIF};

const
  sNotVectorial: string = 'Raster drawings can not be saved to DXF format';

  fAccuracy = 0.003;

type
  TSelectionMode = (smNone, smRectangle, smEllipse);

  TRectangleAround = record
    Box: TFRect;
    PaperSpace: Integer;
  end;

  TForm1 = class(TForm)
    Panel2: TPanel;
    prbProgress: TProgressBar;
    pgcDrawing: TPageControl;
    tbsImage: TTabSheet;
    tbsStructure: TTabSheet;
    TreeView1: TTreeView;
    Splitter1: TSplitter;
    ListBox1: TListBox;
    MainMenu1: TMainMenu;
    MIFile: TMenuItem;
    MIOpen: TMenuItem;
    MIClose: TMenuItem;
    N4: TMenuItem;
    MIExit: TMenuItem;
    pnlFileName: TPanel;
    pnlTime: TPanel;
    MIView: TMenuItem;
    MiOEM: TMenuItem;
    PrintDialog1: TPrintDialog;
    MIPrint: TMenuItem;
    MIScale: TMenuItem;
    MIAuto: TMenuItem;
    MIx2: TMenuItem;
    MIx4: TMenuItem;
    MIx8: TMenuItem;
    MIx16: TMenuItem;
    MIPrev: TMenuItem;
    N1: TMenuItem;
    N251: TMenuItem;
    N501: TMenuItem;
    MIx1: TMenuItem;
    OpenDialog1: TOpenPictureDialog;
    Panel4: TPanel;
    BtnOpen: TSpeedButton;
    BtnPlus: TSpeedButton;
    BtnMinus: TSpeedButton;
    BtnReal: TSpeedButton;
    BtnPrev: TSpeedButton;
    BtnPrint: TSpeedButton;
    N2: TMenuItem;
    MIAbout: TMenuItem;
    BtnSave: TSpeedButton;
    mmiSaveAs: TMenuItem;
    SavePictureDialog: TSavePictureDialog;
    ImageColors1: TMenuItem;
    mmiDisabled: TMenuItem;
    mmiBlack: TMenuItem;
    mmiNormal: TMenuItem;
    SoftGoldHomePage1: TMenuItem;
    btnLayers: TSpeedButton;
    BtnPrint1: TSpeedButton;
    pnlCoords: TPanel;
    btnFitToScreen: TSpeedButton;
    btnIsWithoutBorder: TSpeedButton;
    btnDrawAllColor: TSpeedButton;
    btnBlackWhite: TSpeedButton;
    btnWhiteBackground: TSpeedButton;
    btnBlackBackground: TSpeedButton;
    btnShowLineWeight: TSpeedButton;
    btnHideLineWeight: TSpeedButton;
    btnSplittedArc: TSpeedButton;
    btnArcNormal: TSpeedButton;
    sb3DOrbit: TSpeedButton;
    BtnPrint2: TSpeedButton;
    PopupMenu1: TPopupMenu;
    Printer1: TMenuItem;
    Metafile1: TMenuItem;
    mmiSaveAsBigEMF: TMenuItem;
    SavePictureDialogEMF: TSavePictureDialog;
    pnlLayouts: TPanel;
    lblLayouts: TLabel;
    cbLayouts: TComboBox;
    lblNumPartsCircle: TLabel;
    speNumPartsCircle: TSpinEdit;
    lblNumPartsSpline: TLabel;
    speNumPartsSpline: TSpinEdit;
    sb3DAxes: TSpeedButton;
    mmiShowpoint: TMenuItem;
    mmiFindtext: TMenuItem;
    mmiReopenSameView: TMenuItem;
    miFonts: TMenuItem;
    N3: TMenuItem;
    sbFonts: TSpeedButton;
    sbDrid: TSpeedButton;
    speGridCount: TSpinEdit;
    lblDridCount: TLabel;
    sbDrawingBox: TSpeedButton;
    mmiReopenSWIsometric: TMenuItem;
    sbShowBorder: TSpeedButton;
    OpenBorder: TOpenPictureDialog;
    Snap1: TMenuItem;
    mmiObjectSnapAll: TMenuItem;
    imgFrame: TImage;
    procedure MIOpenClick(Sender: TObject);
    procedure MICloseClick(Sender: TObject);
    procedure MIExitClick(Sender: TObject);
    procedure TreeView1Change(Sender: TObject; Node: TTreeNode);
    procedure MiOEMClick(Sender: TObject);
    procedure MIPrintClick(Sender: TObject);
    procedure MIAutoClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
    procedure MIPrevClick(Sender: TObject);
    procedure sgPaintBoxScaling(Sender: TObject);
    procedure sgPaintBoxProgress(Sender: TObject; Stage: TProgressStage;
      PercentDone: Byte; RedrawNow: Boolean; const R: TRect;
      const Msg: String);
    procedure BtnPlusClick(Sender: TObject);
    procedure BtnMinusClick(Sender: TObject);
    procedure pgcDrawingChanging(Sender: TObject;
      var AllowChange: Boolean);
    procedure MIHelpClick(Sender: TObject);
    procedure OpenDialog1Show(Sender: TObject);
    procedure OpenDialog1Close(Sender: TObject);
    procedure BtnSaveClick(Sender: TObject);
    procedure mmiDisabledClick(Sender: TObject);
    procedure mmiBlackClick(Sender: TObject);
    procedure mmiNormalClick(Sender: TObject);
    procedure SoftGoldHomePage1Click(Sender: TObject);
    procedure MIAboutClick(Sender: TObject);
    procedure btnLayersClick(Sender: TObject);
    procedure sgPaintBoxPaint(Sender: TObject);
    procedure sgPaintBoxMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure BtnPrint1Click(Sender: TObject);
    procedure btnFitToScreenClick(Sender: TObject);
    procedure btnIsWithoutBorderClick(Sender: TObject);
    procedure btnShowLineWeightClick(Sender: TObject);
    procedure btnSplittedArcClick(Sender: TObject);
    procedure btnDrawAllColorClick(Sender: TObject);
    procedure btnWhiteBackgroundClick(Sender: TObject);
    procedure sb3DOrbitClick(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Printer1Click(Sender: TObject);
    procedure Metafile1Click(Sender: TObject);
    procedure BtnPrint2Click(Sender: TObject);
    procedure mmiSaveAsBigEMFClick(Sender: TObject);
    procedure cbLayoutsChange(Sender: TObject);
    procedure pgcDrawingChange(Sender: TObject);
    procedure speNumPartsCircleChange(Sender: TObject);
    procedure speNumPartsSplineChange(Sender: TObject);
    procedure sb3DAxesClick(Sender: TObject);
    procedure mmiShowpointClick(Sender: TObject);
    procedure mmiFindtextClick(Sender: TObject);
    procedure mmiReopenSameViewClick(Sender: TObject);
    procedure miFontsClick(Sender: TObject);
    procedure speGridCountChange(Sender: TObject);
    procedure sbDrawingBoxClick(Sender: TObject);
    procedure mmiReopenSWIsometricClick(Sender: TObject);
    procedure sbShowBorderClick(Sender: TObject);
    procedure mmiObjectSnapAllClick(Sender: TObject);
    procedure SaveToDXF(AFileName: string);
    procedure actFormUpdate(Sender: TObject);
    procedure sbDridClick(Sender: TObject);
    procedure BtnRealClick(Sender: TObject);
    procedure mmiScaleClick(Sender: TObject);
  private
    FSearchingText: string;
    FTextPoint: TFPoint;
    FTextBox: TFRect;
    FCADParams: TsgCADIterate;
    FSearchResult: Boolean;
    FFindFlag: Boolean;
    FSelectionMode: TSelectionMode;
    FSearchModeIsAll: Boolean;
    FSelectedEntities: TList;
    FFileName: string;
    FOptions: TIniFile;
    FStoredNullWidth: Integer;
    FsgPaintBox: TsgDrawingNavigator;
    {$IFDEF SGDEL_4}
    FactForm: TAction;
    {$ENDIF}
    procedure Enable3DOrbit(AIsEnabled: Boolean);
    procedure Enable3DAxes(AIsEnabled: Boolean);
    procedure LoadStructure;
    procedure Time;
    procedure EnableControls;
    procedure Open(const FileName: String);
    procedure RestoreNullWidth(AGraphic: TGraphic);
    procedure SetImgOpt;
    procedure SetNullWidth(AGraphic: TGraphic; AWidth: Integer);
    procedure ViewLayouts;
    function GetImg: TsgDXFImage;
    {$IFNDEF SGDEL_4}
    procedure UpdateActions;
    procedure DoActionIdle;
    {$ENDIF}
    procedure AppIdle(Sender: TObject; var Done: Boolean);
  protected
    procedure ActualGraphic(var vResult: TGraphic);
    function AddRectToConv(ABox: TFRect): TsgDXFEntity;
    procedure SelectEntities;
    procedure LoadOptions;
    procedure BreakLoading(Sender: TObject);
  public
    function FindText(const S: String; const ASelection: TSelectionMode; const ASearch: Boolean): Boolean;
    function ReadCADEntities(Entity: TsgDXFEntity): Integer;
    procedure WndProc(var Message: TMessage); override;
    {$IFDEF SGDEL_4}
    property actForm: TAction read FactForm;
    {$ENDIF}
    property sgPaintBox: TsgDrawingNavigator read FsgPaintBox;
    property Img: TsgDXFImage read GetImg;
  end;

var
  Form1: TForm1;
  Start: Integer;
  FIntPoints: TList;
  Cntr: Integer = 1;


implementation

uses
  Unit2, Unit3,
  fFonts, fPaths;

{$R *.DFM}

function CreateLines(D: integer; AWidth, AHeight: integer): boolean;
var
  I: integer;
  dx, dy: integer;
begin
  if FIntPoints = nil then
    FIntPoints := TList.Create
  else
    FIntPoints.Clear;
  I := 0;
  if D <= 0 then
    D := 1;
  dx := D;
  dy := D;
  while (I*dx <= AWidth) do
  begin
    FIntPoints.Add(pointer(I * dx));
    FIntPoints.Add(pointer(0));
    FIntPoints.Add(pointer(I * dx));
    FIntPoints.Add(pointer(AHeight));
    inc(I);
  end;
  I := 0;
  while (I*dy <= AHeight) do
  begin
    FIntPoints.Add(pointer(0));
    FIntPoints.Add(pointer(I * dy));
    FIntPoints.Add(pointer(AWidth));
    FIntPoints.Add(pointer(I * dy));
    inc(I);
  end;
  Result := True;
  if FIntPoints.Count < 2 then
    Result := False;
end;

procedure DrawPolyPolyLine(DC: HDC; IntPoints: TList);
var
  I, N, C: Integer;
  P: Pointer;
begin
  N := IntPoints.Count shr 2;
  if N = 0 then
    Exit;
  C := IntPoints.Count;
  for I := 0 to N - 1 do
    IntPoints.Add(Pointer(2));
  P := IntPoints.List;
  Inc(PInteger(P), C);
  PolyPolyline(DC, IntPoints.List^, P^, N);
end;

procedure TForm1.LoadOptions;
var
  vSet: string;
begin
   if not Assigned(FOptions) then
   begin
    vSet := ExtractFilePath(Application.ExeName) + sSettings;
    FOptions := TIniFile.Create(vSet);
   end;
   bUseSHXFonts := FOptions.ReadBool(sGeneral, sUseSHX, bUseSHXFonts);
   sSHXSearchPaths := FOptions.ReadString(sGeneral, sSHXPaths, sSHXSearchPaths);
   sDefaultSHXPath := FOptions.ReadString(sGeneral, sSHXPath, sDefaultSHXPath);
   sDefaultSHXFont := FOptions.ReadString(sGeneral, sSHXFont, sDefaultSHXFont);
end;

function TForm1.AddRectToConv(ABox: TFRect): TsgDXFEntity;
var
  Vertex: TsgDXFVertex;
begin
  Result := TsgDXFPolyline.Create;
  Vertex := TsgDXFVertex.Create;
  Vertex.Point := ABox.TopLeft;
  Result.AddEntity(Vertex);
  Vertex := TsgDXFVertex.Create;
  Vertex.Point := MakeFPoint(ABox.BottomRight.X, ABox.TopLeft.Y, ABox.TopLeft.Z);
  Result.AddEntity(Vertex);
  Vertex := TsgDXFVertex.Create;
  Vertex.Point := ABox.BottomRight;
  Result.AddEntity(Vertex);
  Vertex := TsgDXFVertex.Create;
  Vertex.Point := MakeFPoint(ABox.TopLeft.X, ABox.BottomRight.Y, ABox.BottomRight.Z);
  Result.AddEntity(Vertex);
  Result.SetColor(clRed);
  Result.SetLWeight(1);
  TsgDXFPolyline(Result).Closed := True;
end;

function TForm1.ReadCADEntities(Entity: TsgDXFEntity): Integer;
var
  S1, S2: String;
  vRectAround: ^TRectangleAround;
  P: TFPoint;
  CurAttrib: TsgDXFAttrib;
  vBox: TFRect;
  vAttribFlag: Boolean;
begin
  Result := 0;
  if FFindFlag then
    Exit;
  if Entity is TsgDXFMText then
  begin
    FTextPoint := TsgDXFMText(Entity).Point;
  end;
  if Entity is TsgDXFText then
  begin
    S1 := AnsiUpperCase(FSearchingText);
    S2 := AnsiUpperCase(TsgDXFText(Entity).Text);
    vAttribFlag := False;
    if FCADParams.Insert <> nil then
    begin
      P := PtXMat(TsgDXFText(Entity).StartPoint, FCADParams.Matrix);
      CurAttrib := FCADParams.Insert.Attrib(S2, P);
      if CurAttrib <> nil then
      begin
        S2 := CurAttrib.Text;
        vBox := CurAttrib.Box;
        vAttribFlag := True;
      end;
    end;
    if AnsiPos(S1, S2) > 0 then
    begin
      FSearchResult := True;
      FTextPoint := PtXMat(TsgDXFText(Entity).StartPoint, FCADParams.Matrix);
      FTextBox.TopLeft := PtXMat(TsgDXFText(Entity).Box.TopLeft, FCADParams.Matrix);
      FTextBox.BottomRight := PtXMat(TsgDXFText(Entity).Box.BottomRight, FCADParams.Matrix);
      if not(FSearchModeIsAll) then
        FFindFlag := True;
      if FSelectionMode = smRectangle then
      begin
        New(vRectAround);
        if not vAttribFlag then
        begin
          vRectAround^.Box.TopLeft := PtXMat(Entity.Box.TopLeft, FCADParams.Matrix);
          vRectAround^.Box.BottomRight := PtXMat(Entity.Box.BottomRight, FCADParams.Matrix);
        end
        else
          vRectAround^.Box := vBox;
        vRectAround.PaperSpace := Ord(Img.Layouts[0] <> Img.CurrentLayout);
        FSelectedEntities.Add(vRectAround);
      end;
    end;
  end;
end;

procedure TForm1.SelectEntities;
var
  I: Integer;
  Ent: TsgDXFEntity;
begin
  for I := 0 to FSelectedEntities.Count - 1 do
  begin
    Ent := AddRectToConv(TRectangleAround(FSelectedEntities[I]^).Box);
    if Ent <> nil then
    begin
      Img.Converter.Sections[csEntities].AddEntity(Ent);
      if Assigned(Img.Converter.OnCreate) then
        Img.Converter.OnCreate(Ent);
      Img.Converter.Loads(Ent);
      Ent.PaperSpace := TRectangleAround(FSelectedEntities[I]^).PaperSpace;
      sgPaintBox.Invalidate;
    end;
  end;
end;

function TForm1.FindText(const S: String; const ASelection: TSelectionMode; const ASearch: Boolean): Boolean;
var
  I: Integer;
begin
  FSearchingText := S;
  FSelectionMode := ASelection;
  FSearchModeIsAll := ASearch;
  FSearchResult := False;
  FCADParams.Matrix := IdentityMat;
  Img.Converter.AutoInsert := True; // to get all the elements inside of inserts
  FFindFlag := False;
  FSelectedEntities := TList.Create;
  try
    Img.Converter.Iterate(ReadCADEntities, nil, FCADParams);
    SelectEntities;
  finally
    for I := 0 to FSelectedEntities.Count - 1 do
      Dispose(FSelectedEntities[I]);
    FSelectedEntities.Free;
  end;
  Result := FSearchResult;
end;

procedure TForm1.Time;
var T: Integer;
begin
  T := (GetCurrentTime - Start) div 1000;
  pnlTime.Caption := Format('%.2d:%.2d', [T div 60, T mod 60]);
  pnlTime.Update;
end;

procedure TForm1.LoadStructure;

  procedure Add(Parent: TTreeNode; E: TsgDXFEntity);
  var
    I: Integer;
  begin
    Parent := TreeView1.Items.AddChildObject(Parent, E.EntName, E);
    Application.ProcessMessages;
    prbProgress.Position := prbProgress.Position + 1;
    for I:=0 to E.Count-1 do Add(Parent, E[I]);
  end;

var
  I: Integer;
  S_LStructure: string;
begin
  if Img = nil then Exit;
  prbProgress.Position := 0;
  prbProgress.Max := Img.Converter.Count;
  pnlFileName.Caption := S_LStructure;
  pnlFileName.Update;
  TreeView1.Items.BeginUpdate;
  try
    for I:=0 to Img.Converter.Main.Count-1
    do Add(nil, Img.Converter.Main[I]);
  finally
    prbProgress.Position := 0;
    TreeView1.Items.EndUpdate;
  end;
end;

procedure TForm1.EnableControls;
var
  I: Integer;
  vNotEmpty: Boolean;
  vCAD: Boolean;
begin
  vNotEmpty := not sgPaintBox.Empty;
  vCAD := Img <> nil;
  for I := 0 to MIScale.Count-1 do
    MIScale.Items[I].Enabled := vNotEmpty;
  MIPrint.Enabled := vNotEmpty;
  BtnSave.Enabled := vNotEmpty;
  BtnPrint.Enabled := vNotEmpty;
  BtnPrint1.Enabled := vNotEmpty;
  BtnPrint2.Enabled := vNotEmpty;
  BtnPlus.Enabled := vNotEmpty;
  BtnMinus.Enabled := vNotEmpty;
  BtnReal.Enabled := vNotEmpty and (Abs(1 - sgPaintBox.Scale) > fAccuracy);
  BtnPrev.Enabled := vNotEmpty and sgPaintBox.HasPreviousView;
  btnLayers.Enabled := vCAD;
  btnFitToScreen.Enabled := vNotEmpty;
  mmiSaveAsBigEMF.Enabled := vNotEmpty;
  mmiSaveAs.Enabled := vNotEmpty;
  MIPrint.Enabled := vNotEmpty;
  MIClose.Enabled := vNotEmpty;
  btnIsWithoutBorder.Enabled := vCAD;
  btnDrawAllColor.Enabled := vCAD;
  btnBlackWhite.Enabled := vCAD;
  btnWhiteBackground.Enabled := vCAD;

  btnBlackBackground.Enabled := vCAD;
  btnShowLineWeight.Enabled := vCAD;
  btnHideLineWeight.Enabled := vCAD;
  btnSplittedArc.Enabled := vCAD;
  btnArcNormal.Enabled := vCAD;
  sbDrawingBox.Enabled := vCAD;
  sb3DOrbit.Enabled := vCAD and Img.CurrentLayout.IsModel;
  sb3DAxes.Enabled := vCAD;
  sbDrid.Enabled := vCAD;
  sbShowBorder.Enabled := vCAD;

  MiOEM.Enabled := vCAD;
  mmiShowpoint.Enabled := vCAD;
  mmiFindtext.Enabled := vCAD;
  mmiReopenSameView.Enabled := vCAD;
  mmiReopenSWIsometric.Enabled := vCAD;
  mmiDisabled.Enabled := vCAD;
  mmiBlack.Enabled := vCAD;
  mmiNormal.Enabled := vCAD;
  mmiObjectSnapAll.Enabled := vCAD;
end;

procedure TForm1.Open(const FileName: String);
var
  vBreakForm: TForm;

  procedure MakeBreakForm;
  const
    sBreakFormName = 'fmBreakForm';
  var
    vB: TButton;
  begin
    vBreakForm := TForm(Application.FindComponent(sBreakFormName));
    if not Assigned(vBreakForm) then
    begin
      vBreakForm := TForm.Create(Application);
      vBreakForm.Name := sBreakFormName;
      vBreakForm.BorderStyle := bsDialog;
      vBreakForm.Caption := 'Loading...';
      vBreakForm.SetBounds(Left + Width div 2 - 151 div 2,
        Top + Height div 2 - 76 div 2, 151, 76);
      vB := TButton.Create(vBreakForm);
      vB.Parent := vBreakForm;
      vB.Left := 8;
      vB.Top := 8;
      vB.Width := 125;
      vB.Height := 23;
      vB.Caption := 'Break loading';
      vB.OnClick := BreakLoading;
    end;
    vBreakForm.Show;
  end;

begin
  TreeView1.Items.Clear;
  Start := GetCurrentTime;
  Screen.Cursor := crAppStart;
  MakeBreakForm;
  try
    sb3DAxes.Down := False;
    MICloseClick(nil);
    sgPaintBox.LoadFromFile(FileName);
    FFileName := FileName;
    pnlFileName.Caption := UpperCase(ExtractFileName(FileName));
    HelpContext := 3;
    pnlLayouts.Visible := False;
    if Img <> nil then
    begin
      SetImgOpt;
      tbsStructure.TabVisible := True;
      MiOEM.Checked := not Img.Converter.OEM;
      MiOEMClick(nil);
      ViewLayouts;
      speNumPartsCircle.Value := Img.Converter.NumberOfPartsInCircle;
      speNumPartsSpline.Value := Img.Converter.NumberOfPartsInSpline;
    end;
  finally
    if Assigned(vBreakForm) then
      vBreakForm.Close;
    EnableControls;
    prbProgress.Position := 0;
    Screen.Cursor := crDefault;
  end;
end;

procedure TForm1.MIOpenClick(Sender: TObject);
begin
  OpenDialog1.FileName := '';
  {$IFNDEF sgDXFONLY}
  DWGPreview := True;
  {$ENDIF}
  try
    if not OpenDialog1.Execute then Exit;
  finally
  {$IFNDEF sgDXFONLY}
    DWGPreview := False;
  {$ENDIF}
  end;
  MICloseClick(nil);
  Open(OpenDialog1.FileName);
end;

procedure TForm1.MICloseClick(Sender: TObject);
begin
  ListBox1.Clear;
  TreeView1.Items.Clear;
  sgPaintBox.Picture.Graphic := nil;
  sgPaintBox.Color := clBtnFace;
  FFileName := '';
  pnlFileName.Caption := '';
  pnlCoords.Caption := '';
  pnlTime.Caption := '';
  MIClose.Enabled := False;
  MIPrint.Enabled := False;
  MiOEM.Enabled := False;
  BtnSave.Enabled := False;
  pgcDrawing.ActivePage := tbsImage;
  tbsStructure.TabVisible := False;
  prbProgress.Max := 100;
  HelpContext := 1;
  EnableControls;
  cbLayouts.Items.Clear;
  pnlLayouts.Visible := False;
end;

procedure TForm1.MIExitClick(Sender: TObject);
begin
  Close;
end;

procedure TForm1.TreeView1Change(Sender: TObject; Node: TTreeNode);
var
  E: TsgDXFEntity;
  S: String;
begin
  if not Node.Selected then Exit;
  E := TsgDXFEntity(Node.Data);
  if (E=nil) or (E.SrcStart = nil) or (E.SrcEnd = nil)
  then ListBox1.Clear
  else begin
    SetString(S, E.SrcStart, E.SrcEnd - E.SrcStart);
    ListBox1.Items.Text := S;
  end;
end;

procedure TForm1.MiOEMClick(Sender: TObject);
const CS: array[Boolean] of TFontCharset = (DEFAULT_CHARSET, OEM_CHARSET);
begin
  MiOEM.Checked := not MiOEM.Checked;
  if Img=nil then Exit;
  Img.Charset := CS[MiOEM.Checked];
  ListBox1.Font.Charset := Img.Charset;
end;

procedure TForm1.SetNullWidth(AGraphic: TGraphic; AWidth: Integer);
begin
  if AGraphic is TsgDXFImage then
  begin
    FStoredNullWidth := TsgDXFImage(AGraphic).NullWidth;
    TsgDXFImage(AGraphic).NullWidth := AWidth;
  end;
end;

procedure TForm1.RestoreNullWidth(AGraphic: TGraphic);
begin
  if AGraphic is TsgDXFImage then
    TsgDXFImage(AGraphic).NullWidth := FStoredNullWidth;
end;

procedure TForm1.MIPrintClick(Sender: TObject);
const PO: array[Boolean] of TPrinterOrientation = (poPortrait, poLandscape);
var
  W,H: Double;
  PW,PH: Integer;
begin
  Printer.Orientation := PO[sgPaintBox.Picture.Width > sgPaintBox.Picture.Height];
  if PrintDialog1.Execute then
  begin
    SetNullWidth(sgPaintBox.Picture.Graphic, 3);
    W := Printer.PageWidth / sgPaintBox.Picture.Width;
    H := Printer.PageHeight / sgPaintBox.Picture.Height;
    if W > H then W := H;
    PW := Round(W * sgPaintBox.Picture.Width);
    PH := Round(W * sgPaintBox.Picture.Height);
    Printer.BeginDoc;
    Printer.Canvas.StretchDraw(Bounds((Printer.PageWidth-PW) div
      2, (Printer.PageHeight-PH) div 2, PW, PH),
      sgPaintBox.Picture.Graphic);
    Printer.EndDoc;
    RestoreNullWidth(sgPaintBox.Picture.Graphic);
    sgPaintBox.Repaint;
  end;
end;

procedure TForm1.Printer1Click(Sender: TObject);
const PO: array[Boolean] of TPrinterOrientation = (poPortrait, poLandscape);
var
  W,H: Double;
  PW,PH: Integer;
  vGr: TGraphic;
begin
  Printer.Orientation := PO[sgPaintBox.Picture.Width > sgPaintBox.Picture.Height];
  if PrintDialog1.Execute then
  begin
    SetNullWidth(sgPaintBox.Picture.Graphic, 3);
    vGr := TMetafile.Create;
    try
      ActualGraphic(vGr);
      W := Printer.PageWidth / vGr.Width;
      H := Printer.PageHeight / vGr.Height;
      if W > H then W := H;
      PW := Round(W * vGr.Width);
      PH := Round(W * vGr.Height);
      Printer.BeginDoc;
      Printer.Canvas.StretchDraw(Bounds((Printer.PageWidth-PW) div 2,
        (Printer.PageHeight-PH) div 2, PW, PH), vGr);
      Printer.EndDoc;
    finally
      vGr.Free;
    end;
    RestoreNullWidth(sgPaintBox.Picture.Graphic);
    sgPaintBox.Repaint;
  end;
end;

procedure TForm1.Metafile1Click(Sender: TObject);
var
  vGr: TGraphic;
begin
  SavePictureDialog.FilterIndex := 3;
  if sgPaintBox.Empty or not SavePictureDialog.Execute then Exit;
  vGr := TMetafile.Create;
  try
    ActualGraphic(vGr);
    if ExtractFileExt(SavePictureDialog.FileName) = '' then
      vGr.SaveToFile(SavePictureDialog.FileName+'.emf')
    else
      vGr.SaveToFile(SavePictureDialog.FileName);
  finally
    vGr.Free;
  end;
end;

procedure TForm1.BreakLoading(Sender: TObject);
begin
  if Loading <> nil then Loading.StopLoading;
end;

procedure TForm1.ActualGraphic(var vResult: TGraphic);
const
  KfWinNT = 1209;
  MPerInch = 25.1;

var
  vMC: TMetafileCanvas;
  vRect: TRect;
  vRGN: HRGN;
  OSVersionInfo: TOSVersionInfo;
  DC: HDC;
  mmToPixelX, mmToPixelY: Double;
  imgRectangle: TRect;
begin
  imgRectangle := sgPaintBox.ClientRect;

  DC := GetDC(0);
  try
    mmToPixelX := GetDeviceCaps(DC,HORZSIZE) /
      GetDeviceCaps(DC,HORZRES);
    mmToPixelY := GetDeviceCaps(DC,VERTSIZE) /
      GetDeviceCaps(DC,VERTRES);
  finally
    ReleaseDC(Handle, DC);
  end;

  vRect := sgPaintBox.PictureRect;
  vRect.Left := vRect.Left - imgRectangle.Left;
  vRect.Top := vRect.Top - imgRectangle.Top;
  vRect.Right := vRect.Right - imgRectangle.Left;
  vRect.Bottom := vRect.Bottom - imgRectangle.Top;

  OSVersionInfo.dwOSVersionInfoSize := sizeof(TOSVersionInfo);
  GetVersionEx(OSVersionInfo);
  if OSVersionInfo.dwPlatformId = VER_PLATFORM_WIN32_NT then
  begin
    TMetafile(vResult).MMWidth := Round((imgRectangle.Right - imgRectangle.Left) * 1000 * mmToPixelX);
    TMetafile(vResult).MMHeight := Round((imgRectangle.Bottom - imgRectangle.Top) * 1000 * mmToPixelY);
    vRect.Left := vRect.Left * 10;
    vRect.Top := vRect.Top * 10;
    vRect.Right := vRect.Right * 10;
    vRect.Bottom := vRect.Bottom * 10;
  end
  else // win98
  begin
    TMetafile(vResult).MMWidth := Round((imgRectangle.Right - imgRectangle.Left) * 500 * mmToPixelX);
      TMetafile(vResult).MMHeight := Round((imgRectangle.Bottom - imgRectangle.Top) * 500 * mmToPixelY);
      vRect.Left := vRect.Left * 5;
      vRect.Top := vRect.Top * 5;
      vRect.Right := vRect.Right * 5;
      vRect.Bottom := vRect.Bottom * 5;
    end;
    vMC := TMetafileCanvas.Create(TMetafile(vResult), 0);
    try
      if OSVersionInfo.dwPlatformId = VER_PLATFORM_WIN32_NT then
        vRGN := CreateRectRgn(0, 0, (imgRectangle.Right - imgRectangle.Left) * 10, (imgRectangle.Bottom - imgRectangle.Top) * 10)
      else
        vRGN := CreateRectRgn(0, 0, (imgRectangle.Right - imgRectangle.Left) * 5, (imgRectangle.Bottom - imgRectangle.Top) * 5);

      SelectClipRgn(vMC.Handle, vRGN);
      vMC.StretchDraw(vRect, sgPaintBox.Picture.Graphic);
      DeleteObject(vRGN);
    finally
      vMC.Free;
      if Img <> nil then
        Img.IsShowBackground := True;
    end;
end;

procedure TForm1.MIAutoClick(Sender: TObject);
begin
  sgPaintBoxScaling(nil);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  FsgPaintBox := TSGDrawingNavigator.Create(Self);
  FsgPaintBox.Parent := tbsImage;
  FsgPaintBox.AutoFocus := True;
  FsgPaintBox.RectZooming := True;
  FsgPaintBox.OnChangeScale := sgPaintBoxScaling;
  FsgPaintBox.OnPaint := sgPaintBoxPaint;
  FsgPaintBox.OnMouseMove := sgPaintBoxMouseMove;
  FsgPaintBox.OnProgress := sgPaintBoxProgress;
  FsgPaintBox.Align := alClient;
  {$IFDEF SGDEL_4}
  FactForm := TAction.Create(Self);
  FactForm.Caption := 'CADImportVCL Viewer demo';
  FactForm.OnUpdate := actFormUpdate;
  Self.Action := actForm;
  {$ENDIF}
  Application.OnIdle := AppIdle;
  LoadOptions;
  OpenDialog1.Filter := GraphicFilter(TGraphic);
  if ParamCount > 0 then begin
    Open(ParamStr(1));
    OpenDialog1.FileName := ParamStr(1);
  end;
  pnlLayouts.Visible := False;
  sbDrawingBox.Enabled := False;
end;

procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
  if Key = VK_ESCAPE then Close;
  if (pgcDrawing.ActivePage <> tbsImage) or (Shift-[ssCtrl] <> []) then Exit;
  case Key of
    VK_ADD: BtnPlusClick(nil);
    VK_SUBTRACT: BtnMinusClick(nil);
    VK_MULTIPLY:
      if ssCtrl in Shift then
        BtnReal.Click
      else
        btnFitToScreen.Click;
  end;
end;

procedure TForm1.MIPrevClick(Sender: TObject);
begin
  sgPaintBox.CallPreviousView;
end;

procedure TForm1.sgPaintBoxScaling(Sender: TObject);
begin
  MIPrev.Enabled := sgPaintBox.HasPreviousView;
  BtnPrev.Enabled := MIPrev.Enabled;
end;

procedure TForm1.sgPaintBoxProgress(Sender: TObject; Stage: TProgressStage;
  PercentDone: Byte; RedrawNow: Boolean; const R: TRect; const Msg: String);
begin
  if Stage=psStarting then begin
    pnlFileName.Caption := Msg;
    pnlFileName.Update;
  end;
  prbProgress.Position := PercentDone;
  Time;
  if Stage=psEnding then begin
    prbProgress.Position := 0;
    pnlFileName.Caption := UpperCase(ExtractFileName(OpenDialog1.FileName))
  end;
end;

procedure TForm1.BtnPlusClick(Sender: TObject);
begin
  sgPaintBox.AlterScale(2, False, sgPaintBox.Center);
end;

procedure TForm1.BtnMinusClick(Sender: TObject);
begin
  sgPaintBox.AlterScale(0.5, False, sgPaintBox.Center);
end;

procedure TForm1.pgcDrawingChanging(Sender: TObject; var AllowChange: Boolean);
begin
  AllowChange := Img <> nil;
  FocusControl(nil);
end;

procedure TForm1.MIHelpClick(Sender: TObject);
begin
  Application.HelpCommand(HELP_CONTENTS,0);
end;

procedure TForm1.OpenDialog1Show(Sender: TObject);
begin
  MinDXFSize := 140;
end;

procedure TForm1.OpenDialog1Close(Sender: TObject);
begin
  MinDXFSize := 0;
end;

procedure TForm1.BtnSaveClick(Sender: TObject);
var
  E: TsgExport;
  vMC: TMetafileCanvas;
  vM: TMetafile;
  vFileName: string;
  vWidth, vHeight: Integer;
  vRatio: Double;
begin
  if sgPaintBox.Empty or not SavePictureDialog.Execute then Exit;
  vFileName := SavePictureDialog.FileName;
  // Converting CAD-drawing width/height to Screen size for export
  vWidth := sgPaintBox.Picture.Graphic.Width;
  vHeight := sgPaintBox.Picture.Graphic.Height;
  if vHeight <> 0 then
    vRatio := vWidth / vHeight
  else
    vRatio := 1;
  if vRatio <= 1 then
  begin
    vHeight := Screen.Height;
    vWidth := Round(vHeight * vRatio);
  end
  else
  begin
    vWidth := Screen.Width;
    vHeight := Round(vWidth / vRatio);
  end;
  case SavePictureDialog.FilterIndex of
    1:
      if AnsiLowerCase(ExtractFileExt(vFileName)) <> '.bmp' then
        vFileName := vFileName + '.bmp';
    2:
      if (AnsiLowerCase(ExtractFileExt(vFileName)) <> '.jpg')
        or (AnsiLowerCase(ExtractFileExt(vFileName)) <> '.jpeg') then
        vFileName := vFileName + '.jpg';
    3:
      if (AnsiLowerCase(ExtractFileExt(vFileName)) <> '.emf') then
        vFileName := vFileName + '.emf';
    4:
      begin
        vM := TMetafile.Create;
        try
          vM.Width := vWidth;
          vM.Height := vHeight;
          vMC := TMetafileCanvas.Create(vM, 0);
          try
            vMC.StretchDraw(Rect(0, 0, vWidth, vHeight), sgPaintBox.Picture.Graphic);
          finally
            vMC.Free;
          end;
          if AnsiLowerCase(ExtractFileExt(vFileName)) <> '.wmf' then
            vFileName := vFileName + '.wmf';
          vM.SaveToFile(vFileName);
          Exit;
        finally
          vM.Free;
        end;
      end;
    5:
      begin
        if AnsiLowerCase(ExtractFileExt(vFileName)) <> '.dxf' then
          vFileName := vFileName + '.dxf';
        SaveToDXF(vFileName);
        Exit;
      end;
  end;
  E := TsgExport.Create;
  try
    E.ExportTo(sgPaintBox.Picture.Graphic, vFileName,
      TsgExportFormat(SavePictureDialog.FilterIndex-1), vWidth, vHeight);
  finally
    E.Free;
  end;
end;

procedure TForm1.mmiDisabledClick(Sender: TObject);
begin
  if sgPaintBox.Empty or not
    (sgPaintBox.Picture.Graphic is TsgDXFImage) then
    Exit;
  (sgPaintBox.Picture.Graphic as TsgDXFImage).DrawMode := dmGray;
end;

procedure TForm1.mmiBlackClick(Sender: TObject);
begin
  if sgPaintBox.Empty or not
    (sgPaintBox.Picture.Graphic is TsgDXFImage) then
    Exit;
  (sgPaintBox.Picture.Graphic as TsgDXFImage).DrawMode := dmBlack;
end;

procedure TForm1.mmiNormalClick(Sender: TObject);
begin
  if sgPaintBox.Empty or not
    (sgPaintBox.Picture.Graphic is TsgDXFImage) then
    Exit;
  (sgPaintBox.Picture.Graphic as TsgDXFImage).DrawMode := dmNormal;
end;

procedure TForm1.SoftGoldHomePage1Click(Sender: TObject);
begin
  ShellExecute(Handle, 'open', 'www.cadsofttools.com', '', '', SW_SHOW);
end;

procedure TForm1.MIAboutClick(Sender: TObject);
begin
 ShowMessage('DWG/DXF VCLs demo version '+ #13#10 +
             'Please contact www.cadsofttools.com to order a full version');
end;

procedure TForm1.btnLayersClick(Sender: TObject);
begin
  if Img = nil then Exit;
  LayersDialogExecute(Img, sgPaintBox);
end;

procedure TForm1.sgPaintBoxPaint(Sender: TObject);
var
  vLeftTop, vRightBottom: TPoint;
  vExt: TFRect;
  vBMPFrame: TBitmap;
  vImgRect, vPicRect: TRect;
  vPt: TPoint;
begin
  {sgPaintBox.Canvas.Font.Size := 14;
  sgPaintBox.Canvas.Font.Color := clBlack;
  sgPaintBox.Canvas.Font.Name := 'Arial';
  sgPaintBox.Canvas.TextOut(20, 20, 'Custom drawing on Graphic Viewer allowed');}

  if (Assigned(Img)) and (not Img.Empty) then
  begin
    vExt := Img.Extents;
    vPicRect := sgPaintBox.PictureRect;
    if (FSelectionMode = smEllipse) then
    begin
      vLeftTop.X := Round((vPicRect.Right - vPicRect.Left) * (FTextBox.Left - vExt.Left) / (vExt.Right - vExt.Left)) + vPicRect.Left;
      vLeftTop.Y := Round((vPicRect.Bottom - vPicRect.Top) * (1 - (FTextBox.Top - vExt.Bottom) / (vExt.Top - vExt.Bottom))) + vPicRect.Top;
      vRightBottom.X := Round((vPicRect.Right - vPicRect.Left) *  (FTextBox.Right - vExt.Left) / (vExt.Right - vExt.Left)) + vPicRect.Left;
      vRightBottom.Y := Round((vPicRect.Bottom - vPicRect.Top) * (1 - (FTextBox.Bottom - vExt.Bottom) / (vExt.Top - vExt.Bottom))) + vPicRect.Top;
      sgPaintBox.Canvas.Pen.Color := clRed;
      sgPaintBox.Canvas.Brush.Style := bsClear;
      sgPaintBox.Canvas.Ellipse(vLeftTop.X - 10, vLeftTop.Y - 10, vRightBottom.X + 10, vRightBottom.Y + 10);
    end;
    if sbDrid.Down then
    begin
      if CreateLines(Round(Img.AbsWidth*Img.Scale.X/speGridCount.Value),
        Round(Img.AbsWidth*Img.Scale.X),
        Round(Img.AbsHeight*Img.Scale.Y)) then
      begin
        sgPaintBox.Canvas.Pen.Color := clGray;
        OffsetViewportOrgEx(sgPaintBox.Canvas.Handle, vPicRect.Left, vPicRect.Top, vPt);
        DrawPolyPolyLine(sgPaintBox.Canvas.Handle, FIntPoints);
      end;
    end;
    if (sbShowBorder.Enabled) and (sbShowBorder.Down) then
    begin
      vBMPFrame := TBitmap.Create;
      try
        sgPaintBox.Picture.Graphic.Transparent := True;
        vBMPFrame.PixelFormat := pf8bit;
        vBMPFrame.Width := sgPaintBox.Width;
        vBMPFrame.Height := sgPaintBox.Height;
        vBMPFrame.Assign(imgFrame.Picture.Bitmap);

        // draw stretched border bitmap
        sgPaintBox.Canvas.StretchDraw(Rect(0, 0, sgPaintBox.Width, sgPaintBox.Height),
          vBMPFrame);

        FillChar(vImgRect, SizeOf(TRect), #0);
        vImgRect.Left := sgPaintBox.Width div 4;
        vImgRect.Top := sgPaintBox.Height div 4;
        vImgRect.Right := vImgRect.Left + sgPaintBox.Width div 2;
        vImgRect.Bottom := vImgRect.Top + sgPaintBox.Height div 2;
        // draw stretched CAD graphic
        sgPaintBox.Canvas.StretchDraw(vImgRect, Img);
      finally
        vBMPFrame.Free;
      end;
    end;
  end;
end;

procedure TForm1.sgPaintBoxMouseMove(Sender: TObject; Shift: TShiftState;
  X, Y: Integer);
var
  vPt: TFPoint;
  vUnits: string;
begin
  if sgPaintBox.Picture.Graphic is TsgDXFImage then
  begin
    vPt := sgPaintBox.GetDrawingCoords(X, Y, vUnits);
    pnlCoords.Caption := Format('%.3f; %.3f; %.3f (%s)', [vPt.X, vPt.Y, vPt.Z, vUnits]);
  end;
end;

procedure TForm1.BtnPrint1Click(Sender: TObject);
const
  PO: array[Boolean] of TPrinterOrientation = (poPortrait,poLandscape);
  koef = 25.4;
  ScaleFactor = 0.5;
var
  PxlsX, PxlsY: Double;
  W, H: Integer;
begin
  Printer.Orientation := PO[sgPaintBox.Picture.Graphic.Width >
    sgPaintBox.Picture.Graphic.Height];
  if PrintDialog1.Execute then
  begin
    SetNullWidth(sgPaintBox.Picture.Graphic, 3);
    W := sgPaintBox.Picture.Graphic.Width;
    H := sgPaintBox.Picture.Graphic.Height;
    PxlsX := 1;
    PxlsY := 1;
    if sgPaintBox.Picture.Graphic is TsgDXFImage then
    begin
      PxlsX := GetDeviceCaps(Printer.Handle, LOGPIXELSX);
      PxlsY := GetDeviceCaps(Printer.Handle, LOGPIXELSY);
      if Img.Millimetres then
      begin
        PxlsX := PxlsX / koef;
        PxlsY := PxlsY / koef;
      end;
    end;
    Printer.Title := 'CAD Image VCL printing 1:1';
    Printer.BeginDoc;
    Printer.Canvas.StretchDraw(Rect(0, 0, Round(PxlsX * W * ScaleFactor),
                               Round(PxlsY * H * ScaleFactor)),
      sgPaintBox.Picture.Graphic);
    Printer.EndDoc;
    RestoreNullWidth(sgPaintBox.Picture.Graphic);
    sgPaintBox.Repaint;
  end;
end;

procedure TForm1.btnFitToScreenClick(Sender: TObject);
begin
  sgPaintBox.FitToSize;
  sgPaintBoxScaling(Self);
end;

procedure TForm1.btnIsWithoutBorderClick(Sender: TObject);
begin
  if sgPaintBox.Empty or not ( sgPaintBox.Picture.Graphic is TsgDXFImage ) then Exit;
  Img.IsWithoutBorder := not Img.IsWithoutBorder;
end;

procedure TForm1.btnShowLineWeightClick(Sender: TObject);
begin
  Img.IsShowLineWeight := btnShowLineWeight.Down;
end;

procedure TForm1.btnSplittedArcClick(Sender: TObject);
begin
  Img.UseWinEllipse := not btnSplittedArc.Down;
end;

procedure TForm1.btnDrawAllColorClick(Sender: TObject);
begin
  if btnDrawAllColor.Down then
    Img.DrawMode := dmNormal
  else
    Img.DrawMode := dmBlack;
end;

procedure TForm1.SetImgOpt;
begin
  btnShowLineWeightClick(nil);
  btnSplittedArcClick(nil);
  btnDrawAllColorClick(nil);
  btnWhiteBackgroundClick(nil);
end;

procedure TForm1.btnWhiteBackgroundClick(Sender: TObject);
begin
  if btnWhiteBackground.Down then
  begin
    Img.BackgroundColor := clWhite;
    Img.DefaultColor := clBlack;
  end
  else
  begin
    Img.BackgroundColor := clBlack;
    Img.DefaultColor := clWhite;
  end;
  sgPaintBox.Color := Img.BackgroundColor;
end;

procedure TForm1.sb3DAxesClick(Sender: TObject);
begin
  sb3DAxes.Down := sb3DAxes.Down or False;
  if sb3DAxes.Down then
    Img.IsDraw3DAxes := True
  else
    Img.IsDraw3DAxes := False;
  sgPaintBox.Invalidate;
end;


procedure TForm1.sb3DOrbitClick(Sender: TObject);
begin
  sb3DOrbit.Down := sb3DOrbit.Down or False;
  sgPaintBox.Orbit3D.Visible := sb3DOrbit.Down;
  sgPaintBox.Invalidate;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  FOptions.Free;
  FIntPoints.Free;
end;

procedure TForm1.BtnPrint2Click(Sender: TObject);
var
  P: TPoint;
begin
  Win32Check(Windows.GetCursorPos(P));
  PopupMenu1.Popup(P.X, P.Y);
end;

procedure TForm1.mmiSaveAsBigEMFClick(Sender: TObject);
var
  {$IFDEF SGDEL_4}
  vM: TMetafile;
  {$ENDIF}
  vCAD: TsgDXFImage;
begin
  if sgPaintBox.Empty or not (sgPaintBox.Picture.Graphic is TsgDXFImage) then Exit;
  SavePictureDialogEMF.FileName := '*.emf';
  if not SavePictureDialogEMF.Execute then Exit;
  if LowerCase(ExtractFileExt(SavePictureDialogEMF.FileName)) <> '.emf' then
    SavePictureDialogEMF.FileName := ChangeFileExt(SavePictureDialogEMF.FileName, '.emf');
  vCAD := Img;
  {$IFNDEF SGDEL_4}
  vCAD.ExportToMetafile(SavePictureDialogEMF.FileName,
    3276700, Round(3276700 * vCAD.AbsHeight / vCAD.AbsWidth));
  {$ELSE}
  vM := vCAD.ExportToMetafile(3276700);
  try
    vM.SaveToFile(SavePictureDialogEMF.FileName);
  finally
    vM.Free;
  end;
  {$ENDIF}
end;

procedure TForm1.ViewLayouts;
var
  I: Integer;
begin
  if Img <> nil then
  begin
    cbLayouts.Items.Clear;
    for I := 0 to Img.LayoutsCount - 1 do
      cbLayouts.Items.AddObject(Img.Layouts[I].Name, Img.Layouts[I]);
    cbLayouts.ItemIndex := Img.Converter.DefaultLayoutIndex;
    Img.CurrentLayout := Img.Layouts[cbLayouts.ItemIndex];
    pnlLayouts.Visible := True;
    Enable3DAxes(Img.CurrentLayout.CADSpace <> csUndefined);
    Enable3DOrbit(Img.CurrentLayout.CADSpace <> csUndefined);
  end;
end;

procedure TForm1.Enable3DAxes(AIsEnabled: Boolean);
begin
  sb3DAxes.Down := False;
  sb3DAxes.Enabled := AIsEnabled;
  if AIsEnabled = False then
    Img.IsDraw3DAxes := AIsEnabled;
end;

procedure TForm1.Enable3DOrbit(AIsEnabled: Boolean);
begin
  sb3DOrbit.Down := False;
  sb3DOrbit.Enabled := AIsEnabled;
end;

procedure TForm1.cbLayoutsChange(Sender: TObject);
begin
  if cbLayouts.Items.Objects[cbLayouts.ItemIndex] <> nil then
  begin
    Img.CurrentLayout := Img.Layouts[cbLayouts.ItemIndex];
    sbDrawingBoxClick(nil);
    Enable3DAxes(Img.CurrentLayout.CADSpace <> csUndefined);
    Enable3DOrbit(Img.CurrentLayout.CADSpace <> csUndefined);
  end;
end;

procedure TForm1.pgcDrawingChange(Sender: TObject);
begin
  if TreeView1.Items.Count = 0 then
    LoadStructure;
end;

procedure TForm1.speNumPartsCircleChange(Sender: TObject);
var
  Val: Integer;
begin
  if TSpinEdit(Sender).Text = '' then Exit;
  try
    Val := speNumPartsCircle.Value;
  except
    speNumPartsCircle.Value := iDefaultNumberOfCircleParts;
    Val := iDefaultNumberOfCircleParts;
  end;
  if (Val >= 2) then
  begin
    Img.Converter.NumberOfPartsInCircle := Val;
    sgPaintBox.Invalidate;
  end
  else
    speNumPartsCircle.Value := 2;
end;

procedure TForm1.speNumPartsSplineChange(Sender: TObject);
var
  Val: Integer;
begin
  if TSpinEdit(Sender).Text = '' then Exit;
  try
    Val := speNumPartsSpline.Value;
  except
    speNumPartsSpline.Value := iDefaultNumberOfSplineParts;
    Exit;
  end;
  if (Val >= 2) then
  begin
    Img.Converter.NumberOfPartsInSpline := Val;
    sgPaintBox.Invalidate;
  end
  else
    speNumPartsSpline.Value := 2;
end;

procedure TForm1.mmiShowpointClick(Sender: TObject);
var
  Form2: TForm2;
begin
  Form2 := TForm2.Create(Self);
  try
    Form2.ShowModal;
  finally
    Form2.Free;
  end;
end;

procedure TForm1.mmiFindtextClick(Sender: TObject);
var
  Form3: TForm3;
begin
  Form3 := TForm3.Create(Self);
  try
    Form3.ShowModal;
  finally
    Form3.Free;
  end;
end;

procedure TForm1.mmiReopenSameViewClick(Sender: TObject);
var
  vFPoint: TFPoint;
  vRect: TRect;
  vScale: Extended;
  vLayoutName, vUnits, vFileName: String;
  I: Integer;
begin
  if Img <> nil then
  begin
    vLayoutName := Img.CurrentLayout.Name;
    vRect := sgPaintBox.ClientRect;
    vFPoint := sgPaintBox.GetDrawingCoords((vRect.Left + vRect.Right) div 2,
      (vRect.Top + vRect.Bottom) div 2, vUnits);
    vScale := sgPaintBox.Scale;
    vFileName := FFileName;
    MICloseClick(Self);
    Open(vFileName);
    for I := 0 to Img.LayoutsCount - 1 do
      if Img.Layouts[I].Name = vLayoutName then
        Img.CurrentLayout := Img.Layouts[I];
    sgPaintBox.ShowPoint(vFPoint, vScale);
  end
  else
    ShowMessage('It is not CAD file. This operation does not work.');
end;

procedure TForm1.miFontsClick(Sender: TObject);
begin
  if FontsOptionsExecute(FOptions, Form1) and (FFileName<>'') then
    Open(FFileName)
  else
    sgPaintBox.Invalidate;
end;

procedure TForm1.speGridCountChange(Sender: TObject);
begin
  sgPaintBox.Picture.Graphic.Transparent := not sbDrid.Down;
  sgPaintBox.Invalidate;
end;

procedure TForm1.sbDridClick(Sender: TObject);
begin
  speGridCountChange(nil);
end;

procedure TForm1.sbDrawingBoxClick(Sender: TObject);
begin
  if Img = nil then Exit;
  sbDrawingBox.Down := sbDrawingBox.Down or False;
  Enable3DOrbit(not sbDrawingBox.Down);
  if sbDrawingBox.Down then
    Img.DrawingBox := MakeFRect((Img.CurrentLayout.Box.Left + Img.CurrentLayout.Box.Right) / 2,
      Img.CurrentLayout.Box.Top, Img.CurrentLayout.Box.Z1, Img.CurrentLayout.Box.Right, Img.CurrentLayout.Box.Bottom, Img.CurrentLayout.Box.Z2)
  else
    Img.ResetDrawingBox;
end;

procedure TForm1.mmiReopenSWIsometricClick(Sender: TObject);
var
  vLayoutName, vFileName: String;
  I: Integer;
begin
  if sgPaintBox.Picture.Graphic is TsgDXFImage then
  begin
    vLayoutName := Img.CurrentLayout.Name;
    if FFileName = '' then Exit;
    vFileName := FFileName;
    MICloseClick(Self);
    Open(vFileName);
    for I := 0 to Img.LayoutsCount - 1 do
      if Img.Layouts[I].Name = vLayoutName then
        Img.CurrentLayout := Img.Layouts[I];
    //if TsgDXFImage(sgPaintBox.Picture.Graphic).CurrentLayout.IsModel then
    if Img.CurrentLayout.CADSpace = cs3D then
    begin
      Img.RotToView(vdTop);
      Img.Rotate(AxisZ, 45);
      Img.Rotate(AxisX, -54.735610317245345684622999669981);
    end
    else
      ShowMessage('The current layout of this file is not model. This operation does not work.');
  end
  else
    ShowMessage('It is not CAD file. This operation does not work.');
  sgPaintBox.Refresh;
end;

procedure TForm1.sbShowBorderClick(Sender: TObject);
begin
  if sbShowBorder.Down then
  begin
    if OpenBorder.Execute then
    begin
      imgFrame.Picture.LoadFromFile(OpenBorder.FileName);
      sb3DOrbit.Enabled := False;
      sb3DAxes.Enabled := False;
    end
    else
    begin
      sbShowBorder.Down := False;
      sb3DOrbit.Enabled := True;
      sb3DAxes.Enabled := True;
      sgPaintBox.Picture.Graphic.Transparent := False;
    end;
  end
  else
  begin
    if not imgFrame.Picture.Bitmap.Empty then
      imgFrame.Picture.Graphic := nil;
    sgPaintBox.Picture.Graphic.Transparent := False;
    sb3DOrbit.Enabled := True;
    sb3DAxes.Enabled := True;
  end;
  sgPaintBox.Invalidate;
end;


procedure TForm1.mmiObjectSnapAllClick(Sender: TObject);
begin
  {$IFDEF SGDEL_4}
  mmiObjectSnapAll.Checked := not mmiObjectSnapAll.Checked;
  //Object Snap. Snap mode setup
  if mmiObjectSnapAll.Checked then
    sgPaintBox.SnapControl.SnapMode := osAll
  else
    sgPaintBox.SnapControl.SnapMode := osNone;
  {$ENDIF}
end;


{ TForm1.SaveToDXF

  Saving in DXF format.                      }
procedure TForm1.SaveToDXF(AFileName: string);
var
  vExpMetafile: TsgDXFExport;
  vExpCADfile: TsgCADtoDXF;
  vGr: TGraphic;
begin
  vGr := sgPaintBox.Picture.Graphic;
  if (vGr is TsgDXFImage) or (vGr is TMetafile) then
  begin
    if not (vGr is TsgDXFImage) then
    begin
      vExpMetafile := TsgDXFExport.Create;
      try
        vExpMetafile.Canvas.StretchDraw(Rect(0, 0, vGr.Width, vGr.Height), vGr);
        vExpMetafile.EndDraw;
        vExpMetafile.SaveToFile(AFileName);
      finally
        vExpMetafile.Free;
      end;
    end
    else
    begin
      vExpCADfile := TsgCADtoDXF.Create(TsgDXFImage(vGr));
      try
        vExpCADfile.SaveToFile(AFileName);
      finally
        vExpCADfile.Free;
      end;
    end;
    MessageBox(Application.Handle, PChar('DXF Export is made via DXF Export VCL software which is not part of CAD Import VCL and should be bought additionally if needed.'), 'WARNING', MB_ICONWARNING);
  end
  else
    ShowMessage(sNotVectorial);
end;


function TForm1.GetImg: TsgDXFImage;
begin
  Result := nil;
  if sgPaintBox.Picture.Graphic is TsgDXFImage then
    Result := TsgDXFImage(sgPaintBox.Picture.Graphic);
end;

procedure TForm1.actFormUpdate(Sender: TObject);
var
  vCADFlag: Boolean;
begin
  vCADFlag := Assigned(Img);
  BtnPrev.Enabled := FsgPaintBox.HasPreviousView and not FsgPaintBox.Empty;
  btnLayers.Enabled := vCADFlag;
  sb3DOrbit.Enabled := vCADFlag and Img.CurrentLayout.IsModel;
  sb3DAxes.Enabled := vCADFlag;
  sbDrawingBox.Enabled := vCADFlag;
  EnableControls;
end;

{$IFNDEF SGDEL_4}
procedure TForm1.UpdateActions;
var
  I: Integer;

  procedure TraverseClients(Container: TWinControl);
  var
    I: Integer;
    Control: TControl;
  begin
    if Container.Showing then
      for I := 0 to Container.ControlCount - 1 do
      begin
        Control := Container.Controls[I];
        if Control.Visible then
            Control.Update;
        if Control is TWinControl then
          TraverseClients(TWinControl(Control));
      end;
  end;

begin
  if (csDesigning in ComponentState) or not Showing then Exit;
  { Update form }
  Update;
  { Update main menu's top-most items }
  if Menu <> nil then
    for I := 0 to Menu.Items.Count - 1 do
        if Menu.Items[I].Visible then Update;
  { Update any controls }
  TraverseClients(Self);
  actFormUpdate(nil);
end;

procedure TForm1.DoActionIdle;
var
  I: Integer;
begin
  for I := 0 to Screen.CustomFormCount - 1 do
    if Screen.CustomForms[I].HandleAllocated and
       IsWindowVisible(Screen.CustomForms[I].Handle) and
       IsWindowEnabled(Screen.CustomForms[I].Handle) then
      UpdateActions;
end;
{$ENDIF}

procedure TForm1.WndProc(var Message: TMessage);
begin
  inherited;
  {$IFNDEF SGDEL_4}
  DoActionIdle;
  {$ENDIF}
end;

procedure TForm1.AppIdle(Sender: TObject; var Done: Boolean);
begin
  {$IFNDEF SGDEL_4}
  DoActionIdle;
  {$ENDIF}
end;

procedure TForm1.BtnRealClick(Sender: TObject);
begin
  sgPaintBox.Scale := 1.0;
  BtnReal.Enabled := False;
end;

procedure TForm1.mmiScaleClick(Sender: TObject);
begin
  sgPaintBox.Scale := TComponent(Sender).Tag / 100.0;
end;

end.
