unit U_MakeEditPortInterfRel;

interface

uses
  Windows, U_LNG, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs,
  U_BaseCommon, U_BaseConstants, ExtCtrls, RzPanel, RzButton, cxStyles, cxCustomData,
  cxGraphics, cxFilter, cxData, cxDataStorage, cxEdit, DB, cxDBData,
  cxGridLevel, cxClasses, cxControls, cxGridCustomView,
  cxGridCustomTableView, cxGridTableView, cxGridDBTableView, cxGrid,
  kbmMemTable, siComp, siLngLnk, cxLookAndFeels, cxLookAndFeelPainters,
  cxNavigator;

type
  TF_MakeEditPortInterfRel = class(TForm)
    gbInterfaces: TRzGroupBox;
    RzGroupBox2: TRzGroupBox;
    btOk: TRzBitBtn;
    btCancel: TRzBitBtn;
    GT_Interfaces: TcxGridDBTableView;
    GL_Interfaces: TcxGridLevel;
    Grid_Interfaces: TcxGrid;
    DSrcInterfaces: TDataSource;
    mtInterfaces: TkbmMemTable;
    lng_Forms: TsiLangLinked;
    procedure FormCreate(Sender: TObject);
    procedure RzGroupBox2Resize(Sender: TObject);
    procedure GT_InterfacesDblClick(Sender: TObject);
  private
    GForm: TForm;

    FEditingInterfRelID: Integer;
    FEditingPortInterfRelID: Integer;
    FIDPortComponent: Integer;
    FIgnoreIDPort: Integer;
    FIgnoreIDToSelect: Integer;
    FMakeEdit: TMakeEdit;
    FmtEditingPortInterfRel: TkbmMemTable;
    FmeInterfaceRel: TmeInterfaceRel;
    FmtPorts: TkbmMemTable;
    FmtPortInterfRel: TkbmMemTable;
    FmtInterfaces: TkbmMemTable;

    FIsPort: Integer;

    procedure LoadAccessibleInterfaces;
  public
    Constructor Create(AOwner: TComponent; AForm: TForm);
    Destructor  Destroy; override;

    function Execute(AMakeEdit: TMakeEdit; AmeInterfaceRel: TmeInterfaceRel;
                AmtEditingPortInterfaces: TkbmMemTable; AIgnoreIDPort: Integer): Boolean;
    function SelectInterfForInternalConn(AMakeEdit: TMakeEdit; AmeInterfaceRel: TmeInterfaceRel;
                AmtInterfInternalConn: TkbmMemTable; AIgnoreID: Integer): Boolean;
  end;

//var
//  F_MakeEditPortInterfRel: TF_MakeEditPortInterfRel;

implementation
Uses U_Main, Unit_DM_SCS;
{$R *.dfm}

{ TF_MakeEditPortInterfRel }

constructor TF_MakeEditPortInterfRel.Create(AOwner: TComponent;
  AForm: TForm);
begin
  GForm := AForm;
  inherited Create(AOwner);
end;

destructor TF_MakeEditPortInterfRel.Destroy;
begin

  inherited;
end;

function TF_MakeEditPortInterfRel.Execute(AMakeEdit: TMakeEdit;
  AmeInterfaceRel: TmeInterfaceRel; AmtEditingPortInterfaces: TkbmMemTable;
  AIgnoreIDPort: Integer): Boolean;
begin
  Result := false;
  FMakeEdit := AMakeEdit;
  FmeInterfaceRel := AmeInterfaceRel;

  FEditingInterfRelID := -1;
  FEditingPortInterfRelID := -1;
  FIDPortComponent := -1;
  FIgnoreIDPort := AIgnoreIDPort;
  FIgnoreIDToSelect := -1;

  FmtEditingPortInterfRel := AmtEditingPortInterfaces;
  FmtPortInterfRel := AmeInterfaceRel.mtPortInterfRel;
  if Assigned(FmtPortInterfRel) then
    FmtPorts := TkbmMemTable(FmtPortInterfRel.MasterSource.DataSet);
  FmtInterfaces := AmeInterfaceRel.mtInterfaces;

  case FMakeEdit of
    meMake:
      begin
        Caption := cMakeEditPortInterfRel_Msg1_1;
        FIDPortComponent := AmeInterfaceRel.ID_COMPONENT;
      end;
    meEdit:
      begin
        Caption := cMakeEditPortInterfRel_Msg1_2;
        if FmtEditingPortInterfRel.RecordCount > 0 then
        begin
          FEditingPortInterfRelID := FmtEditingPortInterfRel.FieldByName(fnID).AsInteger;
          FEditingInterfRelID := FmtEditingPortInterfRel.FieldByName(fnIDInterfRel).AsInteger;
          FIDPortComponent := FmtPorts.FieldByName(fnIDComponent).AsInteger;
        end;
      end;
  end;
  gbInterfaces.Caption := cMakeEditPortInterfRel_Msg5_1;

  LoadAccessibleInterfaces;
  if FMakeEdit = meEdit then
    mtInterfaces.Locate(fnID, FEditingInterfRelID, []);

  if mtInterfaces.RecordCount = 0 then
    ShowMessageByType(Self.Handle, smtDisplay, cMakeEditPortInterfRel_Msg2,
      Application.Title, MB_ICONINFORMATION or MB_OK)
  else
  if ShowModal = mrOk then
    Result := true;
end;

function TF_MakeEditPortInterfRel.SelectInterfForInternalConn(AMakeEdit: TMakeEdit; AmeInterfaceRel: TmeInterfaceRel;
  AmtInterfInternalConn: TkbmMemTable; AIgnoreID: Integer): Boolean;
var
  Msg: string;  
begin
  Result := false;
  FMakeEdit := AMakeEdit;

  //FIsPort := AIsPort;
  //FmtInterfOrPort := AmtInterfOrPort;
  //FmtInterfInternalConn := FmtInterfInternalConn;
  FEditingInterfRelID := -1;
  FEditingPortInterfRelID := -1;
  FIgnoreIDPort := AIgnoreID;
  FIDPortComponent := AmeInterfaceRel.ID_COMPONENT;

  FmeInterfaceRel := AmeInterfaceRel;
  FmtEditingPortInterfRel := AmtInterfInternalConn;
  FmtPortInterfRel := AmeInterfaceRel.mtInterfInternalConnect;
  if Assigned(FmtPortInterfRel) then
    if Assigned(FmtPortInterfRel.MasterSource) then
      FmtPorts := TkbmMemTable(FmtPortInterfRel.MasterSource.DataSet);
  FmtInterfaces := FmtPorts; //AmeInterfaceRel.mtInterfaces;

  //FEditingInterfRelID := FmtPorts.FieldByName(fnID).AsInteger; //FmtEditingPortInterfRel.FieldByName(fnIDInterfRel).AsInteger;
  FIDPortComponent := FmtPorts.FieldByName(fnIDComponent).AsInteger;
  FIgnoreIDToSelect := FmtPorts.FieldByName(fnID).AsInteger;

  Caption := cMakeEditPortInterfRel_Msg3_1;
  case AmeInterfaceRel.IsPort of
    biTrue:
      begin
        Caption := cMakeEditPortInterfRel_Msg3_2;
        gbInterfaces.Caption := cMakeEditPortInterfRel_Msg5_2;
      end;
    biFalse:
      begin
        Caption := cMakeEditPortInterfRel_Msg3_1;
        gbInterfaces.Caption := cMakeEditPortInterfRel_Msg5_1;
      end;
  end;



  {case FMakeEdit of
    meMake:
      begin
        FIDPortComponent := AmeInterfaceRel.ID_COMPONENT;
      end;
    meEdit:
      begin
        Caption := 'Выбор интерфейса для порта';
        if FmtEditingPortInterfRel.RecordCount > 0 then
        begin
          FEditingInterfRelID := FmtEditingPortInterfRel.FieldByName(fnIDInterfRel).AsInteger;
          FIDPortComponent := FmtPorts.FieldByName(fnIDComponent).AsInteger;
        end;
      end;
  end;}

  LoadAccessibleInterfaces;
  if FMakeEdit = meEdit then
    mtInterfaces.Locate(fnID, FEditingInterfRelID, []);

  if mtInterfaces.RecordCount = 0 then
  begin
    Msg := cMakeEditPortInterfRel_Msg4_1;
    case AmeInterfaceRel.IsPort of
      biTrue:
        Msg := Msg + cMakeEditPortInterfRel_Msg4_3 + '. ' + cMakeEditPortInterfRel_Msg4_5;
      biFalse:
        Msg := Msg + cMakeEditPortInterfRel_Msg4_2 + '. ' + cMakeEditPortInterfRel_Msg4_4;
    end;

    ShowMessageByType(Self.Handle, smtDisplay, Msg,
      Application.Title, MB_ICONINFORMATION or MB_OK);
  end
  else
    if ShowModal = mrOk then
      Result := true;
end;

procedure TF_MakeEditPortInterfRel.FormCreate(Sender: TObject);
var
  i: Integer;
begin
  with TF_Main(GForm).DM do
    for i := 0 to MemTable_InterfaceRel.FieldDefs.Count - 1 do
      Self.mtInterfaces.FieldDefs.Add(MemTable_InterfaceRel.FieldDefs[i].Name,
                                     MemTable_InterfaceRel.FieldDefs[i].DataType,
                                     MemTable_InterfaceRel.FieldDefs[i].Size);

  GT_Interfaces.Assign(TF_Main(GForm).GT_INTERFACE);
  GT_Interfaces.DataController.DataSource := DSrcInterfaces;
  GT_Interfaces.OptionsSelection.CellSelect := false;
  GT_Interfaces.OnDblClick := GT_InterfacesDblClick;
end;

procedure TF_MakeEditPortInterfRel.LoadAccessibleInterfaces;
var
  SavedPortsRecNo: Integer;
  SavedInterfacesRecNo: Integer;
  SavedPortInterfRelNo: Integer;
  SavedEdPortInterfRelNo: Integer;
  CurrInterfRelID: Integer;
  IsAccessible: Boolean;
  i, j: Integer;

  SavedMasterSource: TDataSource;

  function CheckAccessInterfInPortInterfRel(AIDInterfRel: Integer;
    AmtPortInterfRel: TkbmMemTable; AIgnorePortID: Integer): Boolean;
  var
    i: Integer;
    IDPort: Integer;
  begin
    Result := true;
    if AmtPortInterfRel.RecordCount > 0 then // Tolik 28/12/2019 --
    begin
      for i := 0 to AmtPortInterfRel.RecordCount - 1 do
      begin
        AmtPortInterfRel.RecNo := i+1;
        //if AmtPortInterfRel.FieldByName(fnID).AsInteger <> FEditingPortInterfRelID then
        IDPort := AmtPortInterfRel.FieldByName(fnIDPort).AsInteger;
        if IDPort <> AIgnorePortID then
          if AIDInterfRel <> FEditingInterfRelID then
            //if (AmtPortInterfRel.FieldByName(fnIDInterfRel).AsInteger = AIDInterfRel) or
            //   (AmtPortInterfRel.FieldByName(fnIDInterfRel).AsInteger = FmeInterfaceRel.ID) then
            if (AIDInterfRel = AmtPortInterfRel.FieldByName(fnIDInterfRel).AsInteger) or
               (AIDInterfRel = IDPort) then
            begin
              Result := false;
              Break; ///// BREAK /////
            end;
      end;
    end;
  end;
begin
  if Not FmtEditingPortInterfRel.ControlsDisabled then
    FmtEditingPortInterfRel.DisableControls;
  if Not FmtPorts.ControlsDisabled then
    FmtPorts.DisableControls;
  if Not FmtInterfaces.ControlsDisabled then
    FmtInterfaces.DisableControls;
  if Not FmtPortInterfRel.ControlsDisabled then
    FmtPortInterfRel.DisableControls;
  if Not mtInterfaces.ControlsDisabled then
    mtInterfaces.DisableControls;

  SavedPortsRecNo := FmtPorts.RecNo;
  SavedInterfacesRecNo := FmtInterfaces.RecNo;
  SavedPortInterfRelNo := FmtPortInterfRel.RecNo;
  SavedEdPortInterfRelNo := FmtEditingPortInterfRel.RecNo;

  SavedMasterSource := FmtPortInterfRel.MasterSource;
  FmtPortInterfRel.MasterSource := nil;
  try
    mtInterfaces.Active := false;
    mtInterfaces.Active := true;

    mtInterfaces.LoadFromDataSet(FmtInterfaces, []);
    if mtInterfaces.RecordCount > 0 then
    begin
      mtInterfaces.Last;
      while Not mtInterfaces.Bof do
      begin
        IsAccessible := true;
        if mtInterfaces.FieldByName(fnTypeI).AsInteger = itFunctional then
        begin
          CurrInterfRelID := mtInterfaces.FieldByName(fnID).AsInteger;
          if (CurrInterfRelID = FIgnoreIDToSelect) then
            IsAccessible := false
          else
          begin
            //*** Проверить, пренадлежит ли интерфейс другому порту

            if mtInterfaces.FieldByName(fnIDComponent).AsInteger <> FIDPortComponent then
              IsAccessible := false
            else
            if CurrInterfRelID <> FEditingInterfRelID then
            begin
              //*** Проверить в редактируемых записях
              if Not CheckAccessInterfInPortInterfRel(CurrInterfRelID, FmtEditingPortInterfRel, -1) then
                IsAccessible := false;

              //*** Проверить в не редактируемых записях
              if IsAccessible then
                if Not CheckAccessInterfInPortInterfRel(CurrInterfRelID, FmtPortInterfRel, FIgnoreIDPort) then
                  IsAccessible := false;
            end;
          end;
        end
        else
          IsAccessible := false;
        if Not IsAccessible then
          mtInterfaces.Delete
        else
          mtInterfaces.Prior;
      end;
    end;
  finally
    FmtPortInterfRel.MasterSource := SavedMasterSource;
    if SavedPortsRecNo > -1 then  // Tolik 28/12/2019 --
      FmtPorts.RecNo := SavedPortsRecNo;
    if SavedInterfacesRecNo > -1 then // Tolik 28/12/2019 --
      FmtInterfaces.RecNo := SavedInterfacesRecNo;
    if SavedPortInterfRelNo > -1 then // Tolik 28/12/2019 --
      FmtPortInterfRel.RecNo := SavedPortInterfRelNo;
    if mtInterfaces.RecordCount > 0 then
      mtInterfaces.First;
    if SavedEdPortInterfRelNo > -1 then // Tolik 28/12/2019 --
      FmtEditingPortInterfRel.RecNo := SavedEdPortInterfRelNo;

    if FmtEditingPortInterfRel.ControlsDisabled then
      FmtEditingPortInterfRel.EnableControls;
    if FmtPorts.ControlsDisabled then
      FmtPorts.EnableControls;
    if FmtInterfaces.ControlsDisabled then
      FmtInterfaces.EnableControls;
    if FmtPortInterfRel.ControlsDisabled then
      FmtPortInterfRel.EnableControls;
    if mtInterfaces.ControlsDisabled then
      mtInterfaces.EnableControls;
  end;
end;

procedure TF_MakeEditPortInterfRel.RzGroupBox2Resize(Sender: TObject);
begin
  SetMiddleControlChilds(TControl(Sender), Self);
end;

procedure TF_MakeEditPortInterfRel.GT_InterfacesDblClick(Sender: TObject);
begin
  btOk.Click;
end;

end.
