unit U_ObjsProp;

interface

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

type

  TOnSetPropValue = procedure (ASender, AObj: TObject; AProp: PProperty; const AOldVal: String; AChecked: Boolean) of Object;

  TF_ObjsProp = class(TForm)
    gbInterfaces: TRzGroupBox;
    RzGroupBox2: TRzGroupBox;
    btOk: TRzBitBtn;
    btCancel: TRzBitBtn;
    dsrcProps: TDataSource;
    mtProps: TkbmMemTable;
    lng_Forms: TsiLangLinked;
    Grid_CompData: TcxGrid;
    GT_PROPERTY: TcxGridDBTableView;
    GT_PROPERTYNAME: TcxGridDBColumn;
    GT_PROPERTYVALUE: TcxGridDBColumn;
    GT_PROPERTYIZM: TcxGridDBColumn;
    GT_PROPERTYTakeIntoConnect: TcxGridDBColumn;
    GT_PROPERTYTakeIntoJoin: TcxGridDBColumn;
    GT_PROPERTYDESCRIPTION: TcxGridDBColumn;
    GT_PROPERTYDBColumn1: TcxGridDBColumn;
    GT_PROPERTYSysName: TcxGridDBColumn;
    GL_PROPERTY: TcxGridLevel;
    GT_PROPERTYOn: TcxGridDBColumn;
    pnApplyParams: TPanel;
    cbApplyForAllSameType: TRzCheckBox;
    Timer_PostGridTableView: TTimer;
    btCheckAll: TSpeedButton;
    btUnCheckAll: TSpeedButton;
    procedure FormCreate(Sender: TObject);
    procedure RzGroupBox2Resize(Sender: TObject);
    procedure GT_PROPERTYVALUEGetDisplayText(
      Sender: TcxCustomGridTableItem; ARecord: TcxCustomGridRecord;
      var AText: String);
    procedure GT_PROPERTYVALUEGetProperties(Sender: TcxCustomGridTableItem;
      ARecord: TcxCustomGridRecord;
      var AProperties: TcxCustomEditProperties);
    procedure GT_PROPERTYIZMGetDisplayText(Sender: TcxCustomGridTableItem;
      ARecord: TcxCustomGridRecord; var AText: String);
    procedure FormDestroy(Sender: TObject);
    procedure GT_PROPERTYEditValueChanged(Sender: TcxCustomGridTableView;
      AItem: TcxCustomGridTableItem);
    procedure Timer_PostGridTableViewTimer(Sender: TObject);
    procedure btCheckAllClick(Sender: TObject);
    procedure btUnCheckAllClick(Sender: TObject);
    procedure GT_PROPERTYEditChanged(Sender: TcxCustomGridTableView;
      AItem: TcxCustomGridTableItem);
    procedure mtPropsAfterPost(DataSet: TDataSet);
    procedure GT_PROPERTYInitEdit(Sender: TcxCustomGridTableView;
      AItem: TcxCustomGridTableItem; AEdit: TcxCustomEdit);
  private
    GForm: TForm;

    FObject: TObject;
    FOnSetPropValue: TOnSetPropValue;
    FModified: TStringList;
    FEditedItem: TcxCustomGridTableItem;

    procedure SetIsOnForAll(AIsOn: Boolean);
  public
    Constructor Create(AOwner: TComponent; AForm: TForm);
    Destructor Destroy; override;

    function Execute(AObject: TObject; AAllowApplyForAll: Boolean=true; AOnSetPropValue: TOnSetPropValue=nil): Boolean;
  end;

  function EditObjectProps(ASender: TForm; AObject: TObject; AAllowApplyForAll: Boolean=true; AOnSetPropValue: TOnSetPropValue=nil): Boolean;

var
  F_ObjsProp: TF_ObjsProp;

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

{ TF_ObjsProp }

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

destructor TF_ObjsProp.Destroy;
begin

  inherited;
end;

procedure TF_ObjsProp.SetIsOnForAll(AIsOn: Boolean);
var
  //StrBookMark: String;
  StrBookMark: TBookMark;
begin
  //StrBookMark := mtProps.Bookmark;
 // StrBookMark := mtProps.GetBookmark;
  mtProps.DisableControls;
  try
    mtProps.First;
    while Not mtProps.Eof do
    begin
      mtProps.Edit;
      mtProps.FieldByName(fnIsOn).AsBoolean := AIsOn;
      mtProps.Post;
      mtProps.Next;
    end;
  finally
    mtProps.EnableControls;
  end;
end;

function TF_ObjsProp.Execute(AObject: TObject; AAllowApplyForAll: Boolean=true; AOnSetPropValue: TOnSetPropValue=nil): Boolean;
var
  ptrProperty: PProperty;
  OldProps: TStringList;
  SavedAfterPost: TDataSetNotifyEvent;
begin
  Result := false;
  try
    FObject := AObject;
    FOnSetPropValue := AOnSetPropValue;
    

    OldProps := CreateStringListSorted;

    mtProps.Active := false;
    mtProps.Active := true;
    SavedAfterPost := mtProps.AfterPost;
    mtProps.AfterPost := nil;
    mtProps.DisableControls;
    try
      if AObject is TSCSComponCatalogClass then
      begin
        TF_Main(GForm).DM.FillMemTablePropFromList(mtProps, TSCSComponCatalogClass(AObject).Properties, false, true, false);
      end;

      // Запоминаем исходное свойство
      //fnPValueSrc
      mtProps.First;
      while Not mtProps.Eof do
      begin
        ptrProperty := PProperty(mtProps.FieldByName(fnObjectAddress).AsInteger);
        mtProps.Edit;
        mtProps.FieldByName(fnIsOn).AsBoolean := false;
        mtProps.FieldByName(fnPValueSrc).AsString := mtProps.FieldByName(fnPValue).AsString;
        if ptrProperty.Name_ <> '' then
          mtProps.FieldByName(fnName).AsString := ptrProperty.Name_;
        mtProps.Post;
        OldProps.Add(mtProps.FieldByName(fnSysName).AsString);
        mtProps.Next;
      end;
      mtProps.SortOn(fnID, []);
    finally
      mtProps.EnableControls;
      mtProps.AfterPost := SavedAfterPost;
    end;
    FModified.Clear;
    FEditedItem := nil;

    pnApplyParams.Visible := AAllowApplyForAll;
    GT_PROPERTYOn.Visible := AAllowApplyForAll;

    if ShowModal = mrOk then
    begin
      Result := true;

      mtProps.DisableControls;
      try
        mtProps.First;
        while Not mtProps.Eof do
        begin
          if {(mtProps.FieldByName(fnPValueSrc).AsString <> mtProps.FieldByName(fnPValue).AsString) or}
             mtProps.FieldByName(fnIsModified).AsBoolean or
             (mtProps.FieldByName(fnIsOn).AsBoolean = true) or
             (OldProps.IndexOf(mtProps.FieldByName(fnSysName).AsString) = -1) then
          begin
            FModified.Add(mtProps.FieldByName(fnSysName).AsString);
            //ptrProperty := PProperty(mtProps.FieldByName(fnObjectAddress).AsInteger);
            ptrProperty := nil;
            if AObject is TSCSComponCatalogClass then
              ptrProperty := TSCSComponCatalogClass(AObject).GetPropertyBySysName(mtProps.FieldByName(fnSysName).AsString);
            if ptrProperty <> nil then
            begin
              ptrProperty.Value := mtProps.FieldByName(fnPValue).AsString;
              if Assigned(AOnSetPropValue) then
                AOnSetPropValue(Self, AObject, ptrProperty, mtProps.FieldByName(fnPValueSrc).AsString, mtProps.FieldByName(fnIsOn).AsBoolean);
            end;
          end;
          mtProps.Next;
        end;
      finally
        mtProps.EnableControls;
      end;
    end;
    OldProps.Free;
  except
    on E: Exception do AddExceptionToLogExt(ClassName, 'Execute', E.Message);
  end;
end;

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

procedure TF_ObjsProp.GT_PROPERTYVALUEGetDisplayText(
  Sender: TcxCustomGridTableItem; ARecord: TcxCustomGridRecord;
  var AText: String);
begin
  SetDisplayTextToGridTablePropValue(AText, ARecord, 7, 8, TF_Main(GForm).FUOM);
end;

procedure TF_ObjsProp.GT_PROPERTYVALUEGetProperties(
  Sender: TcxCustomGridTableItem; ARecord: TcxCustomGridRecord;
  var AProperties: TcxCustomEditProperties);
begin
  // 05/07/2019 -- IGOR
  // Tolik : здесь выполнен сброс обработчика, если нужно "подсунуть" значение, иначе стандартный обработчик
  // получит текущее значение поля, что не есть гут. Раньше такой проблемы не было, а "ЭТО" выплыло следствие того,
  // что разработчики немного подшаманили новую версию DevExpress'ов ...

  GT_PROPERTYVALUE.OnGetDisplayText := GT_PROPERTYVALUEGetDisplayText;

  if ARecord.Values[7] <> null then
    with DMCommon do
    begin
      if (ARecord.Values[7] = dtBoolean) or (ARecord.Values[7] = dtCompStateType)
         or (ARecord.Values[7] = dtPlaneMaterialType) or (ARecord.Values[7] = dtRoofHipType)
         or (ARecord.Values[7] = dtRoofHipApexType) or (ARecord.Values[7] = dtRoofHipValleyType)
         or (ARecord.Values[7] = dtColor) or (ARecord.Values[7] = dtCableCanalElementType) then
        GT_PROPERTYVALUE.OnGetDisplayText := nil;
    //
      case ARecord.Values[7] of
        dtBoolean:
          AProperties := EditRepositoryCheckBoxItem.Properties;
        //dtFloat:
        //  AProperties := EditRepositorySpinItem.Properties;
        //dtDate:
        //  AProperties := EditRepositoryDateItem.Properties;
        dtCompStateType:
          AProperties := EditRepositoryLookupCompSateType.Properties;
        dtColor:
          AProperties := EditRepositoryColorComboBox.Properties;
        dtCableCanalElementType:
          AProperties := EditRepositoryLookupCableCanalElementType.Properties;
        //dtSectionSide:
        //  AProperties := EditRepositoryMaskItemSectionSide.Properties;
        //dtStringList:
        //  AProperties := EditRepositoryMemo.Properties;
        dtPlaneMaterialType:
          AProperties := erLookupPlaneMaterialType.Properties;
        dtRoofHipType:
          AProperties := erLookupRoofHipType.Properties;
        dtRoofHipApexType:
          AProperties := erLookupRoofHipApexType.Properties;
        dtRoofHipValleyType:
          AProperties := erLookupRoofHipValleyType.Properties;
      end;
    end;
end;

procedure TF_ObjsProp.GT_PROPERTYIZMGetDisplayText(
  Sender: TcxCustomGridTableItem; ARecord: TcxCustomGridRecord;
  var AText: String);
begin
  SetDisplayTextToGridTablePropIzm(AText, ARecord, 8, TF_Main(GForm).FUOM);
end;

procedure TF_ObjsProp.FormCreate(Sender: TObject);
begin
  //mtProps.LoadFromDataSet(TF_Main(GForm).DM.MemTable_Property, [mtcpoStructure]);
  //mtProps.CreateTableAs(TF_Main(GForm).DM.MemTable_Property, [mtcpoStructure]); //LoadFromDataSet(TF_Main(GForm).DM.MemTable_Property, [mtcpoStructure]);
  mtProps.FieldDefs.Assign(TF_Main(GForm).DM.MemTable_Property.FieldDefs);
  mtProps.FieldDefs.Add(fnPValueSrc, ftString, 255);
  mtProps.FieldDefs.Add(fnObjectAddress, ftInteger);
  mtProps.FieldDefs.Add(fnIsOn, ftBoolean);
  FModified := TStringList.Create;
end;

procedure TF_ObjsProp.FormDestroy(Sender: TObject);
begin
  FModified.Free;
end;

function EditObjectProps(ASender: TForm; AObject: TObject; AAllowApplyForAll: Boolean=true; AOnSetPropValue: TOnSetPropValue=nil): Boolean;
begin
  if F_ObjsProp = nil then
    F_ObjsProp := TF_ObjsProp.Create(Application, ASender);
  F_ObjsProp.GForm := ASender;
  Result := F_ObjsProp.Execute(AObject, AAllowApplyForAll, AOnSetPropValue);
end;

procedure TF_ObjsProp.GT_PROPERTYEditValueChanged(
  Sender: TcxCustomGridTableView; AItem: TcxCustomGridTableItem);
begin
  if (Sender.DataController.IsEditing) and (mtProps.State <> dsBrowse) then
  begin
    //EnableTimerWithOrder(Timer_PostGridTableView, true, true);
    //if FEditedItem <> GT_PROPERTYOn then
    Timer_PostGridTableView.Enabled := true;
  end;
end;

procedure TF_ObjsProp.Timer_PostGridTableViewTimer(Sender: TObject);
var
  CurrPropSysName: String;
  CurrProp: PProperty;
  CurrPropOldVal: String;
  TempCompon: TSCSComponent;
  PropFromMT: TProperty;
  ptrProperty: PProperty;
  OldSysNames: TStringList;
  i: Integer;
begin
  TTimer(Sender).Enabled := false;

  if GT_PROPERTY.DataController.IsEditing and (mtProps.State <> dsBrowse) then
  begin
    GT_PROPERTY.DataController.Post;

    //mtProps.Edit;
    //mtProps.FieldByName(fnPValue).AsFloat := FloatInUOM(mtProps.FieldByName(fnPValue).AsFloat, TF_Main(GForm).FUOM, umMetr);
    //mtProps.Post;

     //exit;
    if Assigned(FOnSetPropValue) then
    begin
      CurrPropSysName := mtProps.FieldByName(fnSysName).AsString;
      CurrPropOldVal := mtProps.FieldByName(fnPValueSrc).AsString;
      CurrProp := nil;
      OldSysNames := TStringList.Create;
      OldSysNames.Sorted := true;
      TempCompon := TSCSComponent.Create(GForm);
      if FObject is TSCSComponent then
        TempCompon.ProjectOwner := TSCSComponent(FObject).ProjectOwner;
      mtProps.DisableControls;
      try
        mtProps.First;
        while Not mtProps.Eof do
        begin
          PropFromMT := TF_Main(GForm).DM.GetPropertyFromTable(dsrcProps);
          ptrProperty := TempCompon.GetPropertyAsNew;
          ptrProperty^ := PropFromMT;
          mtProps.Next;
          OldSysNames.Add(PropFromMT.SysName);
          if PropFromMT.SysName = CurrPropSysName then
            CurrProp := ptrProperty;
        end;

        if CurrProp <> nil then
        begin
          FOnSetPropValue(Self, TempCompon, CurrProp, CurrPropOldVal, false);
          // Из таблицы удаляем то чего уже нету в комопненте
          for i := 0 to OldSysNames.Count - 1 do
          begin
            if TempCompon.GetPropertyBySysName(OldSysNames[i]) = nil then
            begin
              if mtProps.Locate(fnSysName, OldSysNames[i], []) then
                mtProps.Delete;
            end;
          end;

          // Из компонента убиваем свойства которые есть в гриде
          for i := TempCompon.Properties.Count - 1 downto 0 do
          begin
            ptrProperty := TempCompon.Properties[i];
            if OldSysNames.IndexOf(ptrProperty^.SysName) <> -1 then
              TempCompon.RemovePropertyBySysName(ptrProperty^.SysName);
          end;

          // Те что остались добавляем в таблицу
          TF_Main(GForm).DM.FillMemTablePropFromList(mtProps, TempCompon.Properties, false, true, false);
        end;
        TempCompon.Free;

        mtProps.Locate(fnSysName, CurrPropSysName, []);
      finally
        mtProps.EnableControls;
      end;
    end;
  end;
end;

procedure TF_ObjsProp.btCheckAllClick(Sender: TObject);
begin
  SetIsOnForAll(true);
end;

procedure TF_ObjsProp.btUnCheckAllClick(Sender: TObject);
begin
  SetIsOnForAll(false);
end;

procedure TF_ObjsProp.GT_PROPERTYEditChanged(
  Sender: TcxCustomGridTableView; AItem: TcxCustomGridTableItem);
begin
  FEditedItem := AItem;
end;

procedure TF_ObjsProp.mtPropsAfterPost(DataSet: TDataSet);
var
  SavedEvent: TDataSetNotifyEvent;
begin
  SavedEvent := DataSet.AfterPost;
  try
    DataSet.AfterPost := nil;
    DataSet.Edit;
    DataSet.FieldByName(fnIsModified).AsBoolean := true;
    //02.04.2012
    DataSet.FieldByName(fnPValue).AsFloat := FloatInUOM(DataSet.FieldByName(fnPValue).AsFloat, TF_Main(GForm).FUOM, umMetr);
    DataSet.Post;
  finally
    DataSet.AfterPost := SavedEvent;
  end;
end;

procedure TF_ObjsProp.GT_PROPERTYInitEdit(Sender: TcxCustomGridTableView;
  AItem: TcxCustomGridTableItem; AEdit: TcxCustomEdit);
begin
  if AItem = GT_PROPERTYVALUE then
    AEdit.EditValue := GetDisplayTextInFLoatUOM(AEdit.EditValue, TF_Main(GForm).FUOM);
end;

end.
