unit ULEdUtl;{v0.13}
interface
uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls,
  Forms, Dialogs, StdCtrls,
  UtlType, PropUtl, WinUtl, BtnEdit,
  ULRecTyp, ULObju, ULObjDes;

type
  TFormULObjOption = (foCaption, foOnlyFileNames{v0.24}, foExcludeFocused{/v0.24});
    { foCaption - set form caption to Obj.Desc
      foOnlyFileNames - copy only values of properties of type FileName
      foExcludeFocused - do not copy value of Obj property to it's visual control if it is focused
     }
  TFormULObjOptions = set of TFormULObjOption;

{ Copy values from AForm's components (TEdit, TCheckBox,...) to AObj's fields }
procedure FormToULObj(AForm: TForm; AObj: TULObj; AOptions: TFormULObjOptions; const AStartDir: string);

{ Copy values from AObj's fields to AForm's components (TEdit, TCheckBox,...)  }
procedure ULObjToForm(AObj: TULObj; AForm: TForm; AOptions: TFormULObjOptions; const AStartDir: string);

{v0.62}
{ Copy values from ACtrl's components (TEdit, TCheckBox,...) to AObj's fields }
procedure WinControlToULObj(ACtrl: TWinControl; AObj: TULObj; AOptions: TFormULObjOptions; const AStartDir: string);

{ Copy values from AObj's fields to ACtrl's components (TEdit, TCheckBox,...)  }
procedure ULObjToWinControl(AObj: TULObj; ACtrl: TWinControl; AOptions: TFormULObjOptions; const AStartDir: string);
{/v0.62}

implementation

procedure FormToULObj(AForm: TForm; AObj: TULObj; AOptions: TFormULObjOptions; const AStartDir: string);
var
  c: TObject;
  n: shortstring;
  v: string;
  i: integer;
  f: TULObjField;
{  d: string;
  dch:boolean;}
  Buffer: PChar;
  Size: Integer;
  {v0.24}
  d: string;
  fn, dn: string;
  {/v0.24}
  {v0.36}
  ext: string;
  {/v0.36}

  {v0.44}
  procedure SetFileName;
  begin
    {v0.50}
    f.DefDirNeeded;
    {/v0.50}
    d := f.FldDesc.DefDir;
    ext := f.FldDesc.DefExt;
    if d = '' then
      d := AStartDir;
    if RelativeFileName(d, f.AsUsrString, ext) <> v then begin
      dn := ExtractFilePath(v);
      fn := ExtractFileName(v);
      if (f.FldDesc.DefDir <> '') then begin
        if (dn = f.FldDesc.DefDir) or (dn = '') then
          f.AsUsrString := fn
        else
          f.AsUsrString := AbsoluteFileName(d, v, ext);
      end else begin
        f.AsUsrString := AbsoluteFileName(d, v, ext)
      end;
    end;
  end;
  {/v0.44}

begin
  if (AForm = nil) or (AObj = nil) then
    exit;
  with AForm do begin
    {v0.24}
    AObj.DoChangeLock;
    try
      for i := 0 to ComponentCount - 1 do begin
        c := TObject(Components[i]);
        if c is TEdit then begin
          with c as TEdit do begin
            n := copy(Name, 1, length(Name) - 4);
            v := Text;
            if AObj.HasField(n, f) then begin
              {v0.36}{/v0.36
              if f.FldDesc.IsFileName then begin
                d := f.FldDesc.DefDir;
                if d = '' then
                  d := AStartDir;
                if RelativeFileName(d, f.AsUsrString) <> v then begin
                  f.AsUsrString := AbsoluteFileName(d, v);
                end;
              end else}
              {v0.44}
              if f.FldDesc.IsFileName then begin
                SetFileName;
              end else
              {/v0.44}
              begin
                {v0.14}
                if not (foOnlyFileNames in AOptions) then
                {/v0.14}
                begin
                  f.AsUsrString := v;
                end;
              end;
            end;
          end;
        end {v0.24} else if c is TBtnEdit then begin
          with c as TBtnEdit do begin
            n := copy(Name, 1, length(Name) - 4);
            v := Text;
            if AObj.HasField(n, f) then begin
              if f.FldDesc.IsFileName then begin
                (*v0.44*)

                SetFileName;
                (*/v0.44
                d := f.FldDesc.DefDir;
                {v0.36}
                ext := f.FldDesc.DefExt;
                {/v0.36}
                if d = '' then
                  d := AStartDir;
                if RelativeFileName(d, f.AsUsrString {v0.36}, ext{/v0.36}) <> v then begin
                  {v0.24}
                  dn := ExtractFilePath(v);
                  fn := ExtractFileName(v);
                  if (f.FldDesc.DefDir <> '') then begin
                    if (dn = f.FldDesc.DefDir) or (dn = '') then
                      f.AsUsrString := fn
                    else
                      f.AsUsrString := AbsoluteFileName(d, v {v0.36}, ext{/v0.36});
                  end else begin
                    f.AsUsrString := AbsoluteFileName(d, v {v0.36}, ext{/v0.36})
                  end;
                  {/v0.24
                  f.AsUsrString := v};
                end;
                *)
              end else {v0.44}if f.FldDesc.IsSetType then begin
                f.AsString := v;
              end else{/v0.44}begin
                {v0.14}
                if not (foOnlyFileNames in AOptions) then
                {/v0.14}
                begin
                  f.AsUsrString := v;
                end;
              end;
            end;
          end;

        end {/v0.24}else if c is TComboBox then begin
          {v0.14}
          if not (foOnlyFileNames in AOptions) then
          {/v0.14}
          with c as TComboBox do begin
            n := copy(Name, 1, length(Name) - 4);
            v := Text;
            if AObj.HasField(n, f) then
              f.AsUsrString := v;
          end;    {ulobju}
        end else if c is TCheckBox then begin
          {v0.14}
          if not (foOnlyFileNames in AOptions) then
          {/v0.14}
          with c as TCheckBox do begin
            n := copy(Name, 1, length(Name) - 4);
            if Checked then
              v := 'True'
            else
              v := 'False';
            if AObj.HasField(n, f) then begin
              {v0.61}
              f.AsString := v;
              {/v0.61
              f.AsUsrString := v;}
            end;
          end;
        end else if c is TMemo then begin
          {v0.14}
          if not (foOnlyFileNames in AOptions) then
          {/v0.14}
          with c as TMemo do begin
            n := copy(Name, 1, length(Name) - 4);
            if AObj.HasField(n, f) then begin
              SelectAll;
              Size := SelLength + Lines.Count * 2 + 1;
              GetMem(Buffer, Size);
              try
                GetSelTextBuf(Buffer, Size);
                f.AsUsrString := StrPas(Buffer);
              finally
                FreeMem(Buffer, Size);
              end;
            end;
          end;
        end;
      end;
      if AObj.JustCreated then
        AObj.JustCreated := false;
    finally
      AObj.DoChangeUnlock;
    end;
    SendMessage(Application.MainForm.Handle, WM_APPMESSAGE, cmULObjAfterEdit,
      longint(AObj));
    {v0.44}
    AObj.UsersNotify(cmULObjAfterEdit);
    {/v0.44}
  end;
end;

procedure ULObjToForm(AObj: TULObj; AForm: TForm; AOptions: TFormULObjOptions; const AStartDir: string);
var
  c: TObject;
  pn, n: shortstring;
  v: string;
  i, j: integer;
{  dt: TDateTime;}

  buffer:PChar;
  size:integer;
  {v0.14}
  k: integer;
  {/v0.14}
  {v0.24}
  d: string;
  {/v0.24}

  {v0.24}
  {v0.30}
  fd: TULObjFldDesc;
  {/v0.30}

  {v0.36}
  ext: string;
  {/v0.36}

  {v0.61}
  ss: shortstring;
  {/v0.61}
  
  function CanCopyTo:boolean;
  begin
    Result := true;
    if foExcludeFocused in AOptions then begin
      if c is TWinControl then with c as TWinControl do
        CanCopyTo := not Focused;
    end;
  end;
  {/v0.24}

  {v0.44}
  function GetFileName: string;
  begin
    {v0.50}
    AObj.Fields[i].DefDirNeeded;
    {/v0.50}
    d := AObj.Fields[i].FldDesc.DefDir;
    if d = '' then
      d := AStartDir;
    ext := AObj.Fields[i].FldDesc.DefExt;
    Result := RelativeFileName(d, v, ext);
  end;
  {/v0.44}

begin
  if (AObj = nil) or (AForm = nil) then
    exit;
  {v0.14} {/v0.14 GetDir(0, AStartDir);}
  with AForm do begin
    if foCaption in AOptions then
      Caption := AObj.ObjDesc.Caption + ' (' + AObj.RootFileDir + ') '
        + ExtractFileName(AObj.RootFileName);
    for i := 0 to AObj.ObjDesc.FieldCount - 1 do begin
      pn := AObj.ObjDesc.Fields[i].Name;
      v := AObj.Fields[i].AsUsrString;
      n := pn + 'Edit';
      for j := 0 to ComponentCount - 1 do begin
        c := Components[j];
        if c is TEdit then begin
          with c as TEdit do {v0.13 if force or (not Modified) then{/v0.13} begin
            if Name = n then begin
              {v0.25}
              Hint := AObj.Fields[i].FldDesc.Hint;
              {v0.25}
              if AObj.IsFlagSet(rfWriteLocked) then
                ReadOnly := true;
              {/v0.15}
              {v0.13}
              {v0.36}{/v0.36
              if AObj.Fields[i].FldDesc.IsFileName then begin
                d := AObj.Fields[i].FldDesc.DefDir;
                if d = '' then
                  d := AStartDir;
                Text := RelativeFileName(d, v);
              end else}
              {/v0.13}
              begin
               {v0.14} if not (foOnlyFileNames in AOptions) then {/v0.14}
               begin
                 Text := v;
               end{v0.44} else begin
                 if AObj.Fields[i].FldDesc.IsFileName then
                   Text := GetFileName;
               end{/v0.44};
              end;
            end;
          end;
        end {v0.24}else if c is TBtnEdit then begin
          with c as TBtnEdit do begin
            if Name = n then begin
              {v0.25}
              Hint := AObj.Fields[i].FldDesc.Hint;
              {v0.25}
              {v0.50} {ulrectyp}
              EmptyAllowed := not AObj.Fields[i].FldDesc.Required;
              {/v0.50}
              if AObj.IsFlagSet(rfWriteLocked) then
                ReadOnly := true;
              if AObj.Fields[i].FldDesc.IsFileName then begin
                (*v0.44*)
                Text := GetFileName;
                (*/v0.44
                d := AObj.Fields[i].FldDesc.DefDir;
                if d = '' then
                  d := AStartDir;
                {v0.36}
                ext := AObj.Fields[i].FldDesc.DefExt;
                {/v0.36}
                Text := RelativeFileName(d, v {v0.36}, ext{/v0.36});
                *)
              end else {v0.44}if AObj.Fields[i].FldDesc.IsSetType then begin
                Text := v;
              end else {/v0.44}begin
                if not (foOnlyFileNames in AOptions) then
                 Text := v;
              end;
            end;
          end;
        end{/v0.24}else if c is TComboBox then begin
         {v0.14} if not (foOnlyFileNames in AOptions) then {/v0.14}
          with c as TComboBox do {v0.13 if force or (not Modified) then{/v0.13} begin
            if Name = n then begin
              {v0.25}
              Hint := AObj.Fields[i].FldDesc.Hint;
              {v0.25}
              {v0.15}
              if AObj.IsFlagSet(rfWriteLocked) then
                Enabled := false;
              {/v0.15}
              {v0.14}
              if AObj.ObjDesc.Fields[i].IsULEnum then begin
                AObj.FillULEnumNames(i, Items);
              end else
              {/v0.14}
              begin
                {v0.30}
                fd := AObj.ObjDesc.Fields[i];
                if fd.IsEnum then begin
                  fd.FillComboBoxItems(Items);
                end else
                {/v0.30}
                begin
                  FillEnumNames(AObj, pn, Items);
                end;
              end;
              {v0.14}
              if Style = csDropDownList then begin
                {v0.30}
                {ulstringgrid}
                {/v0.30}
                for k := 0 to Items.Count - 1 do begin
                  if Items[k] = v then begin
                    ItemIndex := k;
                    break;
                  end;
                end;
              end else
              {/v0.14}
              begin
                Text := v;
              end;
            end;
          end;
        end else if c is TCheckBox then {v0.13 if force or (not Modified) then{/v0.13} begin
         {v0.14} if not (foOnlyFileNames in AOptions) then {/v0.14}
          with c as TCheckBox do begin
            if Name = n then begin
              {v0.25}
              Hint := AObj.Fields[i].FldDesc.Hint;
              {v0.25}
              {v0.15}
              if AObj.IsFlagSet(rfWriteLocked) then
                Enabled := false;
              {/v0.15}
              {v0.61}
              ss := AObj.Fields[i].AsString;
              Checked := (ss = 'True')
              {/v0.61
              Checked := (v = 'True');}
            end;
          end;
        end else if c is TMemo then begin
         {v0.14} if not (foOnlyFileNames in AOptions) then {/v0.14}
          with c as TMemo do begin
            if Name = n then begin
              {v0.25}
              Hint := AObj.Fields[i].FldDesc.Hint;
              {v0.25}
              {v0.15}
              if AObj.IsFlagSet(rfWriteLocked) then
                Enabled := false;
              {/v0.15}
              SelectAll;
              size := length(v) + 1;
              GetMem(Buffer, size);
              try
                StrPCopy(Buffer, v);
                SetSelTextBuf(Buffer);
              finally
                FreeMem(Buffer);
              end;
            end;
          end;
        end;
      end;
    end;
  end;
end;


{v0.62}
{ Copy values from ACtrl's components (TEdit, TCheckBox,...) to AObj's fields }
procedure WinControlToULObj(ACtrl: TWinControl; AObj: TULObj; AOptions: TFormULObjOptions; const AStartDir: string);
var
  c: TObject;
  n: shortstring;
  v: string;
  i: integer;
  f: TULObjField;
  Buffer: PChar;
  Size: Integer;
  d: string;
  fn, dn: string;
  ext: string;

  procedure SetFileName;
  begin
    f.DefDirNeeded;
    d := f.FldDesc.DefDir;
    ext := f.FldDesc.DefExt;
    if d = '' then
      d := AStartDir;
    if RelativeFileName(d, f.AsUsrString, ext) <> v then begin
      dn := ExtractFilePath(v);
      fn := ExtractFileName(v);
      if (f.FldDesc.DefDir <> '') then begin
        if (dn = f.FldDesc.DefDir) or (dn = '') then
          f.AsUsrString := fn
        else
          f.AsUsrString := AbsoluteFileName(d, v, ext);
      end else begin
        f.AsUsrString := AbsoluteFileName(d, v, ext)
      end;
    end;
  end;

begin
  if (ACtrl = nil) or (AObj = nil) then
    exit;
  with ACtrl do begin
    AObj.DoChangeLock;
    try
      for i := 0 to ComponentCount - 1 do begin
        c := TObject(Components[i]);
        if c is TEdit then begin
          with c as TEdit do begin
            n := copy(Name, 1, length(Name) - 4);
            v := Text;
            if AObj.HasField(n, f) then begin
              if f.FldDesc.IsFileName then begin
                SetFileName;
              end else begin
                if not (foOnlyFileNames in AOptions) then begin
                  f.AsUsrString := v;
                end;
              end;
            end;
          end;
        end else if c is TBtnEdit then begin
          with c as TBtnEdit do begin
            n := copy(Name, 1, length(Name) - 4);
            v := Text;
            if AObj.HasField(n, f) then begin
              if f.FldDesc.IsFileName then begin
                SetFileName;
              end else if f.FldDesc.IsSetType then begin
                f.AsString := v;
              end else begin
                if not (foOnlyFileNames in AOptions) then begin
                  f.AsUsrString := v;
                end;
              end;
            end;
          end;
        end else if c is TComboBox then begin
          if not (foOnlyFileNames in AOptions) then
          with c as TComboBox do begin
            n := copy(Name, 1, length(Name) - 4);
            v := Text;
            if AObj.HasField(n, f) then
              f.AsUsrString := v;
          end;
        end else if c is TCheckBox then begin
          if not (foOnlyFileNames in AOptions) then
          with c as TCheckBox do begin
            n := copy(Name, 1, length(Name) - 4);
            if Checked then
              v := 'True'
            else
              v := 'False';
            if AObj.HasField(n, f) then begin
              f.AsString := v;
            end;
          end;
        end else if c is TMemo then begin
          if not (foOnlyFileNames in AOptions) then
          with c as TMemo do begin
            n := copy(Name, 1, length(Name) - 4);
            if AObj.HasField(n, f) then begin
              SelectAll;
              Size := SelLength + Lines.Count * 2 + 1;
              GetMem(Buffer, Size);
              try
                GetSelTextBuf(Buffer, Size);
                f.AsUsrString := StrPas(Buffer);
              finally
                FreeMem(Buffer, Size);
              end;
            end;
          end;
        end;
      end;
      if AObj.JustCreated then
        AObj.JustCreated := false;
    finally
      AObj.DoChangeUnlock;
    end;
    SendMessage(Application.MainForm.Handle, WM_APPMESSAGE, cmULObjAfterEdit,
      longint(AObj));
    AObj.UsersNotify(cmULObjAfterEdit);
  end;
end;

{ Copy values from AObj's fields to ACtrl's components (TEdit, TCheckBox,...)  }
procedure ULObjToWinControl(AObj: TULObj; ACtrl: TWinControl;
  AOptions: TFormULObjOptions; const AStartDir: string);
var
  c: TObject;
  pn, n: shortstring;
  v: string;
  i, j: integer;
  buffer:PChar;
  size:integer;
  k: integer;
  d: string;
  fd: TULObjFldDesc;
  ext: string;
  ss: shortstring;

  function CanCopyTo:boolean;
  begin
    Result := true;
    if foExcludeFocused in AOptions then begin
      if c is TWinControl then with c as TWinControl do
        CanCopyTo := not Focused;
    end;
  end;

  function GetFileName: string;
  begin
    AObj.Fields[i].DefDirNeeded;
    d := AObj.Fields[i].FldDesc.DefDir;
    if d = '' then
      d := AStartDir;
    ext := AObj.Fields[i].FldDesc.DefExt;
    Result := RelativeFileName(d, v, ext);
  end;

begin
  if (AObj = nil) or (ACtrl = nil) then
    exit;
  with ACtrl do begin
    if foCaption in AOptions then begin
      if ACtrl is TForm then begin
        TForm(ACtrl).Caption := AObj.ObjDesc.Caption + ' (' + AObj.RootFileDir + ') '
          + ExtractFileName(AObj.RootFileName);
      end;
    end;

    for i := 0 to AObj.ObjDesc.FieldCount - 1 do begin
      pn := AObj.ObjDesc.Fields[i].Name;
      v := AObj.Fields[i].AsUsrString;
      n := pn + 'Edit';
      for j := 0 to ComponentCount - 1 do begin
        c := Components[j];
        if c is TEdit then begin
          with c as TEdit do begin
            if Name = n then begin
              Hint := AObj.Fields[i].FldDesc.Hint;
              if AObj.IsFlagSet(rfWriteLocked) then
                ReadOnly := true;
              if not (foOnlyFileNames in AOptions) then begin
                Text := v;
              end else begin
                if AObj.Fields[i].FldDesc.IsFileName then
                  Text := GetFileName;
              end;
            end;
          end;
        end else if c is TBtnEdit then begin
          with c as TBtnEdit do begin
            if Name = n then begin
              Hint := AObj.Fields[i].FldDesc.Hint;
              EmptyAllowed := not AObj.Fields[i].FldDesc.Required;
              if AObj.IsFlagSet(rfWriteLocked) then
                ReadOnly := true;
              if AObj.Fields[i].FldDesc.IsFileName then begin
                Text := GetFileName;
              end else if AObj.Fields[i].FldDesc.IsSetType then begin
                Text := v;
              end else begin
                if not (foOnlyFileNames in AOptions) then
                 Text := v;
              end;
            end;
          end;
        end else if c is TComboBox then begin
          if not (foOnlyFileNames in AOptions) then
          with c as TComboBox do begin
            if Name = n then begin
              Hint := AObj.Fields[i].FldDesc.Hint;
              if AObj.IsFlagSet(rfWriteLocked) then
                Enabled := false;
              if AObj.ObjDesc.Fields[i].IsULEnum then begin
                AObj.FillULEnumNames(i, Items);
              end else begin
                fd := AObj.ObjDesc.Fields[i];
                if fd.IsEnum then begin
                  fd.FillComboBoxItems(Items);
                end else begin
                  FillEnumNames(AObj, pn, Items);
                end;
              end;
              if Style = csDropDownList then begin
                for k := 0 to Items.Count - 1 do begin
                  if Items[k] = v then begin
                    ItemIndex := k;
                    break;
                  end;
                end;
              end else begin
                Text := v;
              end;
            end;
          end;
        end else if c is TCheckBox then begin
          if not (foOnlyFileNames in AOptions) then
          with c as TCheckBox do begin
            if Name = n then begin
              Hint := AObj.Fields[i].FldDesc.Hint;
              if AObj.IsFlagSet(rfWriteLocked) then
                Enabled := false;
              ss := AObj.Fields[i].AsString;
              Checked := (ss = 'True')
            end;
          end;
        end else if c is TMemo then begin
          if not (foOnlyFileNames in AOptions) then
          with c as TMemo do begin
            if Name = n then begin
              Hint := AObj.Fields[i].FldDesc.Hint;
              if AObj.IsFlagSet(rfWriteLocked) then
                Enabled := false;
              SelectAll;
              size := length(v) + 1;
              GetMem(Buffer, size);
              try
                StrPCopy(Buffer, v);
                SetSelTextBuf(Buffer);
              finally
                FreeMem(Buffer);
              end;
            end;
          end;
        end;
      end;
    end;
  end;
end;
{/v0.62}


end.
