1067 lines
29 KiB
ObjectPascal
1067 lines
29 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: JvProps.PAS, released on 2002-07-04.
|
|
|
|
The Initial Developers of the Original Code are: Fedor Koshevnikov, Igor Pavluk and Serge Korolev
|
|
Copyright (c) 1997, 1998 Fedor Koshevnikov, Igor Pavluk and Serge Korolev
|
|
Copyright (c) 2001,2002 SGB Software
|
|
All Rights Reserved.
|
|
|
|
Last Modified: 2002-07-04
|
|
|
|
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:
|
|
-----------------------------------------------------------------------------}
|
|
|
|
{$I JVCL.INC}
|
|
|
|
unit JvProps;
|
|
|
|
interface
|
|
|
|
uses
|
|
SysUtils, Classes, Forms, TypInfo;
|
|
|
|
type
|
|
TJvPropInfoList = class(TObject)
|
|
private
|
|
FList: PPropList;
|
|
FCount: Integer;
|
|
FSize: Integer;
|
|
function Get(Index: Integer): PPropInfo;
|
|
public
|
|
constructor Create(AObject: TObject; Filter: TTypeKinds);
|
|
destructor Destroy; override;
|
|
function Contains(P: PPropInfo): Boolean;
|
|
function Find(const AName: string): PPropInfo;
|
|
procedure Delete(Index: Integer);
|
|
procedure Intersect(List: TJvPropInfoList);
|
|
property Count: Integer read FCount;
|
|
property Items[Index: Integer]: PPropInfo read Get; default;
|
|
end;
|
|
|
|
TReadStrEvent = function(const ASection, Item, Default: string): string of object;
|
|
TWriteStrEvent = procedure(const ASection, Item, Value: string) of object;
|
|
TEraseSectEvent = procedure(const ASection: string) of object;
|
|
|
|
TJvPropsStorage = class(TObject)
|
|
private
|
|
FObject: TObject;
|
|
FOwner: TComponent;
|
|
FPrefix: string;
|
|
FSection: string;
|
|
FOnReadString: TReadStrEvent;
|
|
FOnWriteString: TWriteStrEvent;
|
|
FOnEraseSection: TEraseSectEvent;
|
|
function StoreIntegerProperty(PropInfo: PPropInfo): string;
|
|
function StoreCharProperty(PropInfo: PPropInfo): string;
|
|
function StoreEnumProperty(PropInfo: PPropInfo): string;
|
|
function StoreFloatProperty(PropInfo: PPropInfo): string;
|
|
function StoreStringProperty(PropInfo: PPropInfo): string;
|
|
function StoreSetProperty(PropInfo: PPropInfo): string;
|
|
function StoreClassProperty(PropInfo: PPropInfo): string;
|
|
function StoreStringsProperty(PropInfo: PPropInfo): string;
|
|
function StoreComponentProperty(PropInfo: PPropInfo): string;
|
|
{$IFDEF WIN32}
|
|
function StoreLStringProperty(PropInfo: PPropInfo): string;
|
|
function StoreWCharProperty(PropInfo: PPropInfo): string;
|
|
function StoreVariantProperty(PropInfo: PPropInfo): string;
|
|
procedure LoadLStringProperty(const S: string; PropInfo: PPropInfo);
|
|
procedure LoadWCharProperty(const S: string; PropInfo: PPropInfo);
|
|
procedure LoadVariantProperty(const S: string; PropInfo: PPropInfo);
|
|
{$ENDIF}
|
|
{$IFDEF COMPILER4_UP}
|
|
function StoreInt64Property(PropInfo: PPropInfo): string;
|
|
procedure LoadInt64Property(const S: string; PropInfo: PPropInfo);
|
|
{$ENDIF}
|
|
procedure LoadIntegerProperty(const S: string; PropInfo: PPropInfo);
|
|
procedure LoadCharProperty(const S: string; PropInfo: PPropInfo);
|
|
procedure LoadEnumProperty(const S: string; PropInfo: PPropInfo);
|
|
procedure LoadFloatProperty(const S: string; PropInfo: PPropInfo);
|
|
procedure LoadStringProperty(const S: string; PropInfo: PPropInfo);
|
|
procedure LoadSetProperty(const S: string; PropInfo: PPropInfo);
|
|
procedure LoadClassProperty(const S: string; PropInfo: PPropInfo);
|
|
procedure LoadStringsProperty(const S: string; PropInfo: PPropInfo);
|
|
procedure LoadComponentProperty(const S: string; PropInfo: PPropInfo);
|
|
function CreateInfoList(AComponent: TComponent; StoredList: TStrings): TStrings;
|
|
procedure FreeInfoLists(Info: TStrings);
|
|
protected
|
|
function ReadString(const ASection, Item, Default: string): string; virtual;
|
|
procedure WriteString(const ASection, Item, Value: string); virtual;
|
|
procedure EraseSection(const ASection: string); virtual;
|
|
function GetItemName(const APropName: string): string; virtual;
|
|
function CreateStorage: TJvPropsStorage; virtual;
|
|
public
|
|
procedure StoreAnyProperty(PropInfo: PPropInfo);
|
|
procedure LoadAnyProperty(PropInfo: PPropInfo);
|
|
procedure StoreProperties(PropList: TStrings);
|
|
procedure LoadProperties(PropList: TStrings);
|
|
procedure LoadObjectsProps(AComponent: TComponent; StoredList: TStrings);
|
|
procedure StoreObjectsProps(AComponent: TComponent; StoredList: TStrings);
|
|
property AObject: TObject read FObject write FObject;
|
|
property Prefix: string read FPrefix write FPrefix;
|
|
property Section: string read FSection write FSection;
|
|
property OnReadString: TReadStrEvent read FOnReadString write FOnReadString;
|
|
property OnWriteString: TWriteStrEvent read FOnWriteString write FOnWriteString;
|
|
property OnEraseSection: TEraseSectEvent read FOnEraseSection write FOnEraseSection;
|
|
end;
|
|
|
|
{ Utility routines }
|
|
|
|
procedure UpdateStoredList(AComponent: TComponent; AStoredList: TStrings; FromForm: Boolean);
|
|
function CreateStoredItem(const CompName, PropName: string): string;
|
|
function ParseStoredItem(const Item: string; var CompName, PropName: string): Boolean;
|
|
|
|
const
|
|
{$IFDEF WIN32}
|
|
sPropNameDelimiter: string = '_';
|
|
{$ELSE}
|
|
sPropNameDelimiter: Char = '_';
|
|
{$ENDIF}
|
|
|
|
implementation
|
|
|
|
uses
|
|
{$IFNDEF WIN32}
|
|
WinTypes, WinProcs,
|
|
JvStr16,
|
|
{$ENDIF}
|
|
JvStrUtils;
|
|
|
|
const
|
|
sCount = 'Count';
|
|
sItem = 'Item%d';
|
|
sNull = '(null)';
|
|
|
|
type
|
|
TCardinalSet = set of 0..SizeOf(Cardinal) * 8 - 1;
|
|
|
|
{$IFNDEF WIN32}
|
|
function GetEnumName(TypeInfo: PTypeInfo; Value: Integer): string;
|
|
begin
|
|
Result := TypInfo.GetEnumName(TypeInfo, Value)^;
|
|
end;
|
|
{$ENDIF}
|
|
|
|
function GetPropType(PropInfo: PPropInfo): PTypeInfo;
|
|
begin
|
|
{$IFDEF COMPILER3_UP}
|
|
Result := PropInfo^.PropType^;
|
|
{$ELSE}
|
|
Result := PropInfo^.PropType;
|
|
{$ENDIF}
|
|
end;
|
|
|
|
//=== TJvPropInfoList ========================================================
|
|
|
|
constructor TJvPropInfoList.Create(AObject: TObject; Filter: TTypeKinds);
|
|
begin
|
|
inherited Create;
|
|
if AObject <> nil then
|
|
begin
|
|
FCount := GetPropList(AObject.ClassInfo, Filter, nil);
|
|
FSize := FCount * SizeOf(Pointer);
|
|
GetMem(FList, FSize);
|
|
GetPropList(AObject.ClassInfo, Filter, FList);
|
|
end
|
|
else
|
|
begin
|
|
FCount := 0;
|
|
FList := nil;
|
|
end;
|
|
end;
|
|
|
|
destructor TJvPropInfoList.Destroy;
|
|
begin
|
|
if FList <> nil then
|
|
FreeMem(FList, FSize);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TJvPropInfoList.Contains(P: PPropInfo): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := 0 to FCount - 1 do
|
|
with FList^[I]^ do
|
|
if (PropType = P^.PropType) and (CompareText(Name, P^.Name) = 0) then
|
|
begin
|
|
Result := True;
|
|
Exit;
|
|
end;
|
|
Result := False;
|
|
end;
|
|
|
|
function TJvPropInfoList.Find(const AName: string): PPropInfo;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := 0 to FCount - 1 do
|
|
with FList^[I]^ do
|
|
if CompareText(Name, AName) = 0 then
|
|
begin
|
|
Result := FList^[I];
|
|
Exit;
|
|
end;
|
|
Result := nil;
|
|
end;
|
|
|
|
procedure TJvPropInfoList.Delete(Index: Integer);
|
|
begin
|
|
Dec(FCount);
|
|
if Index < FCount then
|
|
Move(FList^[Index + 1], FList^[Index], (FCount - Index) * SizeOf(Pointer));
|
|
end;
|
|
|
|
function TJvPropInfoList.Get(Index: Integer): PPropInfo;
|
|
begin
|
|
Result := FList^[Index];
|
|
end;
|
|
|
|
procedure TJvPropInfoList.Intersect(List: TJvPropInfoList);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := FCount - 1 downto 0 do
|
|
if not List.Contains(FList^[I]) then
|
|
Delete(I);
|
|
end;
|
|
|
|
{ Utility routines }
|
|
|
|
function CreateStoredItem(const CompName, PropName: string): string;
|
|
begin
|
|
Result := '';
|
|
if (CompName <> '') and (PropName <> '') then
|
|
Result := CompName + '.' + PropName;
|
|
end;
|
|
|
|
function ParseStoredItem(const Item: string; var CompName, PropName: string): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := False;
|
|
if Length(Item) = 0 then
|
|
Exit;
|
|
I := Pos('.', Item);
|
|
if I > 0 then
|
|
begin
|
|
CompName := Trim(Copy(Item, 1, I - 1));
|
|
PropName := Trim(Copy(Item, I + 1, MaxInt));
|
|
Result := (Length(CompName) > 0) and (Length(PropName) > 0);
|
|
end;
|
|
end;
|
|
|
|
function ReplaceComponentName(const Item, CompName: string): string;
|
|
var
|
|
ACompName, APropName: string;
|
|
begin
|
|
Result := '';
|
|
if ParseStoredItem(Item, ACompName, APropName) then
|
|
Result := CreateStoredItem(CompName, APropName);
|
|
end;
|
|
|
|
procedure UpdateStoredList(AComponent: TComponent; AStoredList: TStrings; FromForm: Boolean);
|
|
var
|
|
I: Integer;
|
|
Component: TComponent;
|
|
CompName, PropName: string;
|
|
begin
|
|
if (AStoredList = nil) or (AComponent = nil) then
|
|
Exit;
|
|
for I := AStoredList.Count - 1 downto 0 do
|
|
begin
|
|
if ParseStoredItem(AStoredList[I], CompName, PropName) then
|
|
begin
|
|
if FromForm then
|
|
begin
|
|
Component := AComponent.FindComponent(CompName);
|
|
if Component = nil then
|
|
AStoredList.Delete(I)
|
|
else
|
|
AStoredList.Objects[I] := Component;
|
|
end
|
|
else
|
|
begin
|
|
Component := TComponent(AStoredList.Objects[I]);
|
|
if Component <> nil then
|
|
AStoredList[I] := ReplaceComponentName(AStoredList[I], Component.Name)
|
|
else
|
|
AStoredList.Delete(I);
|
|
end;
|
|
end
|
|
else
|
|
AStoredList.Delete(I);
|
|
end;
|
|
end;
|
|
|
|
{$IFDEF WIN32}
|
|
function FindGlobalComponent(const Name: string): TComponent;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := 0 to Screen.FormCount - 1 do
|
|
begin
|
|
Result := Screen.Forms[I];
|
|
if CompareText(Name, Result.Name) = 0 then
|
|
Exit;
|
|
end;
|
|
for I := 0 to Screen.DataModuleCount - 1 do
|
|
begin
|
|
Result := Screen.DataModules[I];
|
|
if CompareText(Name, Result.Name) = 0 then
|
|
Exit;
|
|
end;
|
|
Result := nil;
|
|
end;
|
|
{$ENDIF}
|
|
|
|
//=== TJvPropsStorage ========================================================
|
|
|
|
function TJvPropsStorage.GetItemName(const APropName: string): string;
|
|
begin
|
|
Result := Prefix + APropName;
|
|
end;
|
|
|
|
procedure TJvPropsStorage.LoadAnyProperty(PropInfo: PPropInfo);
|
|
var
|
|
S, Def: string;
|
|
begin
|
|
try
|
|
if PropInfo <> nil then
|
|
begin
|
|
case PropInfo^.PropType^.Kind of
|
|
tkInteger:
|
|
Def := StoreIntegerProperty(PropInfo);
|
|
tkChar:
|
|
Def := StoreCharProperty(PropInfo);
|
|
tkEnumeration:
|
|
Def := StoreEnumProperty(PropInfo);
|
|
tkFloat:
|
|
Def := StoreFloatProperty(PropInfo);
|
|
{$IFDEF WIN32}
|
|
tkWChar:
|
|
Def := StoreWCharProperty(PropInfo);
|
|
tkLString:
|
|
Def := StoreLStringProperty(PropInfo);
|
|
{$IFNDEF COMPILER3_UP} { - Delphi 2.0, C++Builder 1.0 }
|
|
tkLWString:
|
|
Def := StoreLStringProperty(PropInfo);
|
|
{$ENDIF}
|
|
tkVariant:
|
|
Def := StoreVariantProperty(PropInfo);
|
|
{$ENDIF WIN32}
|
|
{$IFDEF COMPILER4_UP}
|
|
tkInt64:
|
|
Def := StoreInt64Property(PropInfo);
|
|
{$ENDIF}
|
|
tkString:
|
|
Def := StoreStringProperty(PropInfo);
|
|
tkSet:
|
|
Def := StoreSetProperty(PropInfo);
|
|
tkClass:
|
|
Def := '';
|
|
else
|
|
Exit;
|
|
end;
|
|
if (Def <> '') or (PropInfo^.PropType^.Kind in [tkString, tkClass])
|
|
{$IFDEF WIN32}
|
|
or (PropInfo^.PropType^.Kind in [tkLString,
|
|
{$IFNDEF COMPILER3_UP}tkLWString, {$ENDIF}tkWChar])
|
|
{$ENDIF WIN32}
|
|
then
|
|
S := Trim(ReadString(Section, GetItemName(PropInfo^.Name), Def))
|
|
else
|
|
S := '';
|
|
case PropInfo^.PropType^.Kind of
|
|
tkInteger:
|
|
LoadIntegerProperty(S, PropInfo);
|
|
tkChar:
|
|
LoadCharProperty(S, PropInfo);
|
|
tkEnumeration:
|
|
LoadEnumProperty(S, PropInfo);
|
|
tkFloat:
|
|
LoadFloatProperty(S, PropInfo);
|
|
{$IFDEF WIN32}
|
|
tkWChar:
|
|
LoadWCharProperty(S, PropInfo);
|
|
tkLString:
|
|
LoadLStringProperty(S, PropInfo);
|
|
{$IFNDEF COMPILER3_UP} { - Delphi 2.0, C++Builder 1.0 }
|
|
tkLWString:
|
|
LoadLStringProperty(S, PropInfo);
|
|
{$ENDIF}
|
|
tkVariant:
|
|
LoadVariantProperty(S, PropInfo);
|
|
{$ENDIF WIN32}
|
|
{$IFDEF COMPILER4_UP}
|
|
tkInt64:
|
|
LoadInt64Property(S, PropInfo);
|
|
{$ENDIF}
|
|
tkString:
|
|
LoadStringProperty(S, PropInfo);
|
|
tkSet:
|
|
LoadSetProperty(S, PropInfo);
|
|
tkClass:
|
|
LoadClassProperty(S, PropInfo);
|
|
end;
|
|
end;
|
|
except
|
|
{ ignore any exception }
|
|
end;
|
|
end;
|
|
|
|
procedure TJvPropsStorage.StoreAnyProperty(PropInfo: PPropInfo);
|
|
var
|
|
S: string;
|
|
begin
|
|
if PropInfo <> nil then
|
|
begin
|
|
case PropInfo^.PropType^.Kind of
|
|
tkInteger:
|
|
S := StoreIntegerProperty(PropInfo);
|
|
tkChar:
|
|
S := StoreCharProperty(PropInfo);
|
|
tkEnumeration:
|
|
S := StoreEnumProperty(PropInfo);
|
|
tkFloat:
|
|
S := StoreFloatProperty(PropInfo);
|
|
{$IFDEF WIN32}
|
|
tkLString:
|
|
S := StoreLStringProperty(PropInfo);
|
|
{$IFNDEF COMPILER3_UP} { - Delphi 2.0, C++Builder 1.0 }
|
|
tkLWString:
|
|
S := StoreLStringProperty(PropInfo);
|
|
{$ENDIF}
|
|
tkWChar:
|
|
S := StoreWCharProperty(PropInfo);
|
|
tkVariant:
|
|
S := StoreVariantProperty(PropInfo);
|
|
{$ENDIF WIN32}
|
|
{$IFDEF COMPILER4_UP}
|
|
tkInt64:
|
|
S := StoreInt64Property(PropInfo);
|
|
{$ENDIF}
|
|
tkString:
|
|
S := StoreStringProperty(PropInfo);
|
|
tkSet:
|
|
S := StoreSetProperty(PropInfo);
|
|
tkClass:
|
|
S := StoreClassProperty(PropInfo);
|
|
else
|
|
Exit;
|
|
end;
|
|
if (S <> '') or (PropInfo^.PropType^.Kind in [tkString
|
|
{$IFDEF WIN32}, tkLString, {$IFNDEF COMPILER3_UP} tkLWString, {$ENDIF}
|
|
tkWChar {$ENDIF WIN32}]) then
|
|
WriteString(Section, GetItemName(PropInfo^.Name), Trim(S));
|
|
end;
|
|
end;
|
|
|
|
function TJvPropsStorage.StoreIntegerProperty(PropInfo: PPropInfo): string;
|
|
begin
|
|
Result := IntToStr(GetOrdProp(FObject, PropInfo));
|
|
end;
|
|
|
|
function TJvPropsStorage.StoreCharProperty(PropInfo: PPropInfo): string;
|
|
begin
|
|
Result := Char(GetOrdProp(FObject, PropInfo));
|
|
end;
|
|
|
|
function TJvPropsStorage.StoreEnumProperty(PropInfo: PPropInfo): string;
|
|
begin
|
|
Result := GetEnumName(GetPropType(PropInfo), GetOrdProp(FObject, PropInfo));
|
|
end;
|
|
|
|
function TJvPropsStorage.StoreFloatProperty(PropInfo: PPropInfo): string;
|
|
const
|
|
{$IFDEF WIN32}
|
|
Precisions: array [TFloatType] of Integer = (7, 15, 18, 18, 19);
|
|
{$ELSE}
|
|
Precisions: array [TFloatType] of Integer = (7, 15, 18, 18);
|
|
{$ENDIF}
|
|
begin
|
|
Result := ReplaceStr(FloatToStrF(GetFloatProp(FObject, PropInfo), ffGeneral,
|
|
Precisions[GetTypeData(GetPropType(PropInfo))^.FloatType], 0),
|
|
DecimalSeparator, '.');
|
|
end;
|
|
|
|
function TJvPropsStorage.StoreStringProperty(PropInfo: PPropInfo): string;
|
|
begin
|
|
Result := GetStrProp(FObject, PropInfo);
|
|
end;
|
|
|
|
{$IFDEF WIN32}
|
|
|
|
function TJvPropsStorage.StoreLStringProperty(PropInfo: PPropInfo): string;
|
|
begin
|
|
Result := GetStrProp(FObject, PropInfo);
|
|
end;
|
|
|
|
function TJvPropsStorage.StoreWCharProperty(PropInfo: PPropInfo): string;
|
|
begin
|
|
Result := Char(GetOrdProp(FObject, PropInfo));
|
|
end;
|
|
|
|
function TJvPropsStorage.StoreVariantProperty(PropInfo: PPropInfo): string;
|
|
begin
|
|
Result := GetVariantProp(FObject, PropInfo);
|
|
end;
|
|
|
|
{$ENDIF}
|
|
|
|
{$IFDEF COMPILER4_UP}
|
|
function TJvPropsStorage.StoreInt64Property(PropInfo: PPropInfo): string;
|
|
begin
|
|
Result := IntToStr(GetInt64Prop(FObject, PropInfo));
|
|
end;
|
|
{$ENDIF}
|
|
|
|
function TJvPropsStorage.StoreSetProperty(PropInfo: PPropInfo): string;
|
|
var
|
|
TypeInfo: PTypeInfo;
|
|
W: Cardinal;
|
|
I: Integer;
|
|
begin
|
|
Result := '[';
|
|
W := GetOrdProp(FObject, PropInfo);
|
|
TypeInfo := GetTypeData(GetPropType(PropInfo))^.CompType{$IFDEF COMPILER3_UP}^{$ENDIF};
|
|
for I := 0 to SizeOf(TCardinalSet) * 8 - 1 do
|
|
if I in TCardinalSet(W) then
|
|
begin
|
|
if Length(Result) <> 1 then
|
|
Result := Result + ',';
|
|
Result := Result + GetEnumName(TypeInfo, I);
|
|
end;
|
|
Result := Result + ']';
|
|
end;
|
|
|
|
function TJvPropsStorage.StoreStringsProperty(PropInfo: PPropInfo): string;
|
|
var
|
|
List: TObject;
|
|
I: Integer;
|
|
SectName: string;
|
|
begin
|
|
Result := '';
|
|
List := TObject(GetOrdProp(Self.FObject, PropInfo));
|
|
SectName := Format('%s.%s', [Section, GetItemName(PropInfo^.Name)]);
|
|
EraseSection(SectName);
|
|
if (List is TStrings) and (TStrings(List).Count > 0) then
|
|
begin
|
|
WriteString(SectName, sCount, IntToStr(TStrings(List).Count));
|
|
for I := 0 to TStrings(List).Count - 1 do
|
|
WriteString(SectName, Format(sItem, [I]), TStrings(List)[I]);
|
|
end;
|
|
end;
|
|
|
|
function TJvPropsStorage.StoreComponentProperty(PropInfo: PPropInfo): string;
|
|
var
|
|
Comp: TComponent;
|
|
RootName: string;
|
|
begin
|
|
Comp := TComponent(GetOrdProp(FObject, PropInfo));
|
|
if Comp <> nil then
|
|
begin
|
|
Result := Comp.Name;
|
|
if (Comp.Owner <> nil) and (Comp.Owner <> FOwner) then
|
|
begin
|
|
RootName := Comp.Owner.Name;
|
|
if RootName = '' then
|
|
begin
|
|
RootName := Comp.Owner.ClassName;
|
|
if (RootName <> '') and (UpCase(RootName[1]) = 'T') then
|
|
Delete(RootName, 1, 1);
|
|
end;
|
|
Result := Format('%s.%s', [RootName, Result]);
|
|
end;
|
|
end
|
|
else
|
|
Result := sNull;
|
|
end;
|
|
|
|
function TJvPropsStorage.StoreClassProperty(PropInfo: PPropInfo): string;
|
|
var
|
|
Saver: TJvPropsStorage;
|
|
I: Integer;
|
|
Obj: TObject;
|
|
|
|
procedure StoreObjectProps(Obj: TObject; const APrefix, ASection: string);
|
|
var
|
|
I: Integer;
|
|
Props: TJvPropInfoList;
|
|
begin
|
|
with Saver do
|
|
begin
|
|
AObject := Obj;
|
|
Prefix := APrefix;
|
|
Section := ASection;
|
|
FOnWriteString := Self.FOnWriteString;
|
|
FOnEraseSection := Self.FOnEraseSection;
|
|
Props := TJvPropInfoList.Create(AObject, tkProperties);
|
|
try
|
|
for I := 0 to Props.Count - 1 do
|
|
StoreAnyProperty(Props.Items[I]);
|
|
finally
|
|
Props.Free;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
Result := '';
|
|
Obj := TObject(GetOrdProp(Self.FObject, PropInfo));
|
|
if Obj <> nil then
|
|
begin
|
|
if Obj is TStrings then
|
|
StoreStringsProperty(PropInfo)
|
|
{$IFDEF WIN32}
|
|
else
|
|
if Obj is TCollection then
|
|
begin
|
|
EraseSection(Format('%s.%s', [Section, Prefix + PropInfo^.Name]));
|
|
Saver := CreateStorage;
|
|
try
|
|
WriteString(Section, Format('%s.%s', [Prefix + PropInfo^.Name, sCount]),
|
|
IntToStr(TCollection(Obj).Count));
|
|
for I := 0 to TCollection(Obj).Count - 1 do
|
|
begin
|
|
StoreObjectProps(TCollection(Obj).Items[I],
|
|
Format(sItem, [I]) + sPropNameDelimiter,
|
|
Format('%s.%s', [Section, Prefix + PropInfo^.Name]));
|
|
end;
|
|
finally
|
|
Saver.Free;
|
|
end;
|
|
end
|
|
{$ENDIF}
|
|
else
|
|
if Obj is TComponent then
|
|
begin
|
|
Result := StoreComponentProperty(PropInfo);
|
|
Exit;
|
|
end;
|
|
end;
|
|
Saver := CreateStorage;
|
|
try
|
|
with Saver do
|
|
begin
|
|
StoreObjectProps(Obj, Self.Prefix + PropInfo^.Name, Self.Section);
|
|
end;
|
|
finally
|
|
Saver.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvPropsStorage.LoadIntegerProperty(const S: string; PropInfo: PPropInfo);
|
|
begin
|
|
SetOrdProp(FObject, PropInfo, StrToIntDef(S, 0));
|
|
end;
|
|
|
|
procedure TJvPropsStorage.LoadCharProperty(const S: string; PropInfo: PPropInfo);
|
|
begin
|
|
SetOrdProp(FObject, PropInfo, Integer(S[1]));
|
|
end;
|
|
|
|
procedure TJvPropsStorage.LoadEnumProperty(const S: string; PropInfo: PPropInfo);
|
|
var
|
|
I: Integer;
|
|
EnumType: PTypeInfo;
|
|
begin
|
|
EnumType := GetPropType(PropInfo);
|
|
with GetTypeData(EnumType)^ do
|
|
for I := MinValue to MaxValue do
|
|
if CompareText(GetEnumName(EnumType, I), S) = 0 then
|
|
begin
|
|
SetOrdProp(FObject, PropInfo, I);
|
|
Exit;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvPropsStorage.LoadFloatProperty(const S: string; PropInfo: PPropInfo);
|
|
begin
|
|
SetFloatProp(FObject, PropInfo, StrToFloat(ReplaceStr(S, '.',
|
|
DecimalSeparator)));
|
|
end;
|
|
|
|
{$IFDEF COMPILER4_UP}
|
|
procedure TJvPropsStorage.LoadInt64Property(const S: string; PropInfo: PPropInfo);
|
|
begin
|
|
SetInt64Prop(FObject, PropInfo, StrToInt64Def(S, 0));
|
|
end;
|
|
{$ENDIF}
|
|
|
|
{$IFDEF WIN32}
|
|
|
|
procedure TJvPropsStorage.LoadLStringProperty(const S: string; PropInfo: PPropInfo);
|
|
begin
|
|
SetStrProp(FObject, PropInfo, S);
|
|
end;
|
|
|
|
procedure TJvPropsStorage.LoadWCharProperty(const S: string; PropInfo: PPropInfo);
|
|
begin
|
|
SetOrdProp(FObject, PropInfo, Longint(S[1]));
|
|
end;
|
|
|
|
procedure TJvPropsStorage.LoadVariantProperty(const S: string; PropInfo: PPropInfo);
|
|
begin
|
|
SetVariantProp(FObject, PropInfo, S);
|
|
end;
|
|
|
|
{$ENDIF}
|
|
|
|
procedure TJvPropsStorage.LoadStringProperty(const S: string; PropInfo: PPropInfo);
|
|
begin
|
|
SetStrProp(FObject, PropInfo, S);
|
|
end;
|
|
|
|
procedure TJvPropsStorage.LoadSetProperty(const S: string; PropInfo: PPropInfo);
|
|
const
|
|
Delims = [' ', ',', '[', ']'];
|
|
var
|
|
TypeInfo: PTypeInfo;
|
|
W: Cardinal;
|
|
I, N: Integer;
|
|
Count: Integer;
|
|
EnumName: string;
|
|
begin
|
|
W := 0;
|
|
TypeInfo := GetTypeData(GetPropType(PropInfo))^.CompType{$IFDEF COMPILER3_UP}^{$ENDIF};
|
|
Count := WordCount(S, Delims);
|
|
for N := 1 to Count do
|
|
begin
|
|
EnumName := ExtractWord(N, S, Delims);
|
|
try
|
|
I := GetEnumValue(TypeInfo, EnumName);
|
|
if I >= 0 then
|
|
Include(TCardinalSet(W), I);
|
|
except
|
|
end;
|
|
end;
|
|
SetOrdProp(FObject, PropInfo, W);
|
|
end;
|
|
|
|
procedure TJvPropsStorage.LoadStringsProperty(const S: string; PropInfo: PPropInfo);
|
|
var
|
|
List: TObject;
|
|
Temp: TStrings;
|
|
I, Cnt: Integer;
|
|
SectName: string;
|
|
begin
|
|
List := TObject(GetOrdProp(Self.FObject, PropInfo));
|
|
if List is TStrings then
|
|
begin
|
|
SectName := Format('%s.%s', [Section, GetItemName(PropInfo^.Name)]);
|
|
Cnt := StrToIntDef(Trim(ReadString(SectName, sCount, '0')), 0);
|
|
if Cnt > 0 then
|
|
begin
|
|
Temp := TStringList.Create;
|
|
try
|
|
for I := 0 to Cnt - 1 do
|
|
Temp.Add(ReadString(SectName, Format(sItem, [I]), ''));
|
|
TStrings(List).Assign(Temp);
|
|
finally
|
|
Temp.Free;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvPropsStorage.LoadComponentProperty(const S: string; PropInfo: PPropInfo);
|
|
{$IFDEF WIN32}
|
|
var
|
|
RootName, Name: string;
|
|
Root: TComponent;
|
|
P: Integer;
|
|
begin
|
|
if Trim(S) = '' then
|
|
Exit;
|
|
if CompareText(SNull, Trim(S)) = 0 then
|
|
begin
|
|
SetOrdProp(FObject, PropInfo, Longint(nil));
|
|
Exit;
|
|
end;
|
|
P := Pos('.', S);
|
|
if P > 0 then
|
|
begin
|
|
RootName := Trim(Copy(S, 1, P - 1));
|
|
Name := Trim(Copy(S, P + 1, MaxInt));
|
|
end
|
|
else
|
|
begin
|
|
RootName := '';
|
|
Name := Trim(S);
|
|
end;
|
|
if RootName <> '' then
|
|
Root := FindGlobalComponent(RootName)
|
|
else
|
|
Root := FOwner;
|
|
if Root <> nil then
|
|
SetOrdProp(FObject, PropInfo, Longint(Root.FindComponent(Name)));
|
|
end;
|
|
{$ELSE}
|
|
begin
|
|
if Trim(S) = '' then
|
|
Exit;
|
|
if CompareText(SNull, Trim(S)) = 0 then
|
|
begin
|
|
SetOrdProp(FObject, PropInfo, Longint(nil));
|
|
Exit;
|
|
end;
|
|
if FOwner <> nil then
|
|
SetOrdProp(FObject, PropInfo, Longint(FOwner.FindComponent(Trim(S))));
|
|
end;
|
|
{$ENDIF}
|
|
|
|
procedure TJvPropsStorage.LoadClassProperty(const S: string; PropInfo: PPropInfo);
|
|
var
|
|
Loader: TJvPropsStorage;
|
|
I: Integer;
|
|
{$IFDEF WIN32}
|
|
Cnt: Integer;
|
|
Recreate: Boolean;
|
|
{$ENDIF}
|
|
Obj: TObject;
|
|
|
|
procedure LoadObjectProps(Obj: TObject; const APrefix, ASection: string);
|
|
var
|
|
I: Integer;
|
|
Props: TJvPropInfoList;
|
|
begin
|
|
with Loader do
|
|
begin
|
|
AObject := Obj;
|
|
Prefix := APrefix;
|
|
Section := ASection;
|
|
FOnReadString := Self.FOnReadString;
|
|
Props := TJvPropInfoList.Create(AObject, tkProperties);
|
|
try
|
|
for I := 0 to Props.Count - 1 do
|
|
LoadAnyProperty(Props.Items[I]);
|
|
finally
|
|
Props.Free;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
Obj := TObject(GetOrdProp(Self.FObject, PropInfo));
|
|
if Obj <> nil then
|
|
begin
|
|
if Obj is TStrings then
|
|
LoadStringsProperty(S, PropInfo)
|
|
{$IFDEF WIN32}
|
|
else
|
|
if Obj is TCollection then
|
|
begin
|
|
Loader := CreateStorage;
|
|
try
|
|
Cnt := TCollection(Obj).Count;
|
|
Cnt := StrToIntDef(ReadString(Section, Format('%s.%s',
|
|
[Prefix + PropInfo^.Name, sCount]), IntToStr(Cnt)), Cnt);
|
|
Recreate := TCollection(Obj).Count <> Cnt;
|
|
TCollection(Obj).BeginUpdate;
|
|
try
|
|
if Recreate then
|
|
TCollection(Obj).Clear;
|
|
for I := 0 to Cnt - 1 do
|
|
begin
|
|
if Recreate then
|
|
TCollection(Obj).Add;
|
|
LoadObjectProps(TCollection(Obj).Items[I],
|
|
Format(sItem, [I]) + sPropNameDelimiter,
|
|
Format('%s.%s', [Section, Prefix + PropInfo^.Name]));
|
|
end;
|
|
finally
|
|
TCollection(Obj).EndUpdate;
|
|
end;
|
|
finally
|
|
Loader.Free;
|
|
end;
|
|
end
|
|
{$ENDIF}
|
|
else
|
|
if Obj is TComponent then
|
|
begin
|
|
LoadComponentProperty(S, PropInfo);
|
|
Exit;
|
|
end;
|
|
end;
|
|
Loader := CreateStorage;
|
|
try
|
|
LoadObjectProps(Obj, Self.Prefix + PropInfo^.Name, Self.Section);
|
|
finally
|
|
Loader.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvPropsStorage.StoreProperties(PropList: TStrings);
|
|
var
|
|
I: Integer;
|
|
Props: TJvPropInfoList;
|
|
begin
|
|
Props := TJvPropInfoList.Create(AObject, tkProperties);
|
|
try
|
|
for I := 0 to PropList.Count - 1 do
|
|
StoreAnyProperty(Props.Find(PropList[I]));
|
|
finally
|
|
Props.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvPropsStorage.LoadProperties(PropList: TStrings);
|
|
var
|
|
I: Integer;
|
|
Props: TJvPropInfoList;
|
|
begin
|
|
Props := TJvPropInfoList.Create(AObject, tkProperties);
|
|
try
|
|
for I := 0 to PropList.Count - 1 do
|
|
LoadAnyProperty(Props.Find(PropList[I]));
|
|
finally
|
|
Props.Free;
|
|
end;
|
|
end;
|
|
|
|
function TJvPropsStorage.CreateInfoList(AComponent: TComponent; StoredList: TStrings): TStrings;
|
|
var
|
|
I: Integer;
|
|
Obj: TComponent;
|
|
Props: TJvPropInfoList;
|
|
begin
|
|
UpdateStoredList(AComponent, StoredList, False);
|
|
Result := TStringList.Create;
|
|
try
|
|
TStringList(Result).Sorted := True;
|
|
for I := 0 to StoredList.Count - 1 do
|
|
begin
|
|
Obj := TComponent(StoredList.Objects[I]);
|
|
if Result.IndexOf(Obj.Name) < 0 then
|
|
begin
|
|
Props := TJvPropInfoList.Create(Obj, tkProperties);
|
|
try
|
|
Result.AddObject(Obj.Name, Props);
|
|
except
|
|
Props.Free;
|
|
raise;
|
|
end;
|
|
end;
|
|
end;
|
|
except
|
|
Result.Free;
|
|
Result := nil;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvPropsStorage.FreeInfoLists(Info: TStrings);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := Info.Count - 1 downto 0 do
|
|
Info.Objects[I].Free;
|
|
Info.Free;
|
|
end;
|
|
|
|
procedure TJvPropsStorage.LoadObjectsProps(AComponent: TComponent; StoredList: TStrings);
|
|
var
|
|
Info: TStrings;
|
|
I, Idx: Integer;
|
|
Props: TJvPropInfoList;
|
|
CompName, PropName: string;
|
|
begin
|
|
Info := CreateInfoList(AComponent, StoredList);
|
|
if Info <> nil then
|
|
try
|
|
FOwner := AComponent;
|
|
for I := 0 to StoredList.Count - 1 do
|
|
begin
|
|
if ParseStoredItem(StoredList[I], CompName, PropName) then
|
|
begin
|
|
AObject := StoredList.Objects[I];
|
|
Prefix := TComponent(AObject).Name;
|
|
Idx := Info.IndexOf(Prefix);
|
|
if Idx >= 0 then
|
|
begin
|
|
Prefix := Prefix + sPropNameDelimiter;
|
|
Props := TJvPropInfoList(Info.Objects[Idx]);
|
|
if Props <> nil then
|
|
LoadAnyProperty(Props.Find(PropName));
|
|
end;
|
|
end;
|
|
end;
|
|
finally
|
|
FOwner := nil;
|
|
FreeInfoLists(Info);
|
|
end;
|
|
end;
|
|
|
|
procedure TJvPropsStorage.StoreObjectsProps(AComponent: TComponent; StoredList: TStrings);
|
|
var
|
|
Info: TStrings;
|
|
I, Idx: Integer;
|
|
Props: TJvPropInfoList;
|
|
CompName, PropName: string;
|
|
begin
|
|
Info := CreateInfoList(AComponent, StoredList);
|
|
if Info <> nil then
|
|
try
|
|
FOwner := AComponent;
|
|
for I := 0 to StoredList.Count - 1 do
|
|
begin
|
|
if ParseStoredItem(StoredList[I], CompName, PropName) then
|
|
begin
|
|
AObject := StoredList.Objects[I];
|
|
Prefix := TComponent(AObject).Name;
|
|
Idx := Info.IndexOf(Prefix);
|
|
if Idx >= 0 then
|
|
begin
|
|
Prefix := Prefix + sPropNameDelimiter;
|
|
Props := TJvPropInfoList(Info.Objects[Idx]);
|
|
if Props <> nil then
|
|
StoreAnyProperty(Props.Find(PropName));
|
|
end;
|
|
end;
|
|
end;
|
|
finally
|
|
FOwner := nil;
|
|
FreeInfoLists(Info);
|
|
end;
|
|
end;
|
|
|
|
function TJvPropsStorage.CreateStorage: TJvPropsStorage;
|
|
begin
|
|
Result := TJvPropsStorage.Create;
|
|
end;
|
|
|
|
function TJvPropsStorage.ReadString(const ASection, Item, Default: string): string;
|
|
begin
|
|
if Assigned(FOnReadString) then
|
|
Result := FOnReadString(ASection, Item, Default)
|
|
else
|
|
Result := '';
|
|
end;
|
|
|
|
procedure TJvPropsStorage.WriteString(const ASection, Item, Value: string);
|
|
begin
|
|
if Assigned(FOnWriteString) then
|
|
FOnWriteString(ASection, Item, Value);
|
|
end;
|
|
|
|
procedure TJvPropsStorage.EraseSection(const ASection: string);
|
|
begin
|
|
if Assigned(FOnEraseSection) then
|
|
FOnEraseSection(ASection);
|
|
end;
|
|
|
|
end.
|
|
|