unit U_PEAutoTraceDialog;

interface

uses
  Windows,  Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, RzPanel, RzRadGrp, RzButton, RzRadChk, exgrid,
  RapTree, FlytreePro, StdCtrls, RzLabel, RzSplit,
  U_SCSComponent, U_SCSLists, Mask, RzEdit, RzSpnEdt, Buttons, siComp,
  siLngLnk, DrawObjects, ComCtrls;

type

  TF_PEAutotraceDialog = class(TForm)
    TypeAutotrace_RadioGroup: TRzRadioGroup;
    Panel1: TPanel;
    bOk: TRzBitBtn;
    bCancel: TRzBitBtn;
    Panel2: TPanel;
    RzSplitter1: TRzSplitter;
    tvEndObject: TFlyTreeViewPro;
    tvWorkObject: TFlyTreeViewPro;
    RzPanel1: TRzPanel;
    RzLabel1: TRzLabel;
    RzPanel2: TRzPanel;
    RzLabel2: TRzLabel;
    PutBox_Check: TRzCheckBox;
    RzPanel3: TRzPanel;
    GetBox_Edit: TRzEdit;
    Label1: TLabel;
    AKolTrace_Edit: TRzSpinEdit;
    TraceFromSwitch_CheckBox: TRzCheckBox;
    GetBox_btn: TSpeedButton;
    lng_Forms: TsiLangLinked;
    AutotraceKind: TRzRadioGroup;
    TypeConnection: TRzRadioGroup;
    DoNotUseUpDown: TRzCheckBox;
    CheckPassedTraces: TRzCheckBox;
    CheckCanConnectCable: TRzCheckBox;
    IgnoreExistingCable: TRzCheckBox;
    SpeedButton5: TSpeedButton;
    SpeedButton3: TSpeedButton;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure bOkClick(Sender: TObject);
    procedure bCancelClick(Sender: TObject);
    procedure GetBox_btnClick(Sender: TObject);
    procedure PutBox_CheckClick(Sender: TObject);
    procedure AKolTrace_EditChange(Sender: TObject);
    procedure tvEndObjectDeletion(Sender: TObject; Node: TFlyNode);
    procedure AutotraceKindChanging(Sender: TObject; NewIndex: Integer;
      var AllowChange: Boolean);
    procedure TypeConnectionChanging(Sender: TObject; NewIndex: Integer;
      var AllowChange: Boolean);
    procedure TypeAutotrace_RadioGroupChanging(Sender: TObject;
      NewIndex: Integer; var AllowChange: Boolean);
    procedure FormShow(Sender: TObject);
    procedure IgnoreExistingCableClick(Sender: TObject);

    procedure tvEndObjectStateChange(Node: TFlyNode; Oldindex: Integer);
    procedure tvWorkObjectStateChange(Node: TFlyNode; Oldindex: Integer);
    procedure SpeedButton2Click(Sender: TObject);
    procedure SpeedButton1Click(Sender: TObject);
    procedure btCanComplectClick1(Sender: TObject);
    procedure SpeedButton5Click(Sender: TObject);
    procedure SpeedButton3Click(Sender: TObject);
  private
    { Private declarations }
    FKolTrace: Integer;
    LampParentNode, SwitchParentNode: TFlyNode;
    procedure ExportResultInLists;
  public
    { Public declarations }
    ListEndCompon, ListWorkCompon: TIntList;
    RaspredBox: TSCSComponent;
    FromAutoTraceDialog: Boolean;
    ListLampCompon, ListSwitchesCompon: TIntList;
    //Tolik
    ShowBadCableConnect: Boolean;
    currTreeNode: TFlyNode;
    NewRaspredBox: Boolean;
    Cypher: String;
    LastAddedCableIDList: TIntList;
    RaspredBoxConnectorList: TList;
    RaspredBoxList: TSCSComponents;
    property KolTrace: integer read FKolTrace;

    procedure BuildTree(Atree: TFlyTreeViewPro; ListFolder: TStringList; ListObject: Tlist; AIndLamp: integer = -1; AIndSwitch: integer = -1 );
    procedure CopyEndListToSwitchesList;
    Procedure DeleteDoublesfromWorkTree; // Tolik  26/03/2021 --
    Procedure DeselectConnected;

  end;

var
  F_PEAutoTraceDialog: TF_PEAutotraceDialog;

  // function AddChild(ATree: TFlyTreeViewPro; AParentNode:TFlyNode; AChildComplects: TSCSComponents): TFlyNode;
  // Function AddNode (ATree: TFlyTreeViewPro; ACurrNode: TFlyNode; ACompon: TSCSComponent; AString: string = ''): TFlyNode;

implementation
 uses  U_main, Treecoll, U_PECommon, U_PEGetBox, u_BaseCommon, U_BaseConstants,
       U_Common, U_Cad, PowerCad, U_ESCadClasess,
       U_SCSEngineTest, U_Constants, {Tolik -- 18/01/2017 -- }U_AnswerToQuast;
{$R *.dfm}


// построение дерева согласно списков
 procedure TF_PEAutotraceDialog.BuildTree(Atree: TFlyTreeViewPro; ListFolder: TStringList;
                                  ListObject: Tlist; AIndLamp: integer = -1; AIndSwitch: integer = -1);
var
  currNode,RememberNode: TFlyNode;
  currCompon: TSCSComponent;
  i, j: integer;
begin
  currNode := nil;
  RememberNode := nil;
  Try
    if aTree.Items.Count > 0 then // Tolik 03/04/2021 --
      ATree.Items.Clear;
    if ListFolder.Count > 0 then
    begin
      For i := 0 to ListFolder.Count -1 do
      begin
        RememberNode := nil;
        currNode := Nil;
        currNode := AddNode(Atree, currNode, nil, ListFolder[i]);
        if i = AIndLamp then
        begin
          LampParentNode := currNode;
        end;
        if i = AIndSwitch then
        begin
          SwitchParentNode := currNode;
        end;

        if ListObject.Count > 0 then // Tolik 03/04/2021 --
        begin
          for j := 0 to TList(ListObject[i]).Count - 1 do
          begin
            currCompon := TscsComponent(TList(ListObject[i]).Items[j]);
            currNode := AddNode(Atree, currNode, currCompon);
          end;
        end;
        if currNode <> nil then // Tolik 03/04/2021 --
        begin
          Atree.NodeStateRefreshParent(currNode, false);
          currNode := Atree.Items[i];
          Atree.NodeStateRefreshParent(currNode, false);
        end;
      end;
      if currNode <> nil then    // Tolik 03/04/2021 --
        i := currNode.StateIndex;
    end;
  Except
    on E: Exception do addExceptionToLogEx('TF_PEAutotraceDialog.BuildTree', E.Message);
  End;
end;

procedure TF_PEAutotraceDialog.ExportResultInLists;

  procedure PutResultsFromTreeInList(ATree : TFlyTreeViewPro; Alist: TintList);
  var
    i: integer;
    CurrNode, ChildNode: TFlyNode;


      procedure AddToSwitchListNode(ANode: TFlyNode);
      var
        i: integer;
      begin
        if ANode.StateIndex = 2 then
        begin
          If TNodeData(ANode.Data).ID = -1 then
            for i := 0 to ANode.Count - 1 do
            begin
              ListSwitchesCompon.Add(TNodeData(ANode.Items[i].Data).ID);
            end
          else
            ListSwitchesCompon.Add(TNodeData(ANode.Data).ID);
        end;
        //if CurrNode.StateIndex > 2 then
        if ANode.StateIndex > 2 then
        begin
          for i := 0 to ANode.Count - 1 do
          begin
            AddToSwitchListNode(ANode.Item[i]);
          end;
        end;
      end;

      procedure AddToLampListNode(ANode: TFlyNode);
      var
        i: integer;
      begin
        if ANode.StateIndex = 2 then
        begin
          If TNodeData(ANode.Data).ID = -1 then
            for i := 0 to ANode.Count - 1 do
            begin
              ListLampCompon.Add(TNodeData(ANode.Items[i].Data).ID);
            end
          else
            ListLampCompon.Add(TNodeData(ANode.Data).ID);
        end;
        //if CurrNode.StateIndex > 2 then
        if ANode.StateIndex > 2 then
        begin
          for i := 0 to ANode.Count - 1 do
          begin
            AddToLampListNode(ANode.Item[i]);
          end;
        end;
      end;

      procedure AddToListNode(ANode: TFlyNode);
      var
        i: integer;
      begin
        //Tolik
        // тут надо бы так, чтобы и чилды выбранного узла попали в список
        if ANode.StateIndex = 2 then
        begin
          // Tolik -- и нах категория в списке компонент? не совсем понятно (совсем непонятно)
          //if AList.IndexOf(TNodeData(ANode.Data).ID) = -1 then
          if (TNodeData(ANode.Data).ID <> -1) and (AList.IndexOf(TNodeData(ANode.Data).ID) = -1) then
            Alist.Add(TNodeData(ANode.Data).ID);
          //  

          // Tolik 20/11/2015
          //if ANode.Expanded then
          if (ANode.Expanded or (TNodeData(ANode.Data).ID = -1)) then // нужно выбрать компоненты из категории, если она чекнута,
                                                                      // но свернута
          //
          begin
            for i := 0 to ANode.Count - 1 do
            begin
              if TFlyNode(ANode.Item[i]).StateIndex = 2 then
              begin
                Alist.Add(TNodeData(ANode.Items[i].Data).ID);
                AddToListNode(TFlyNode(ANode.Item[i]));
              end;
            end;
          end;
        end;
        {
        if ANode.StateIndex = 2 then
        begin
          If TNodeData(ANode.Data).ID = -1 then
            for i := 0 to ANode.Count - 1 do
            begin
              Alist.Add(TNodeData(ANode.Items[i].Data).ID);
            end
          else
            Alist.Add(TNodeData(ANode.Data).ID);
        end;
        }
        //if CurrNode.StateIndex > 2 then
        if ANode.StateIndex > 2 then
        begin
          for i := 0 to ANode.Count - 1 do
          begin
            AddToListNode(TFlyNode(ANode.Item[i]));
          end;
        end;
      end;


  begin
    CurrNode := ATree.GetFirstVisibleNode;
    while CurrNode <> Nil do
    begin
      if CurrNode = LampParentNode then
      begin
        AddToLampListNode(CurrNode);
      end
      else
        if  CurrNode = SwitchParentNode then
        begin
          AddToSwitchListNode(CurrNode);
        end
          else
          begin
            AddToListNode(CurrNode);
          end;
      CurrNode := CurrNode.GetNextSibling;
    end;
  end;

  procedure PutResultsFromTreeInWorkList(ATree : TFlyTreeViewPro; Alist: TintList);
  var
    i: integer;
    CurrNode, ChildNode: TFlyNode;


      procedure AddToSwitchListNode(ANode: TFlyNode);
      var
        i: integer;
      begin
        if ANode.StateIndex = 2 then
        begin
          If TNodeData(ANode.Data).ID = -1 then
            for i := 0 to ANode.Count - 1 do
            begin
              ListSwitchesCompon.Add(TNodeData(ANode.Items[i].Data).ID);
            end
          else
            ListSwitchesCompon.Add(TNodeData(ANode.Data).ID);
        end;
        //if CurrNode.StateIndex > 2 then
        if ANode.StateIndex > 2 then
        begin
          for i := 0 to ANode.Count - 1 do
          begin
            AddToSwitchListNode(ANode.Item[i]);
          end;
        end;
      end;

      procedure AddToLampListNode(ANode: TFlyNode);
      var
        i: integer;
      begin
        if ANode.StateIndex = 2 then
        begin
          If TNodeData(ANode.Data).ID = -1 then
            for i := 0 to ANode.Count - 1 do
            begin
              ListLampCompon.Add(TNodeData(ANode.Items[i].Data).ID);
            end
          else
            ListLampCompon.Add(TNodeData(ANode.Data).ID);
        end;
        //if CurrNode.StateIndex > 2 then
        if ANode.StateIndex > 2 then
        begin
          for i := 0 to ANode.Count - 1 do
          begin
            AddToLampListNode(ANode.Item[i]);
          end;
        end;
      end;

      procedure AddToListNode(ANode: TFlyNode);
      var
        i: integer;
      begin
        //Tolik
        // тут надо бы так, чтобы и чилды выбранного узла попали в список
        if ANode.StateIndex = 2 then
        begin
         // if AList.IndexOf(TNodeData(ANode.Data).ID) = -1 then
         // Tolik -- 20/11/2015 -- нех категории в списки компонентов совать
          if (AList.IndexOf(TNodeData(ANode.Data).ID) = -1) and (ANode.Expanded = False) and
             (TNodeData(ANode.Data).ID <> -1) then
          //
            Alist.Add(TNodeData(ANode.Data).ID);
          // Tolik
          //if ANode.Expanded then
          if ANode.Expanded or (TNodeData(ANode.Data).ID = -1)  then // выгрести компоненты и из выбранной свернутой категории
          //
          begin
            for i := 0 to ANode.Count - 1 do
            begin
              if TFlyNode(ANode.Item[i]).StateIndex = 2 then
              begin
                //Tolik
                // Если компонент развернут - его в список не добавляем и подключать не будем
                // а подключаем только его выбранных чилдов
                // Если компонент свернут - его подключаем, чилдов во внимание не берем
                if TFlyNode(ANode.Item[i]).Expanded then
                  AddToListNode(TFlyNode(ANode.Item[i]))
                else
                  Alist.Add(TNodeData(ANode.Items[i].Data).ID);
               // Alist.Add(TNodeData(ANode.Items[i].Data).ID);
               // AddToListNode(TFlyNode(ANode.Item[i]));
               //
              end;
            end;
          end
          {else
          if ANode.StateIndex = 2 then
          begin
            If TNodeData(ANode.Data).ID = -1 then
              for i := 0 to ANode.Count - 1 do
              begin
                Alist.Add(TNodeData(ANode.Items[i].Data).ID);
              end
            else
              Alist.Add(TNodeData(ANode.Data).ID);
          end;}
        end;

        //if CurrNode.StateIndex > 2 then
        if ANode.StateIndex > 2 then
        begin
          for i := 0 to ANode.Count - 1 do
          begin
            AddToListNode(TFlyNode(ANode.Item[i]));
          end;
        end;
      end;


  begin
    CurrNode := ATree.GetFirstVisibleNode;
    while CurrNode <> Nil do
    begin
      if CurrNode = LampParentNode then
      begin
        AddToLampListNode(CurrNode);
      end
      else
        if  CurrNode = SwitchParentNode then
        begin
          AddToSwitchListNode(CurrNode);
        end
          else
          begin
            AddToListNode(CurrNode);
          end;
      CurrNode := CurrNode.GetNextSibling;
    end;
  end;


begin
  if ListEndCompon <> Nil then
    ListEndCompon.Clear
  else
    ListEndCompon := TIntList.Create;
  if ListWorkCompon <> Nil then
    ListWorkCompon.Clear
  else
    ListWorkCompon := TIntList.Create;
  if ListLampCompon <> Nil then
    ListLampCompon.Clear
  else
    ListLampCompon := TIntList.Create;
  if ListSwitchesCompon <> Nil then
    ListSwitchesCompon.Clear
  else
    ListSwitchesCompon := TIntList.Create;
  //Tolik
  tvEndObject.Refresh;
  tvWorkObject.Refresh;
  //


  PutResultsFromTreeInList(tvEndObject, ListEndCompon);
  PutResultsFromTreeInWorkList(tvWorkObject, ListWorkCompon);
end;

procedure TF_PEAutotraceDialog.FormCreate(Sender: TObject);
begin
  // Tolik 01/11/2019 --
  AKolTrace_Edit.Min := 3;
  AKolTrace_Edit.Max := 9;
  //
  FromAutoTraceDialog := false;
  ListEndCompon := Nil;
  ListWorkCompon := Nil;
  LampParentNode := Nil;
  SwitchParentNode := Nil;
  RaspredBox := Nil;
  ListLampCompon := Nil;
  ListSwitchesCompon := Nil;
  currTreeNode := nil;
end;

procedure TF_PEAutotraceDialog.FormDestroy(Sender: TObject);
begin
  if ListEndCompon <> Nil then
    ListEndCompon.Free;
  if ListWorkCompon = Nil then
    ListEndCompon.Free;
  tvEndObject.Items.Clear;
  tvWorkObject.Items.Clear;  
end;

procedure TF_PEAutotraceDialog.bOkClick(Sender: TObject);
begin
  ShowBadCableConnect := False;
  NewRaspredBox := False;
  Cypher :='';
  LastAddedCableIDList := TIntList.Create;
  RaspredBoxConnectorList := TList.Create;
  RaspredBoxList := TSCSComponents.Create(False);
  if PutBox_Check.Checked and (Not Assigned(RaspredBox)) then
    MessageModal(cPEMes16, cPEMes15, MB_ICONWARNING)
  else
  begin
    F_PEAutotraceDialog.FKolTrace := StrToInt(F_PEAutotraceDialog.AKolTrace_Edit.Text);
    FromAutoTraceDialog := true;
    ExportResultInLists;
    ModalResult := mrOk;
  end;
end;

procedure TF_PEAutotraceDialog.bCancelClick(Sender: TObject);
begin
  ModalResult := mrCancel;
end;

procedure TF_PEAutotraceDialog.GetBox_btnClick(Sender: TObject);
begin
  if GetBox_btn.tag = 0 then
  begin
    GetBox_btn.tag := 1;
    //запуск окна выбора разветвительной коробки
    F_PEGetBox.SetNBToForm;
    if F_PEGetBox.ShowModal = mrOk then
    begin
      if Assigned(RaspredBox) then
      begin
        RaspredBox.Free;
      end;
      RaspredBox := F_PEGetBox.GetCompon;
      GetBox_Edit.Text := RaspredBox.Name;
    end
    else
      PutBox_Check.Checked := false;
    GetBox_btn.tag := 0;
  end;
end;

procedure TF_PEAutotraceDialog.PutBox_CheckClick(Sender: TObject);
begin
  if PutBox_Check.Checked then
  begin
    RzPanel3.Enabled := true;
    if not Assigned(RaspredBox)then
      F_PEAutotraceDialog.GetBox_btnClick(Sender);
  end
  else
  begin
     RzPanel3.Enabled := false;
  end;
end;

procedure TF_PEAutotraceDialog.AKolTrace_EditChange(Sender: TObject);
var
  len: integer;
begin
  len := length(AKolTrace_Edit.EditText);
  if len > 1 then
  begin
    AKolTrace_Edit.EditText := AKolTrace_Edit.EditText[len];
  end;
end;

procedure TF_PEAutotraceDialog.tvEndObjectDeletion(Sender: TObject;
  Node: TFlyNode);
begin
  if Assigned(Node.Data) then
     FreeMemory(Node.Data);
end;

procedure TF_PEAutotraceDialog.CopyEndListToSwitchesList;
var
  i: integer;
begin
  for i := 0 to F_PEAutotraceDialog.ListEndCompon.count -1 do
  begin
    F_PEAutotraceDialog.ListSwitchesCompon.add(F_PEAutotraceDialog.ListEndCompon[i]);
  end;
end;

function GetTreeNodebyDataID(aNode: TFlyNode; dataID: integer): TFlyNode;
var i: integer;
    ChildNode: TFlyNode;
begin
  Result := nil;
  if TNodeData(aNode.Data).ID = dataID then
    Result := aNode
  else
  begin
    for i := 0 to aNode.Count - 1 do
    begin
      ChildNode := aNode.Item[i];
      Result := GetTreeNodebyDataID(ChildNode, dataID);
      if Result <> nil then
        Break; //// BREAK ////;
    end;
  end;
end;

Procedure TF_PEAutotraceDialog.DeleteDoublesfromWorkTree; // Tolik 26/03/2021 --
var i, j: integer;
    ENode, WNode: TFlyNode;

    Procedure DeleteDoubleNodes(aNode: TFlyNode; NodeDataID: integer);
    var i: integer;
        delNode, WNode: TFlyNode;
    begin
      if TNodeData(aNode.Data).ID <> -1 then
      begin
        for i := 0 to tvWorkObject.Items.Count - 1 do
        begin
          WNode := tvWorkObject.Items[i];
          delNode := GetTreeNodebyDataID(WNode, NodeDataID);
          if delNode <> nil then
            tvWorkObject.Items.Delete(delNode);
        end;
      end;
    end;

    Procedure delWNode(aNode: TFlyNode; NodeDataID: integer);
    var i: integer;
        ChildNode: TFlyNode;
    begin
      DeleteDoubleNodes(aNode, NodeDataID);
      for i := 0 to aNode.Count - 1 do
      begin
        ChildNode := aNode.Item[i];
        delWNode(ChildNode, TNodeData(ChildNode.Data).ID);
      end;
    end;

begin
  for i := 0 to tvEndObject.Items.Count - 1 do
  begin
    ENode := tvEndObject.Items[i];
    DelWNode(eNode, TNodeData(ENode.Data).ID);
  end;
  for i := tvWorkObject.Items.Count - 1  downto 0 do
  begin
    WNode := tvWorkObject.Items[i];
    if TNodeData(WNode.Data).ID = -1 then
      if WNode.Count = 0 then
        tvWorkObject.Items.Delete(WNode);
  end;
end;

Procedure TF_PEAutotraceDialog.DeselectConnected;
var i: integer;
    Node: TFlyNode;
    tvWorkEvent: TStateChangedEvent;

    Procedure disableNode(aNode: TflyNode);
    var childNode: TFlyNode;
        SCSComponent: TSCSComponent;
        i: integer;
    begin
      if TNodeData(aNode.Data).ID <> -1 then
      begin
        SCSComponent := F_ProjMan.GSCSBase.CurrProject.GetComponentFromReferences(TNodeData(aNode.Data).ID);
        if SCSComponent <> nil then
        begin
          if SCSComponent.JoinedComponents.Count > 0 then
          begin
            for i := 0 to SCSComponent.JoinedComponents.Count - 1 do
            begin
              if isCableComponent(SCSComponent.JoinedComponents[i]) then
              begin
                aNode.BeginUpdate;
                aNode.StateIndex := STATE_UNCHECKED;
                tvWorkObject.NodeStateRefresh(aNode);
                aNode.EndUpdate;
                break;
              end;
            end;
          end;
        end;
      end;
      for i := 0 to aNode.Count - 1 do
      begin
        ChildNode := aNode.Item[i];
        disableNode(ChildNode);
      end;
    end;
begin
  tvWorkEvent := tvworkObject.OnStateChanged;
  tvWorkObject.OnStateChanged := nil;
  for i := 0 to tvWorkObject.Items.Count - 1 do
  begin
    Node := tvWorkObject.Items[i];
    disableNode(Node);
  end;
  //tvWorkObject.RefreshTreeStates;
  tvWorkObject.OnStateChanged := tvWorkEvent;
  tvWorkObject.Refresh;

  {for i := 0 to tvEndObject.Items.Count - 1 do
  begin
    Node := tvEndObject.Items[i];
    disableNode(Node);
  end;}
end;


procedure TF_PEAutotraceDialog.AutotraceKindChanging(Sender: TObject;
  NewIndex: Integer; var AllowChange: Boolean);
begin
  if NewIndex = 1 then
  begin
    TraceFromSwitch_CheckBox.Checked := false;
    TraceFromSwitch_CheckBox.Visible := false;
    TypeConnection.Visible := true;

    // Tolik
    if TypeConnection.ItemIndex = 0 then
    begin
      TypeAutotrace_RadioGroup.Enabled := True;
      CheckPassedTraces.Visible := False;
    end
    else
    begin
      TypeAutotrace_RadioGroup.Enabled := False;
      CheckPassedTraces.Visible := True;
    end;
    //
  end
  else
  begin
    TraceFromSwitch_CheckBox.Visible := true;
    TypeConnection.Visible := False;
    //Tolik
    TypeAutotrace_RadioGroup.Enabled := True;
    TypeConnection.ItemIndex := 0;
    CheckCanConnectCable.Visible := False;
  end;
  // Tolik 09/04/2021 --
  if GCallAutoTraceElectricMaster then
    IgnoreExistingCable.Visible := True
  else
  //
    IgnoreExistingCable.Visible := (TypeAutotrace_RadioGroup.Enabled and (TypeAutotrace_RadioGroup.ItemIndex = 1) and
                                  (NewIndex = 0) );
end;

procedure TF_PEAutotraceDialog.TypeConnectionChanging(Sender: TObject;
  NewIndex: Integer; var AllowChange: Boolean);
begin
  if NewIndex = 1 then
  //Tolik
  begin
    PutBox_Check.Enabled := false;
    TypeAutotrace_RadioGroup.Enabled := False;
    CheckPassedTraces.Visible := True;
    CheckCanConnectCable.Visible := True;
  end
  else
  begin
    TypeAutotrace_RadioGroup.Enabled := True;
    //PutBox_Check.Enabled := true;
    PutBox_Check.Enabled := (TypeAutotrace_RadioGroup.ItemIndex = 1);
    CheckPassedTraces.Visible := False;
    CheckCanConnectCable.Visible := False;
  end;
  // Tolik 09/04/2021 --
  if GCallAutoTraceElectricMaster then
    IgnoreExistingCable.Visible := True
  else
  //
    IgnoreExistingCable.Visible := (TypeAutotrace_RadioGroup.Enabled and (TypeAutotrace_RadioGroup.ItemIndex = 1) and
                                  (AutotraceKind.ItemIndex = 0) );
end;

procedure TF_PEAutotraceDialog.TypeAutotrace_RadioGroupChanging(
  Sender: TObject; NewIndex: Integer; var AllowChange: Boolean);
begin
    // Tolik 09/04/2021 --
  if GCallAutoTraceElectricMaster then
    IgnoreExistingCable.Visible := True
  else
  //
    IgnoreExistingCable.Visible := (TypeAutotrace_RadioGroup.Enabled and (NewIndex = 1) and
                                  (AutotraceKind.ItemIndex = 0) );
    PutBox_Check.Enabled := (NewIndex = 1);
end;
 // Tolik
procedure TF_PEAutotraceDialog.FormShow(Sender: TObject);
var currList: TSCSList;
    i, j: Integer;
    currCatalog: TSCSCatalog;
  Procedure ShowCatalogInPM(ACatalog : TSCSCatalog; aShowNode: Boolean = True);
  var
    Node: TTreeNode;
    FirstChildNode: TTreeNode;
    ObjID: Integer;
    Catalog: TSCSCatalog;
    //LastRoom: TSCSCatalog;
  begin
    //Exit; //#Del
    try
      with F_ProjMan do
      begin
        Catalog := ACatalog;
        if Assigned(Catalog) then
        begin
          Node := nil;
          FirstChildNode := nil;
          if Catalog.SCSComponents.Count > 0 then
          begin
            Node := Catalog.SCSComponents.Items[0].TreeViewNode;
            if Not Assigned(Node) then
              Node := FindComponOrDirInTree(TSCSComponent(Catalog.SCSComponents.Items[0]).ID, true)
          end
          else
            Node := Catalog.TreeViewNode; //FindComponOrDirInTree(ObjID, false);
          if Not Assigned(Node) then
            Node := FindComponOrDirInTree(Catalog.ID, false);
          //Tolik
          if aShowNode then
          begin
          //
            if Assigned(Node) then
            begin
             // Tree_Catalog.Items.BeginUpdate;
              try
                Tree_Catalog.Selected := Node;
                if Tree_Catalog.Selected <> Node then
                  Tree_Catalog.Selected := Node;
                //Tolik
                if aShowNode then
                  ShowSelectedNode(Tree_Catalog);
              finally
               // Tree_Catalog.Items.EndUpdate;
              end;
            end;
          end;
        end;
      end;
    except
      on E: Exception do AddExceptionToLog('ShowCatalogInPM: '+E.Message);
    end;
  end;

begin
  FromAutoTraceDialog := False;
  currList := F_ProjMan.GSCSBase.CurrProject.CurrList;
  if currList <> nil then
  begin
    // загрузить каталоги листа
    for i := 0 to currList.ChildCatalogs.Count - 1 do
    begin
      currCatalog := currList.ChildCatalogs[i];
      if currCatalog <> nil then
        ShowCatalogInPM(currCatalog);
    end;
    // сбросить LastAdded на всех каталогах листа
    for i := 0 to currList.ChildCatalogReferences.Count - 1 do
    begin
      currCatalog := currList.ChildCatalogReferences[i];
      if currCatalog <> nil then
      begin
        if currCatalog.LastAddedComponent <> nil then
        begin
          currCatalog.LastAddedComponent := nil;
          currCatalog.IDLastAddedComponent := 0;
        end;
      end;
    end;

  end;
  // Tolik 09/04/2021 --
  if GCallAutoTraceElectricMaster then
    IgnoreExistingCable.Visible := True
  else
  //
  IgnoreExistingCable.Visible := (TypeAutotrace_RadioGroup.Enabled and (TypeAutotrace_RadioGroup.ItemIndex = 1) and
                                  (AutotraceKind.ItemIndex = 0) );
  IgnoreExistingCable.Checked := False;
end;

procedure TF_PEAutotraceDialog.IgnoreExistingCableClick(Sender: TObject);
var currComponent: TSCSComponent;
    i: Integer;
    CanCheck: Boolean;
begin
  CanCheck := True;
  if (F_PEAutotraceDialog.IgnoreExistingCable.Checked) then
  begin
    currComponent := F_NormBase.GSCSBase.SCSComponent;   
    if (currComponent <> nil) and (currComponent.IsLine = biTrue) then
    begin
      for i := 0 to currComponent.Interfaces.Count - 1 do
      begin
        if (currComponent.Interfaces[i].TypeI = itFunctional) and (currComponent.Interfaces[i].Multiple = biTrue) then
        begin
          CanCheck := False;
          Break;
        end;
      end;
    end;
  end;
  if not CanCheck then
  begin
    F_PEAutotraceDialog.IgnoreExistingCable.Checked := False;
    ShowMessage(cPEMes25);
  end;
end;

// Tolik -- New --19/11/2015
// Tolik -- Следующий блок реализует взаимное исключение выбора объектов в левом и правом дереве
 // мастера автотрассировки (чтобы не было выбора подключения к самому себе)

 // Tolik -- New --19/11/2015
Procedure DropStateIndex(aNode: TFlyNode);
var i: Integer;
    ChildNode: TFlyNode;
begin
  if aNode.Count = 0 then
    aNode.StateIndex := 2
  else
  begin
    for i := 0 to aNode.UpdateCount - 1 do
    begin
      ChildNode := aNode.Item[i];
      DropStateIndex(ChildNode);
    end;
  end;
end;

// Tolik -- New --19/11/2015
procedure TF_PEAutotraceDialog.tvEndObjectStateChange(Node: TFlyNode;
  Oldindex: Integer);
var i, j: Integer;
   aNode, NodeToChange: TFlyNode;
   NodeFound: Boolean;
   tvWorkEvent: TStateChangedEvent;

 {  function GetTreeNodebyDataID(aNode: TFlyNode; dataID: integer): TFlyNode;
   var i: integer;
       ChildNode: TFlyNode;
   begin
     Result := nil;
     if TNodeData(aNode.Data).ID = dataID then
       Result := aNode
     else
     begin
       for i := 0 to aNode.Count - 1 do
       begin
         ChildNode := aNode.Item[i];
         Result := GetTreeNodebyDataID(ChildNode, dataID);
         if Result <> nil then
           Break; //// BREAK ////;
       end;
     end;
   end;

   Procedure DropStateIndex(aNode: TFlyNode);
   var i: Integer;
       ChildNode: TFlyNode;
   begin
     if aNode.Count = 0 then
       aNode.StateIndex := 2
     else
     begin
       for i := 0 to aNode.UpdateCount - 1 do
       begin
         ChildNode := aNode.Item[i];
         DropStateIndex(ChildNode);
       end;
     end;
   end;
          }
begin

  if OldIndex <> 2 then
  begin
    tvWorkEvent := tvWorkObject.OnStateChanged;
    tvWorkObject.OnStateChanged := nil;

    NodeFound := False;
    NodeToChange := nil;

    i :=  TNodeData(Node.Data).ID;
    if i <> -1 then
    begin
      if tvWorkObject.Items.Count > 0 then
      begin
        for j := 0 to tvWorkObject.Items.Count - 1 do
        begin
          aNode := TFlyNode(tvWorkObject.Items[j]);
          if TNodeData(aNode.Data).ID = i then
          begin
             NodeToChange := aNode;
          end
          else
            NodeToChange := GetTreeNodebyDataID(aNode, i);
          if NodeToChange <> nil then
            Break; //// BREAK ////;
        end;

       { if NodeToChange <> nil then
        begin
          NodeToChange.StateIndex := 1;
          tvWorkObject.RefreshTreeStates;
          tvWorkObject.Repaint;
        end;}
        if NodeToChange <> nil then
        begin
          if (TNodeData(NodeToChange.Data).Id = -1) then
            NodeTochange.StateIndex := 1
          else
          begin
            if NodeToChange.Parent.expanded then
              NodeToChange.StateIndex := 1
            else
            begin
              aNode := NodeToChange.Parent;
              if TNodeData(aNode.Data).ID = -1 then
                aNode.StateIndex := 1
              else
              begin
                while ((not aNode.Parent.Expanded) and (TNodeData(aNode.Parent.Data).ID <> -1)) do
                  aNode := aNode.Parent;

                aNode.Expand(true);
                aNode.BeginUpdate;
                DropStateIndex(aNode);
                aNode.StateIndex := 1;
                tvWorkObject.NodeStateRefreshChildren(aNode, True);
                aNode.EndUpdate;
                
              end;
            end;
          end;
        end;
      end;
    end;

    tvWorkObject.RefreshTreeStates;
    tvWorkObject.Repaint;
    tvWorkObject.OnStateChanged := tvWorkEvent;
  end;
end;
// Tolik -- New --19/11/2015
procedure TF_PEAutotraceDialog.tvWorkObjectStateChange(Node: TFlyNode;
  Oldindex: Integer);
var i, j: Integer;
   aNode, NodeToChange: TFlyNode;
   NodeFound: Boolean;
   currEvent: TStateChangedEvent;
   tvEndEvent: TStateChangedEvent;
   ChildChecked: Boolean;
   CanCheckNextTreeNode: Boolean;

begin

  if OldIndex <> 2 then
  begin
    tvEndEvent := tvEndObject.OnStateChanged;
    tvEndObject.OnStateChanged := nil;

    NodeFound := False;
    NodeToChange := nil;

    i :=  TNodeData(Node.Data).ID;
    if i <> -1 then // категория
    begin
      if tvEndObject.Items.Count > 0 then
      begin
        for j := 0 to tvEndObject.Items.Count - 1 do
        begin
          aNode := TFlyNode(tvEndObject.Items[j]);
          if TNodeData(aNode.Data).ID = i then
          begin
             NodeToChange := aNode;
          end
          else
            NodeToChange := GetTreeNodebyDataID(aNode, i);
          if NodeToChange <> nil then
            Break; //// BREAK ////;
        end;

        if NodeToChange <> nil then
        begin
          if (TNodeData(NodeToChange.Data).Id = -1) then
            NodeTochange.StateIndex := 1
          else
          begin
            if NodeToChange.Parent.expanded then
              NodeToChange.StateIndex := 1
            else
            begin
              aNode := NodeToChange.Parent;
              if TNodeData(aNode.Data).ID = -1 then
                aNode.StateIndex := 1
              else
              begin
                while ((not aNode.Parent.Expanded) and (TNodeData(aNode.Parent.Data).ID <> -1)) do
                  aNode := aNode.Parent;

                aNode.Expand(true);
                aNode.BeginUpdate;
                DropStateIndex(aNode);
                aNode.StateIndex := 1;
                tvEndObject.NodeStateRefreshChildren(aNode, True);
                aNode.EndUpdate;
              end;
            end;
          end;
        end;
      end;
    end;
    tvEndObject.RefreshTreeStates;
    tvEndObject.Repaint;
    tvEndObject.OnStateChanged := tvEndEvent;
  end;
end;
/////Tolik ----------18/01/2017
procedure TF_PEAutotraceDialog.SpeedButton2Click(Sender: TObject);
begin
 { TF_MAIN(F_NormBase).F_AnswerToQuast.GCaption := cAddComponent_Msg6_1;
  TF_MAIN(F_NormBase).F_AnswerToQuast.GAnswer := cAddComponent_Msg6_2;
  TF_MAIN(F_NormBase).F_AnswerToQuast.ShowContextHelp(TF_MAIN(F_NormBase).F_AnswerToQuast.GCaption, TF_MAIN(F_NormBase).F_AnswerToQuast.GAnswer);
}end;

procedure TF_PEAutotraceDialog.SpeedButton1Click(Sender: TObject);
begin
 { TF_MAIN(F_NormBase).F_AnswerToQuast.GCaption := PE_HelpCapt3;
  TF_MAIN(F_NormBase).F_AnswerToQuast.GAnswer := PE_HelpMsg_2;
  TF_MAIN(F_NormBase).F_AnswerToQuast.ShowContextHelp(TF_MAIN(F_NormBase).F_AnswerToQuast.GCaption, TF_MAIN(F_NormBase).F_AnswerToQuast.GAnswer);
}end;

procedure TF_PEAutotraceDialog.btCanComplectClick1(Sender: TObject);
begin
{  TF_MAIN(F_NormBase).F_AnswerToQuast.GCaption := PE_HelpCapt4;
  TF_MAIN(F_NormBase).F_AnswerToQuast.GAnswer := PE_HelpMsg_4;
  TF_MAIN(F_NormBase).F_AnswerToQuast.ShowContextHelp(TF_MAIN(F_NormBase).F_AnswerToQuast.GCaption, TF_MAIN(F_NormBase).F_AnswerToQuast.GAnswer);
}end;
//
procedure TF_PEAutotraceDialog.SpeedButton5Click(Sender: TObject);
begin
  TF_MAIN(F_NormBase).F_AnswerToQuast.GCaption := PE_HelpCapt2;
  TF_MAIN(F_NormBase).F_AnswerToQuast.GAnswer := PE_HelpMsg_2;
  TF_MAIN(F_NormBase).F_AnswerToQuast.ShowContextHelp(TF_MAIN(F_NormBase).F_AnswerToQuast.GCaption, TF_MAIN(F_NormBase).F_AnswerToQuast.GAnswer);
end;

procedure TF_PEAutotraceDialog.SpeedButton3Click(Sender: TObject);
begin
  TF_MAIN(F_NormBase).F_AnswerToQuast.GCaption := PE_HelpCapt1;
  TF_MAIN(F_NormBase).F_AnswerToQuast.GAnswer := PE_HelpMsg_1;
  TF_MAIN(F_NormBase).F_AnswerToQuast.ShowContextHelp(TF_MAIN(F_NormBase).F_AnswerToQuast.GCaption, TF_MAIN(F_NormBase).F_AnswerToQuast.GAnswer);
end;

end.


