245 lines
7.0 KiB
ObjectPascal
245 lines
7.0 KiB
ObjectPascal
{-----------------------------------------------------------------------------
|
||
The contents of this file are subject to the Mozilla Public License
|
||
Version 1.1 (the "License"); you may not use this file except in compliance
|
||
with the License. You may obtain a copy of the License at
|
||
http://www.mozilla.org/MPL/MPL-1.1.html
|
||
|
||
Software distributed under the License is distributed on an "AS IS" basis,
|
||
WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See the License for
|
||
the specific language governing rights and limitations under the License.
|
||
|
||
The Original Code is: JvgRttiUtils.PAS, released on 2003-01-15.
|
||
|
||
The Initial Developer of the Original Code is Andrey V. Chudin, [chudin att yandex dott ru]
|
||
Portions created by Andrey V. Chudin are Copyright (C) 2003 Andrey V. Chudin.
|
||
All Rights Reserved.
|
||
|
||
Contributor(s):
|
||
Michael Beck [mbeck att bigfoot dott com].
|
||
Burov Dmitry, translation of russian text.
|
||
|
||
You may retrieve the latest version of this file at the Project JEDI's JVCL home page,
|
||
located at http://jvcl.sourceforge.net
|
||
|
||
Known Issues:
|
||
-----------------------------------------------------------------------------}
|
||
// $Id: JvgRttiUtils.pas 10610 2006-05-19 13:35:08Z elahn $
|
||
|
||
unit JvgRttiUtils;
|
||
|
||
{$I jvcl.inc}
|
||
|
||
interface
|
||
|
||
{$IFDEF USEJVCL}
|
||
{$IFDEF UNITVERSIONING}
|
||
uses
|
||
JclUnitVersioning;
|
||
{$ENDIF UNITVERSIONING}
|
||
{$ENDIF USEJVCL}
|
||
{ Procedures for comfort working with objects' properties via RTTI }
|
||
|
||
function GetValueFromPropertyName(Component: TObject; const PropertyName: string): string;
|
||
procedure SetValueByPropertyName(Component: TObject; const PropertyName, PropertyValue: string);
|
||
procedure Assign(Source, Target: TObject; Recursive: Boolean);
|
||
|
||
{$IFDEF USEJVCL}
|
||
{$IFDEF UNITVERSIONING}
|
||
const
|
||
UnitVersioning: TUnitVersionInfo = (
|
||
RCSfile: '$RCSfile$';
|
||
Revision: '$Revision: 10610 $';
|
||
Date: '$Date: 2006-05-19 15:35:08 +0200 (ven., 19 mai 2006) $';
|
||
LogPath: 'JVCL\run'
|
||
);
|
||
{$ENDIF UNITVERSIONING}
|
||
{$ENDIF USEJVCL}
|
||
|
||
implementation
|
||
|
||
uses
|
||
Classes, SysUtils, TypInfo;
|
||
|
||
function GetValueFromPropertyName(Component: TObject; const PropertyName: string): string;
|
||
var
|
||
PropInfo: PPropInfo;
|
||
TypeInf, PropTypeInf: PTypeInfo;
|
||
TypeData: PTypeData;
|
||
I: Integer;
|
||
AName, PropName: string;
|
||
PropList: PPropList;
|
||
NumProps: Word;
|
||
PropObject: TObject;
|
||
begin
|
||
{ Playing with RTTI }
|
||
TypeInf := Component.ClassInfo;
|
||
AName := TypeInf^.Name;
|
||
TypeData := GetTypeData(TypeInf);
|
||
NumProps := TypeData^.PropCount;
|
||
|
||
Result := '';
|
||
GetMem(PropList, NumProps * SizeOf(Pointer));
|
||
try
|
||
//{ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> }
|
||
{ Retrieving list of properties [translated] }
|
||
GetPropInfos(TypeInf, PropList);
|
||
|
||
for I := 0 to NumProps - 1 do
|
||
begin
|
||
PropName := PropList^[I]^.Name;
|
||
PropTypeInf := PropList^[I]^.PropType^;
|
||
PropInfo := PropList^[I];
|
||
|
||
if PropTypeInf^.Kind = tkClass then
|
||
begin
|
||
PropObject := GetObjectProp(Component, PropInfo);
|
||
Result := GetValueFromPropertyName(PropObject, PropertyName);
|
||
end
|
||
else
|
||
if CompareText(PropName, PropertyName) = 0 then
|
||
begin
|
||
Result := GetPropValue(Component, PropName, True);
|
||
Break;
|
||
end;
|
||
|
||
if Result <> '' then
|
||
Exit;
|
||
end;
|
||
finally
|
||
FreeMem(PropList);
|
||
end;
|
||
end;
|
||
|
||
procedure SetValueByPropertyName(Component: TObject; const PropertyName, PropertyValue: string);
|
||
var
|
||
PropInfo: PPropInfo;
|
||
TypeInf, PropTypeInf: PTypeInfo;
|
||
TypeData: PTypeData;
|
||
I: Integer;
|
||
AName, PropName: string;
|
||
PropList: PPropList;
|
||
NumProps: Word;
|
||
PropObject: TObject;
|
||
begin
|
||
{ Playing with RTTI }
|
||
TypeInf := Component.ClassInfo;
|
||
AName := TypeInf^.Name;
|
||
TypeData := GetTypeData(TypeInf);
|
||
NumProps := TypeData^.PropCount;
|
||
|
||
GetMem(PropList, NumProps * SizeOf(Pointer));
|
||
try
|
||
//{ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> }
|
||
{ Retrieving list of properties [translated] }
|
||
GetPropInfos(TypeInf, PropList);
|
||
|
||
for I := 0 to NumProps - 1 do
|
||
begin
|
||
PropName := PropList^[I]^.Name;
|
||
PropTypeInf := PropList^[I]^.PropType^;
|
||
PropInfo := PropList^[I];
|
||
|
||
if PropTypeInf^.Kind = tkClass then
|
||
begin
|
||
PropObject := GetObjectProp(Component, PropInfo);
|
||
SetValueByPropertyName(PropObject, PropertyName, PropertyValue);
|
||
end
|
||
else
|
||
if CompareText(PropName, PropertyName) = 0 then
|
||
begin
|
||
SetPropValue(Component, PropName, PropertyValue);
|
||
Break;
|
||
end;
|
||
end;
|
||
finally
|
||
FreeMem(PropList);
|
||
end;
|
||
end;
|
||
|
||
procedure Assign(Source, Target: TObject; Recursive: Boolean);
|
||
var
|
||
{TypeInf, } PropTypeInf: PTypeInfo;
|
||
I, Index: Integer;
|
||
PropName: string;
|
||
Source_PropList, Target_PropList: PPropList;
|
||
Source_NumProps, Target_NumProps: Word;
|
||
Source_PropObject, Target_PropObject: TObject;
|
||
|
||
//{ <20><><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> }
|
||
{ Searching for given name in the list of properties [translated] }
|
||
|
||
function FindProperty(const PropName: string; PropList: PPropList; NumProps: Word): Integer;
|
||
var
|
||
I: Integer;
|
||
begin
|
||
Result := -1;
|
||
for I := 0 to NumProps - 1 do
|
||
if CompareStr(PropList^[I]^.Name, PropName) = 0 then
|
||
begin
|
||
Result := I;
|
||
Break;
|
||
end;
|
||
end;
|
||
|
||
begin
|
||
if not Assigned(Source) or not Assigned(Target) then
|
||
Exit;
|
||
|
||
{ Playing with RTTI }
|
||
Source_NumProps := GetTypeData(Source.ClassInfo)^.PropCount;
|
||
Target_NumProps := GetTypeData(Target.ClassInfo)^.PropCount;
|
||
|
||
GetMem(Source_PropList, Source_NumProps * SizeOf(Pointer));
|
||
GetMem(Target_PropList, Target_NumProps * SizeOf(Pointer));
|
||
try
|
||
//{ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> }
|
||
{ Retrieving list of properties [translated] }
|
||
GetPropInfos(Source.ClassInfo, Source_PropList);
|
||
GetPropInfos(Target.ClassInfo, Target_PropList);
|
||
|
||
for I := 0 to Source_NumProps - 1 do
|
||
begin
|
||
PropName := Source_PropList^[I]^.Name;
|
||
|
||
Index := FindProperty(PropName, Target_PropList, Target_NumProps);
|
||
if Index = -1 then
|
||
Continue; // <20><> <20><><EFBFBD><EFBFBD><EFBFBD>, Not found [translated]
|
||
|
||
//{ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> }
|
||
{ check whether the types do match }
|
||
if Source_PropList^[I]^.PropType^.Kind <> Target_PropList^[I]^.PropType^.Kind then
|
||
Continue;
|
||
|
||
PropTypeInf := Source_PropList^[I]^.PropType^;
|
||
// PropInfo := PropList^[I];
|
||
if PropTypeInf^.Kind = tkClass then
|
||
begin
|
||
if Recursive then
|
||
begin
|
||
Source_PropObject := GetObjectProp(Source, Source.ClassInfo);
|
||
Target_PropObject := GetObjectProp(Target, Target.ClassInfo);
|
||
Assign(Source_PropObject, Target_PropObject, Recursive);
|
||
end;
|
||
end
|
||
else
|
||
SetPropValue(Target, PropName, GetPropValue(Source, PropName));
|
||
end;
|
||
finally
|
||
FreeMem(Source_PropList);
|
||
FreeMem(Target_PropList);
|
||
end;
|
||
end;
|
||
|
||
{$IFDEF USEJVCL}
|
||
{$IFDEF UNITVERSIONING}
|
||
initialization
|
||
RegisterUnitVersion(HInstance, UnitVersioning);
|
||
|
||
finalization
|
||
UnregisterUnitVersion(HInstance);
|
||
{$ENDIF UNITVERSIONING}
|
||
{$ENDIF USEJVCL}
|
||
|
||
end.
|
||
|