git-svn-id: https://192.168.0.254/svn/Componentes.Terceros.jvcl@12 7f62d464-2af8-f54e-996c-e91b33f51cbe
490 lines
15 KiB
ObjectPascal
490 lines
15 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.
|
|
|
|
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: JvPropertyStorage.pas 11893 2008-09-09 20:45:14Z obones $
|
|
|
|
unit JvPropertyStorage;
|
|
|
|
{$I jvcl.inc}
|
|
|
|
interface
|
|
|
|
uses
|
|
{$IFDEF UNITVERSIONING}
|
|
JclUnitVersioning,
|
|
{$ENDIF UNITVERSIONING}
|
|
SysUtils, Classes,
|
|
Forms,
|
|
TypInfo,
|
|
JvAppStorage;
|
|
|
|
type
|
|
TJvPropInfoList = class(TObject)
|
|
private
|
|
FList: PPropList;
|
|
FCount: Integer;
|
|
FSize: Integer;
|
|
function Get(Index: Integer): PPropInfo;
|
|
public
|
|
constructor Create(AObject: TObject; Filter: TTypeKinds);
|
|
{$IFNDEF CLR}
|
|
destructor Destroy; override;
|
|
{$ENDIF !CLR}
|
|
function Contains(P: PPropInfo): Boolean;
|
|
function Find(const AName: {$IFDEF RTL200_UP}ShortString{$ELSE}string{$ENDIF RTL200_UP}): PPropInfo;
|
|
procedure Delete(Index: Integer);
|
|
procedure Intersect(List: TJvPropInfoList);
|
|
property Count: Integer read FCount;
|
|
property Items[Index: Integer]: PPropInfo read Get; default;
|
|
end;
|
|
|
|
TJvPropertyStorage = class(TObject)
|
|
private
|
|
FObject: TObject;
|
|
FOwner: TComponent;
|
|
FPrefix: string;
|
|
FAppStorage: TJvCustomAppStorage;
|
|
FAppStoragePath: string;
|
|
function CreateInfoList(AComponent: TComponent; StoredList: TStrings): TStrings;
|
|
procedure FreeInfoLists(Info: TStrings);
|
|
protected
|
|
function ReadString(const APath, Item, Default: string): string; virtual;
|
|
procedure WriteString(const APath, Item, Value: string); virtual;
|
|
|
|
procedure ReadProperty(const APath, AStorageName: string; const PersObj: TPersistent; const PropName: {$IFDEF RTL200_UP}ShortString{$ELSE}string{$ENDIF RTL200_UP});
|
|
procedure WriteProperty(const APath, AStorageName: string; const PersObj: TPersistent; const PropName: {$IFDEF RTL200_UP}ShortString{$ELSE}string{$ENDIF RTL200_UP});
|
|
|
|
procedure EraseSection(const APath: string); virtual;
|
|
function GetItemName(const APropName: {$IFDEF RTL200_UP}ShortString{$ELSE}string{$ENDIF RTL200_UP}): string; virtual;
|
|
function CreateStorage: TJvPropertyStorage; 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 AppStorage: TJvCustomAppStorage read FAppStorage write FAppStorage;
|
|
property AppStoragePath: string read FAppStoragePath write FAppStoragePath;
|
|
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
|
|
sPropNameDelimiter: string = '_';
|
|
|
|
{$IFDEF UNITVERSIONING}
|
|
const
|
|
UnitVersioning: TUnitVersionInfo = (
|
|
RCSfile: '$URL: https://jvcl.svn.sourceforge.net/svnroot/jvcl/branches/JVCL3_36_PREPARATION/run/JvPropertyStorage.pas $';
|
|
Revision: '$Revision: 11893 $';
|
|
Date: '$Date: 2008-09-09 22:45:14 +0200 (mar., 09 sept. 2008) $';
|
|
LogPath: 'JVCL\run'
|
|
);
|
|
{$ENDIF UNITVERSIONING}
|
|
|
|
implementation
|
|
|
|
uses
|
|
{$IFDEF RTL200_UP}
|
|
AnsiStrings,
|
|
{$ENDIF RTL200_UP}
|
|
JvJCLUtils;
|
|
|
|
//=== { TJvPropInfoList } ====================================================
|
|
|
|
constructor TJvPropInfoList.Create(AObject: TObject; Filter: TTypeKinds);
|
|
begin
|
|
inherited Create;
|
|
if AObject <> nil then
|
|
begin
|
|
{$IFDEF CLR}
|
|
FList := GetPropList(AObject.ClassInfo, Filter);
|
|
FCount := Length(FList);
|
|
FSize := FCount * SizeOf(IntPtr);
|
|
{$ELSE}
|
|
FCount := GetPropList(AObject.ClassInfo, Filter, nil);
|
|
FSize := FCount * SizeOf(Pointer);
|
|
GetMem(FList, FSize);
|
|
GetPropList(AObject.ClassInfo, Filter, FList);
|
|
{$ENDIF CLR}
|
|
end
|
|
else
|
|
begin
|
|
FCount := 0;
|
|
FList := nil;
|
|
end;
|
|
end;
|
|
|
|
{$IFNDEF CLR}
|
|
destructor TJvPropInfoList.Destroy;
|
|
begin
|
|
if FList <> nil then
|
|
FreeMem(FList, FSize);
|
|
inherited Destroy;
|
|
end;
|
|
{$ENDIF !CLR}
|
|
|
|
function TJvPropInfoList.Contains(P: PPropInfo): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := 0 to FCount - 1 do
|
|
with FList[I]{$IFNDEF CLR}^{$ENDIF} do
|
|
if (PropType = P.PropType) and ({$IFDEF RTL200_UP}AnsiStrings.{$ENDIF RTL200_UP}CompareText(Name, P.Name) = 0) then
|
|
begin
|
|
Result := True;
|
|
Exit;
|
|
end;
|
|
Result := False;
|
|
end;
|
|
|
|
function TJvPropInfoList.Find(const AName: {$IFDEF RTL200_UP}ShortString{$ELSE}string{$ENDIF RTL200_UP}): PPropInfo;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := 0 to FCount - 1 do
|
|
with FList[I]{$IFNDEF CLR}^{$ENDIF} do
|
|
if {$IFDEF RTL200_UP}AnsiStrings.{$ENDIF RTL200_UP}CompareText(Name, AName) = 0 then
|
|
begin
|
|
Result := FList[I];
|
|
Exit;
|
|
end;
|
|
Result := nil;
|
|
end;
|
|
|
|
procedure TJvPropInfoList.Delete(Index: Integer);
|
|
{$IFDEF CLR}
|
|
var
|
|
I: Integer;
|
|
{$ENDIF CLR}
|
|
begin
|
|
Dec(FCount);
|
|
if Index < FCount then
|
|
{$IFDEF CLR}
|
|
for I := 0 to (FCount - Index) - 1 do
|
|
FList[Index + I] := FList[Index + 1 + I];
|
|
{$ELSE}
|
|
Move(FList[Index + 1], FList[Index], (FCount - Index) * SizeOf(Pointer));
|
|
{$ENDIF CLR}
|
|
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 Item = '' 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 := (CompName <> '') and (PropName <> '');
|
|
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;
|
|
|
|
//=== { TJvPropertyStorage } =================================================
|
|
|
|
function TJvPropertyStorage.GetItemName(const APropName: {$IFDEF RTL200_UP}ShortString{$ELSE}string{$ENDIF RTL200_UP}): string;
|
|
begin
|
|
Result := Prefix + string(APropName);
|
|
end;
|
|
|
|
procedure TJvPropertyStorage.LoadAnyProperty(PropInfo: PPropInfo);
|
|
begin
|
|
try
|
|
if PropInfo <> nil then
|
|
ReadProperty (AppStoragePath, GetItemName(PropInfo.Name), TPersistent(FObject), PropInfo.Name);
|
|
except
|
|
{ ignore any exception }
|
|
end;
|
|
end;
|
|
|
|
procedure TJvPropertyStorage.StoreAnyProperty(PropInfo: PPropInfo);
|
|
begin
|
|
if PropInfo <> nil then
|
|
WriteProperty (AppStoragePath, GetItemName(PropInfo.Name), TPersistent(FObject), PropInfo.Name);
|
|
end;
|
|
|
|
|
|
procedure TJvPropertyStorage.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({$IFDEF SUPPORTS_UNICODE}UTF8Encode{$ENDIF SUPPORTS_UNICODE}(PropList[I])));
|
|
finally
|
|
Props.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvPropertyStorage.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({$IFDEF SUPPORTS_UNICODE}UTF8Encode{$ENDIF SUPPORTS_UNICODE}(PropList[I])));
|
|
finally
|
|
Props.Free;
|
|
end;
|
|
end;
|
|
|
|
function TJvPropertyStorage.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 TJvPropertyStorage.FreeInfoLists(Info: TStrings);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := Info.Count - 1 downto 0 do
|
|
Info.Objects[I].Free;
|
|
Info.Free;
|
|
end;
|
|
|
|
procedure TJvPropertyStorage.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({$IFDEF SUPPORTS_UNICODE}UTF8Encode{$ENDIF SUPPORTS_UNICODE}(PropName)));
|
|
end;
|
|
end;
|
|
end;
|
|
finally
|
|
FOwner := nil;
|
|
FreeInfoLists(Info);
|
|
end;
|
|
end;
|
|
|
|
procedure TJvPropertyStorage.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({$IFDEF SUPPORTS_UNICODE}UTF8Encode{$ENDIF SUPPORTS_UNICODE}(PropName)));
|
|
end;
|
|
end;
|
|
end;
|
|
finally
|
|
FOwner := nil;
|
|
FreeInfoLists(Info);
|
|
end;
|
|
end;
|
|
|
|
function TJvPropertyStorage.CreateStorage: TJvPropertyStorage;
|
|
begin
|
|
Result := TJvPropertyStorage.Create;
|
|
Result.AppStorage := AppStorage;
|
|
end;
|
|
|
|
function TJvPropertyStorage.ReadString(const APath, Item, Default: string): string;
|
|
begin
|
|
if Assigned(AppStorage) then
|
|
Result := AppStorage.ReadString(AppStorage.ConcatPaths([APath, AppStorage.TranslatePropertyName(Nil, Item, True)]), Default)
|
|
else
|
|
Result := Default;
|
|
end;
|
|
|
|
procedure TJvPropertyStorage.WriteString(const APath, Item, Value: string);
|
|
begin
|
|
if Assigned(AppStorage) then
|
|
AppStorage.WriteString(AppStorage.ConcatPaths([APath, AppStorage.TranslatePropertyName(Nil, Item, False)]), Value);
|
|
end;
|
|
|
|
procedure TJvPropertyStorage.EraseSection(const APath: string);
|
|
begin
|
|
if Assigned(AppStorage) then
|
|
AppStorage.DeleteSubTree(APath);
|
|
end;
|
|
|
|
procedure TJvPropertyStorage.ReadProperty(const APath, AStorageName: string; const PersObj: TPersistent; const PropName: {$IFDEF RTL200_UP}ShortString{$ELSE}string{$ENDIF RTL200_UP});
|
|
var
|
|
NPath: string;
|
|
begin
|
|
if Assigned(AppStorage) then
|
|
begin
|
|
NPath := AppStorage.ConcatPaths([APath, AppStorage.TranslatePropertyName(PersObj, AStorageName, True)]);
|
|
if AppStorage.ValueStored(NPath) or AppStorage.IsFolder(NPath, False) then
|
|
AppStorage.ReadProperty(NPath, PersObj, string(PropName), True, True);
|
|
end;
|
|
end;
|
|
|
|
procedure TJvPropertyStorage.WriteProperty(const APath, AStorageName: string; const PersObj: TPersistent; const PropName: {$IFDEF RTL200_UP}ShortString{$ELSE}string{$ENDIF RTL200_UP});
|
|
begin
|
|
if Assigned(AppStorage) then
|
|
AppStorage.WriteProperty(AppStorage.ConcatPaths([APath, AppStorage.TranslatePropertyName(PersObj, AStorageName, False)]), PersObj, string(PropName), True);
|
|
end;
|
|
|
|
{$IFDEF UNITVERSIONING}
|
|
initialization
|
|
RegisterUnitVersion(HInstance, UnitVersioning);
|
|
|
|
finalization
|
|
UnregisterUnitVersion(HInstance);
|
|
{$ENDIF UNITVERSIONING}
|
|
|
|
end.
|
|
|