mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-05 04:08:06 +02:00
814 lines
21 KiB
ObjectPascal
814 lines
21 KiB
ObjectPascal
{ $Id$ }
|
|
{
|
|
*****************************************************************************
|
|
This file is part of the Lazarus Component Library (LCL)
|
|
|
|
See the file COPYING.modifiedLGPL.txt, included in this distribution,
|
|
for details about the license.
|
|
*****************************************************************************
|
|
}
|
|
unit PropertyStorage;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
|
|
uses
|
|
Classes, SysUtils, RTLConsts, RTTIUtils;
|
|
|
|
Type
|
|
TPlacementOperation = (poSave, poRestore);
|
|
TCustomPropertyStorage = Class;
|
|
TStoredValue = Class;
|
|
TStoredValues = Class;
|
|
|
|
{ TStoredValue }
|
|
|
|
{$ifdef storevariant}
|
|
TStoredType = Variant;
|
|
{$else}
|
|
TStoredType = AnsiString;
|
|
{$endif}
|
|
|
|
TStoredValueEvent = procedure(Sender: TStoredValue;
|
|
var Value: TStoredType) of object;
|
|
|
|
TStoredValue = class(TCollectionItem)
|
|
private
|
|
FName: string;
|
|
FValue: TStoredType;
|
|
FKeyString: string;
|
|
FOnSave: TStoredValueEvent;
|
|
FOnRestore: TStoredValueEvent;
|
|
function IsValueStored: Boolean;
|
|
function GetStoredValues: TStoredValues;
|
|
protected
|
|
function GetDisplayName: string; override;
|
|
procedure SetDisplayName(const AValue: string); override;
|
|
public
|
|
constructor Create(ACollection: TCollection); override;
|
|
procedure Assign(Source: TPersistent); override;
|
|
procedure Clear;
|
|
procedure Save; virtual;
|
|
procedure Restore; virtual;
|
|
property StoredValues: TStoredValues read GetStoredValues;
|
|
published
|
|
property Name: string read FName write SetDisplayName;
|
|
property Value: TStoredType read FValue write FValue stored IsValueStored;
|
|
property KeyString: string read FKeyString write FKeyString;
|
|
property OnSave: TStoredValueEvent read FOnSave write FOnSave;
|
|
property OnRestore: TStoredValueEvent read FOnRestore write FOnRestore;
|
|
end;
|
|
|
|
|
|
{ TStoredValues }
|
|
|
|
TStoredValues = class(TOwnedCollection)
|
|
private
|
|
FStorage: TCustomPropertyStorage;
|
|
function GetValue(const AName: string): TStoredValue;
|
|
procedure SetValue(const AName: string; AStoredValue: TStoredValue);
|
|
function GetStoredValue(const AName: string): TStoredType;
|
|
procedure SetStoredValue(const AName: string; Value: TStoredType);
|
|
function GetItem(Index: Integer): TStoredValue;
|
|
procedure SetItem(Index: Integer; AStoredValue: TStoredValue);
|
|
public
|
|
constructor Create(AOwner: TPersistent);
|
|
function IndexOf(const AName: string): Integer;
|
|
procedure SaveValues; virtual;
|
|
procedure RestoreValues; virtual;
|
|
property Storage: TCustomPropertyStorage read FStorage write FStorage;
|
|
property Items[Index: Integer]: TStoredValue read GetItem write SetItem; default;
|
|
property Values[const Name: string]: TStoredValue read GetValue write SetValue;
|
|
property StoredValue[const Name: string]: TStoredType read GetStoredValue write SetStoredValue;
|
|
end;
|
|
|
|
|
|
{ TCustomPropertyStorage }
|
|
|
|
TPropertyStorageLink = class(TPersistent)
|
|
private
|
|
FStorage: TCustomPropertyStorage;
|
|
FOnSave: TNotifyEvent;
|
|
FOnLoad: TNotifyEvent;
|
|
function GetRootSection: string;
|
|
procedure SetStorage(Value: TCustomPropertyStorage);
|
|
protected
|
|
procedure SaveProperties; virtual;
|
|
procedure LoadProperties; virtual;
|
|
public
|
|
destructor Destroy; override;
|
|
property Storage: TCustomPropertyStorage read FStorage write SetStorage;
|
|
property RootSection: string read GetRootSection;
|
|
property OnSave: TNotifyEvent read FOnSave write FOnSave;
|
|
property OnLoad: TNotifyEvent read FOnLoad write FOnLoad;
|
|
end;
|
|
|
|
{ TCustomPropertyStorage }
|
|
|
|
TPropertyStorageSaveExceptionEvent = procedure(Sender: TObject;
|
|
const ExClassName: String;
|
|
const ExMessage: String) of object;
|
|
|
|
TCustomPropertyStorage = Class (TComponent)
|
|
private
|
|
FOnRestoringProperties: TNotifyEvent;
|
|
FOnSavingProperties: TNotifyEvent;
|
|
FStoredValues: TStoredValues;
|
|
FActive: Boolean;
|
|
FLinks: TList;
|
|
FSaved: Boolean;
|
|
FOnSaveProperties: TNotifyEvent;
|
|
FOnRestoreProperties: TNotifyEvent;
|
|
FOnSaveException:TPropertyStorageSaveExceptionEvent;
|
|
procedure AddLink(ALink: TPropertyStorageLink);
|
|
procedure RemoveLink(ALink: TPropertyStorageLink);
|
|
procedure NotifyLinks(Operation: TPlacementOperation);
|
|
procedure SetStoredValues(Value: TStoredValues);
|
|
function GetStoredValue(const AName: string): TStoredType;
|
|
procedure SetStoredValue(const AName: string; Value: TStoredType);
|
|
protected
|
|
function GetRoot: TComponent; virtual;
|
|
function RootSection: String; Virtual;
|
|
procedure SaveProperties; virtual;
|
|
procedure RestoreProperties; virtual;
|
|
procedure GetPropertyList(List: TStrings); virtual; abstract;
|
|
procedure FinishPropertyList(List: TStrings); virtual;
|
|
function DoReadInteger(const Section, Ident : String; DefaultValue: Integer): Integer; Virtual;
|
|
function DoReadString(const Section, Ident, DefaultValue: string): string; Virtual; Abstract;
|
|
procedure DoWriteString(const Section, Ident, Value: string); Virtual; Abstract;
|
|
procedure DoWriteInteger(const Section, Ident : String; Value: Integer); Virtual;
|
|
procedure DoEraseSections(const ARootSection : String); virtual; abstract;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
procedure Save; virtual;
|
|
procedure Restore; virtual;
|
|
// Public Read/Write methods
|
|
procedure StorageNeeded(ReadOnly: Boolean); Virtual;
|
|
procedure FreeStorage; Virtual;
|
|
function ReadBoolean(const Ident: string; DefaultValue: Boolean): Boolean;
|
|
function ReadString(const Ident, DefaultValue: string): string;
|
|
function ReadInteger(const Ident: string; DefaultValue: Longint): Longint;
|
|
procedure ReadRect(const Ident: string; out ARect: TRect;
|
|
const Default: TRect);
|
|
procedure ReadStrings(const Ident: string; const List: TStrings;
|
|
const DefaultList: TStrings = nil);
|
|
procedure WriteString(const Ident, Value: string);
|
|
procedure WriteInteger(const Ident: string; Value: Longint);
|
|
procedure WriteBoolean(const Ident: string; Value: Boolean);
|
|
procedure WriteRect(const Ident: string; const Value: TRect);
|
|
procedure WriteStrings(const Ident: string; const List: TStrings);
|
|
procedure EraseSections;
|
|
public
|
|
property StoredValue[const AName: string]: TStoredType read GetStoredValue write SetStoredValue;
|
|
property Root: TComponent read GetRoot;
|
|
property Active: Boolean read FActive write FActive default True;
|
|
property StoredValues: TStoredValues read FStoredValues write SetStoredValues;
|
|
property OnSavingProperties: TNotifyEvent read FOnSavingProperties write FOnSavingProperties;
|
|
property OnSaveProperties: TNotifyEvent read FOnSaveProperties write FOnSaveProperties;
|
|
property OnRestoringProperties: TNotifyEvent read FOnRestoringProperties write FOnRestoringProperties;
|
|
property OnRestoreProperties: TNotifyEvent read FOnRestoreProperties write FOnRestoreProperties;
|
|
property OnSaveException: TPropertyStorageSaveExceptionEvent read FOnSaveException write FOnSaveException;
|
|
end;
|
|
|
|
implementation
|
|
|
|
function XorEncode(const Key, Source: string): string;
|
|
var
|
|
I: Integer;
|
|
C: Byte;
|
|
begin
|
|
Result := '';
|
|
for I := 1 to Length(Source) do begin
|
|
if Length(Key) > 0 then
|
|
C := Byte(Key[1 + ((I - 1) mod Length(Key))]) xor Byte(Source[I])
|
|
else
|
|
C := Byte(Source[I]);
|
|
Result := Result + AnsiLowerCase(IntToHex(C, 2));
|
|
end;
|
|
end;
|
|
|
|
function XorDecode(const Key, Source: string): string;
|
|
var
|
|
I: Integer;
|
|
C: Char;
|
|
|
|
begin
|
|
Result := '';
|
|
for I := 0 to Length(Source) div 2 - 1 do begin
|
|
C := Chr(StrToIntDef('$' + Copy(Source, (I * 2) + 1, 2), Ord(' ')));
|
|
if Length(Key) > 0 then
|
|
C := Chr(Byte(Key[1 + (I mod Length(Key))]) xor Byte(C));
|
|
Result := Result + C;
|
|
end;
|
|
end;
|
|
|
|
|
|
{ TPropertyStorageLink }
|
|
|
|
destructor TPropertyStorageLink.Destroy;
|
|
begin
|
|
FOnSave := nil;
|
|
FOnLoad := nil;
|
|
SetStorage(nil);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TPropertyStorageLink.GetRootSection: string;
|
|
begin
|
|
if Assigned(FStorage) then
|
|
Result:=FStorage.RootSection
|
|
else
|
|
Result:='';
|
|
if Result<>'' then
|
|
Result:=Result+'\';
|
|
end;
|
|
|
|
procedure TPropertyStorageLink.SetStorage(Value: TCustomPropertyStorage);
|
|
begin
|
|
if FStorage <> Value then
|
|
begin
|
|
if FStorage <> nil then
|
|
FStorage.RemoveLink(Self);
|
|
if Value <> nil then
|
|
Value.AddLink(Self);
|
|
end;
|
|
end;
|
|
|
|
procedure TPropertyStorageLink.SaveProperties;
|
|
begin
|
|
if Assigned(FOnSave) then
|
|
FOnSave(Self);
|
|
end;
|
|
|
|
procedure TPropertyStorageLink.LoadProperties;
|
|
begin
|
|
if Assigned(FOnLoad) then
|
|
FOnLoad(Self);
|
|
end;
|
|
|
|
{ TStoredValue }
|
|
|
|
constructor TStoredValue.Create(ACollection: TCollection);
|
|
begin
|
|
inherited Create(ACollection);
|
|
{$ifdef storevariant}
|
|
FValue := Unassigned;
|
|
{$else}
|
|
FValue:='';
|
|
{$endif}
|
|
end;
|
|
|
|
procedure TStoredValue.Assign(Source: TPersistent);
|
|
begin
|
|
if (Source is TStoredValue) and (Source <> nil) then
|
|
begin
|
|
{$ifdef storevariant}
|
|
if VarIsEmpty(TStoredValue(Source).FValue) then
|
|
Clear
|
|
else
|
|
{$endif}
|
|
Value := TStoredValue(Source).FValue;
|
|
Name := TStoredValue(Source).Name;
|
|
KeyString := TStoredValue(Source).KeyString;
|
|
end;
|
|
end;
|
|
|
|
function TStoredValue.GetDisplayName: string;
|
|
begin
|
|
if FName = '' then
|
|
Result := inherited GetDisplayName
|
|
else
|
|
Result := FName;
|
|
end;
|
|
|
|
procedure TStoredValue.SetDisplayName(const AValue: string);
|
|
begin
|
|
if (AValue <> '') and (AnsiCompareText(AValue, FName) <> 0)
|
|
and (Collection is TStoredValues)
|
|
and (TStoredValues(Collection).IndexOf(AValue) >= 0) then
|
|
raise Exception.Create(SDuplicateString);
|
|
FName := AValue;
|
|
inherited;
|
|
end;
|
|
|
|
function TStoredValue.GetStoredValues: TStoredValues;
|
|
begin
|
|
if Collection is TStoredValues then
|
|
Result := TStoredValues(Collection)
|
|
else
|
|
Result := nil;
|
|
end;
|
|
|
|
procedure TStoredValue.Clear;
|
|
begin
|
|
{$ifdef storevariant}
|
|
FValue := Unassigned;
|
|
{$else}
|
|
FValue := '';
|
|
{$endif}
|
|
end;
|
|
|
|
function TStoredValue.IsValueStored: Boolean;
|
|
begin
|
|
{$ifdef storevariant}
|
|
Result := not VarIsEmpty(FValue);
|
|
{$else}
|
|
Result := (FValue<>'');
|
|
{$endif}
|
|
end;
|
|
|
|
procedure TStoredValue.Save;
|
|
var
|
|
SaveValue: TStoredType;
|
|
SaveStrValue: string;
|
|
begin
|
|
SaveValue := Value;
|
|
if Assigned(FOnSave) then
|
|
FOnSave(Self, SaveValue);
|
|
{$ifdef storevariant}
|
|
SaveStrValue := VarToStr(SaveValue);
|
|
{$else}
|
|
SaveStrValue := SaveValue;
|
|
{$endif}
|
|
if KeyString <> '' then
|
|
SaveStrValue := XorEncode(KeyString, SaveStrValue);
|
|
StoredValues.Storage.WriteString(Name, SaveStrValue);
|
|
end;
|
|
|
|
procedure TStoredValue.Restore;
|
|
var
|
|
RestoreValue: TStoredType;
|
|
RestoreStrValue, DefaultStrValue: string;
|
|
begin
|
|
{$ifdef storevariant}
|
|
DefaultStrValue := VarToStr(Value);
|
|
{$else}
|
|
DefaultStrValue := Value;
|
|
{$endif}
|
|
if KeyString <> '' then
|
|
DefaultStrValue := XorEncode(KeyString, DefaultStrValue);
|
|
RestoreStrValue := StoredValues.Storage.ReadString(Name, DefaultStrValue);
|
|
if KeyString <> '' then
|
|
RestoreStrValue := XorDecode(KeyString, RestoreStrValue);
|
|
RestoreValue := RestoreStrValue;
|
|
if Assigned(FOnRestore) then
|
|
FOnRestore(Self, RestoreValue);
|
|
Value := RestoreValue;
|
|
end;
|
|
|
|
{ TStoredValues }
|
|
|
|
constructor TStoredValues.Create(AOwner: TPersistent);
|
|
begin
|
|
inherited Create(AOwner, TStoredValue);
|
|
If AOwner is TCustomPropertyStorage then
|
|
FStorage:=TCustomPropertyStorage(AOwner);
|
|
end;
|
|
|
|
function TStoredValues.IndexOf(const AName: string): Integer;
|
|
begin
|
|
for Result := 0 to Count - 1 do
|
|
if AnsiCompareText(Items[Result].Name, AName) = 0 then Exit;
|
|
Result := -1;
|
|
end;
|
|
|
|
function TStoredValues.GetItem(Index: Integer): TStoredValue;
|
|
begin
|
|
Result := TStoredValue(inherited Items[Index]);
|
|
end;
|
|
|
|
procedure TStoredValues.SetItem(Index: Integer; AStoredValue: TStoredValue);
|
|
begin
|
|
inherited SetItem(Index, TCollectionItem(AStoredValue));
|
|
end;
|
|
|
|
function TStoredValues.GetStoredValue(const AName: string): TStoredType;
|
|
var
|
|
AStoredValue: TStoredValue;
|
|
begin
|
|
AStoredValue := GetValue(AName);
|
|
if AStoredValue = nil then
|
|
{$ifdef storevariant}
|
|
Result := Null
|
|
{$else}
|
|
Result := ''
|
|
{$endif}
|
|
else
|
|
Result := AStoredValue.Value;
|
|
end;
|
|
|
|
procedure TStoredValues.SetStoredValue(const AName: string; Value: TStoredType);
|
|
var
|
|
AStoredValue: TStoredValue;
|
|
begin
|
|
AStoredValue := GetValue(AName);
|
|
if AStoredValue = nil then begin
|
|
AStoredValue := TStoredValue(Add);
|
|
AStoredValue.Name := AName;
|
|
AStoredValue.Value := Value;
|
|
end
|
|
else AStoredValue.Value := Value;
|
|
end;
|
|
|
|
function TStoredValues.GetValue(const AName: string): TStoredValue;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
I := IndexOf(AName);
|
|
if I < 0 then
|
|
Result := nil
|
|
else
|
|
Result := Items[I];
|
|
end;
|
|
|
|
procedure TStoredValues.SetValue(const AName: string; AStoredValue: TStoredValue);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
I := IndexOf(AName);
|
|
if I >= 0 then
|
|
Items[I].Assign(AStoredValue);
|
|
end;
|
|
|
|
procedure TStoredValues.SaveValues;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := 0 to Count - 1 do
|
|
Items[I].Save;
|
|
end;
|
|
|
|
procedure TStoredValues.RestoreValues;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := 0 to Count - 1 do
|
|
Items[I].Restore;
|
|
end;
|
|
|
|
{ TCustomPropertyStorage }
|
|
|
|
constructor TCustomPropertyStorage.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
FActive := True;
|
|
FLinks := TList.Create;
|
|
FStoredValues:=TStoredValues.Create(Self);
|
|
FStoredValues.Storage:=Self;
|
|
end;
|
|
|
|
destructor TCustomPropertyStorage.Destroy;
|
|
begin
|
|
FreeStorage;
|
|
FStoredValues.Free;
|
|
while FLinks.Count > 0 do
|
|
RemoveLink(TPropertyStorageLink(FLinks.Last));
|
|
FreeAndNil(FLinks);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TCustomPropertyStorage.AddLink(ALink: TPropertyStorageLink);
|
|
begin
|
|
FLinks.Add(ALink);
|
|
ALink.FStorage := Self;
|
|
end;
|
|
|
|
procedure TCustomPropertyStorage.NotifyLinks(Operation: TPlacementOperation);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := 0 to FLinks.Count - 1 do
|
|
with TPropertyStorageLink(FLinks[I]) do
|
|
case Operation of
|
|
poSave: SaveProperties;
|
|
poRestore: LoadProperties;
|
|
end;
|
|
end;
|
|
|
|
procedure TCustomPropertyStorage.RemoveLink(ALink: TPropertyStorageLink);
|
|
begin
|
|
ALink.FStorage := nil;
|
|
FLinks.Remove(ALink);
|
|
end;
|
|
|
|
function TCustomPropertyStorage.GetRoot: TComponent;
|
|
begin
|
|
Result:=Owner;
|
|
end;
|
|
|
|
function TCustomPropertyStorage.RootSection : string;
|
|
|
|
var
|
|
ARoot: TPersistent;
|
|
Prepend: String;
|
|
|
|
begin
|
|
Result:='';
|
|
ARoot:=Root;
|
|
while ARoot<>nil do begin
|
|
if (ARoot is TComponent) and (TComponent(ARoot).Name<>'') then
|
|
Prepend:=TComponent(ARoot).Name
|
|
else begin
|
|
Prepend:=ARoot.ClassName;
|
|
ARoot:=nil;
|
|
end;
|
|
if Result<>'' then
|
|
Result:=Prepend+'.'+Result
|
|
else
|
|
Result:=Prepend;
|
|
if not (ARoot is TComponent) then break;
|
|
ARoot:=TComponent(ARoot).Owner;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TCustomPropertyStorage.Save;
|
|
begin
|
|
if Active and not (csDesigning in ComponentState) then begin
|
|
StorageNeeded(False);
|
|
Try
|
|
if Assigned(FOnSavingProperties) then
|
|
FOnSavingProperties(Self);
|
|
try
|
|
SaveProperties;
|
|
FStoredValues.SaveValues;
|
|
NotifyLinks(poSave);
|
|
if Assigned(FOnSaveProperties) then
|
|
FOnSaveProperties(Self);
|
|
FSaved := True;
|
|
except
|
|
on E: Exception do
|
|
begin
|
|
if Assigned(FOnSaveException) then
|
|
FOnSaveException(Self, E.ClassName, E.Message);
|
|
end;
|
|
end;
|
|
Finally
|
|
FreeStorage;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TCustomPropertyStorage.Restore;
|
|
begin
|
|
if Active and not (csDesigning in ComponentState) then begin
|
|
FSaved := False;
|
|
StorageNeeded(True);
|
|
try
|
|
if Assigned(FOnRestoringProperties) then
|
|
FOnRestoringProperties(Self);
|
|
FStoredValues.RestoreValues;
|
|
RestoreProperties;
|
|
NotifyLinks(poRestore);
|
|
if Assigned(FOnRestoreProperties) then
|
|
FOnRestoreProperties(Self);
|
|
finally
|
|
FreeStorage;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TCustomPropertyStorage.SaveProperties;
|
|
|
|
Var
|
|
AStoredList : TStringList;
|
|
begin
|
|
AStoredList:=TStringList.Create;
|
|
Try
|
|
GetPropertyList(AStoredList);
|
|
FinishPropertyList(AStoredList);
|
|
StorageNeeded(False);
|
|
Try
|
|
with TPropsStorage.Create do
|
|
try
|
|
Section := RootSection;
|
|
OnWriteString := @DoWriteString;
|
|
OnEraseSection := @DoEraseSections;
|
|
StoreObjectsProps(Owner,AStoredList);
|
|
finally
|
|
Free;
|
|
end;
|
|
Finally
|
|
FreeStorage;
|
|
end;
|
|
finally
|
|
AStoredList.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TCustomPropertyStorage.RestoreProperties;
|
|
|
|
Var
|
|
L : TStringList;
|
|
|
|
begin
|
|
L:=TStringList.Create;
|
|
Try
|
|
GetPropertyList(L);
|
|
FinishPropertyList(L);
|
|
StorageNeeded(True);
|
|
Try
|
|
with TPropsStorage.Create do
|
|
try
|
|
Section := RootSection;
|
|
OnReadString := @DoReadString;
|
|
try
|
|
LoadObjectsProps(Owner,L);
|
|
except
|
|
{ ignore any exceptions }
|
|
// ToDo: Why?
|
|
end;
|
|
finally
|
|
Free;
|
|
end;
|
|
Finally
|
|
FreeStorage;
|
|
end;
|
|
finally
|
|
L.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TCustomPropertyStorage.FinishPropertyList(List: TStrings);
|
|
var
|
|
i: Integer;
|
|
CompName: string;
|
|
PropName: string;
|
|
ARoot: TComponent;
|
|
AComponent: TComponent;
|
|
begin
|
|
// set Objects (i.e. the component of each property)
|
|
ARoot:=Root;
|
|
for i:=List.Count-1 downto 0 do begin
|
|
if ParseStoredItem(List[I], CompName, PropName) then begin
|
|
if CompareText(ARoot.Name,CompName)=0 then
|
|
List.Objects[i]:=ARoot
|
|
else begin
|
|
AComponent:=Root.FindComponent(CompName);
|
|
if AComponent<>nil then
|
|
List.Objects[i]:=AComponent
|
|
else
|
|
List.Delete(i);
|
|
end;
|
|
end else begin
|
|
List.Delete(i);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TCustomPropertyStorage.DoReadInteger(const Section, Ident: String;
|
|
DefaultValue: Integer): Integer;
|
|
begin
|
|
Result:=StrToIntDef(DoReadString(Section,Ident,IntToStr(DefaultValue)),DefaultValue);
|
|
end;
|
|
|
|
procedure TCustomPropertyStorage.DoWriteInteger(const Section, Ident: String;
|
|
Value: Integer);
|
|
begin
|
|
DoWriteString(Section,Ident,IntToStr(Value))
|
|
end;
|
|
|
|
procedure TCustomPropertyStorage.StorageNeeded(ReadOnly: Boolean);
|
|
begin
|
|
end;
|
|
|
|
procedure TCustomPropertyStorage.FreeStorage;
|
|
begin
|
|
end;
|
|
|
|
function TCustomPropertyStorage.ReadString(const Ident, DefaultValue: string): string;
|
|
begin
|
|
StorageNeeded(True);
|
|
try
|
|
Result := DoReadString(RootSection, Ident, DefaultValue);
|
|
finally
|
|
FreeStorage;
|
|
end;
|
|
end;
|
|
|
|
procedure TCustomPropertyStorage.WriteString(const Ident, Value: string);
|
|
begin
|
|
StorageNeeded(False);
|
|
try
|
|
DoWriteString(RootSection, Ident, Value);
|
|
finally
|
|
FreeStorage;
|
|
end;
|
|
end;
|
|
|
|
function TCustomPropertyStorage.ReadInteger(const Ident: string; DefaultValue: Longint): Longint;
|
|
begin
|
|
StorageNeeded(True);
|
|
try
|
|
Result := DoReadInteger(RootSection, Ident, DefaultValue);
|
|
finally
|
|
FreeStorage;
|
|
end;
|
|
end;
|
|
|
|
function TCustomPropertyStorage.ReadBoolean(const Ident: string; DefaultValue: Boolean): Boolean;
|
|
begin
|
|
Result := ReadInteger(Ident, Ord(DefaultValue)) <> Ord(False);
|
|
end;
|
|
|
|
procedure TCustomPropertyStorage.ReadRect(const Ident: string;
|
|
out ARect: TRect; const Default: TRect);
|
|
begin
|
|
ARect.Left:=ReadInteger(Ident+'Left',Default.Left);
|
|
ARect.Top:=ReadInteger(Ident+'Top',Default.Top);
|
|
ARect.Right:=ReadInteger(Ident+'Right',Default.Right);
|
|
ARect.Bottom:=ReadInteger(Ident+'Bottom',Default.Bottom);
|
|
end;
|
|
|
|
procedure TCustomPropertyStorage.ReadStrings(const Ident: string;
|
|
const List: TStrings; const DefaultList: TStrings);
|
|
var
|
|
sl: TStringList;
|
|
NewCount: LongInt;
|
|
i: Integer;
|
|
begin
|
|
if ReadString(Ident+'Count','')='' then begin
|
|
// use default
|
|
if DefaultList<>nil then
|
|
List.Assign(DefaultList)
|
|
else
|
|
List.Clear;
|
|
exit;
|
|
end;
|
|
// read list into a temporary list and then use Assign to copy in one step
|
|
sl:=TStringList.Create;
|
|
try
|
|
NewCount:=ReadInteger(Ident+'Count',0);
|
|
for i:=0 to NewCount-1 do
|
|
sl.Add(ReadString(Ident+'Item'+IntToStr(i+1),''));
|
|
List.Assign(sl);
|
|
finally
|
|
sl.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TCustomPropertyStorage.WriteInteger(const Ident: string; Value: Longint);
|
|
begin
|
|
StorageNeeded(False);
|
|
try
|
|
DoWriteInteger(RootSection, Ident, Value);
|
|
finally
|
|
FreeStorage;
|
|
end;
|
|
end;
|
|
|
|
procedure TCustomPropertyStorage.WriteBoolean(const Ident: string; Value: Boolean);
|
|
begin
|
|
WriteInteger(Ident, Ord(Value));
|
|
end;
|
|
|
|
procedure TCustomPropertyStorage.WriteRect(const Ident: string;
|
|
const Value: TRect);
|
|
begin
|
|
WriteInteger(Ident+'Left',Value.Left);
|
|
WriteInteger(Ident+'Top',Value.Top);
|
|
WriteInteger(Ident+'Right',Value.Right);
|
|
WriteInteger(Ident+'Bottom',Value.Bottom);
|
|
end;
|
|
|
|
procedure TCustomPropertyStorage.WriteStrings(const Ident: string;
|
|
const List: TStrings);
|
|
var
|
|
i: Integer;
|
|
begin
|
|
WriteInteger(Ident+'Count',List.Count);
|
|
for i:=0 to List.Count-1 do
|
|
WriteString(Ident+'Item'+IntToStr(i+1),List[i]);
|
|
end;
|
|
|
|
procedure TCustomPropertyStorage.EraseSections;
|
|
begin
|
|
StorageNeeded(False);
|
|
try
|
|
DoEraseSections(RootSection);
|
|
finally
|
|
FreeStorage;
|
|
end;
|
|
end;
|
|
|
|
procedure TCustomPropertyStorage.SetStoredValues(Value: TStoredValues);
|
|
begin
|
|
FStoredValues.Assign(Value);
|
|
end;
|
|
|
|
function TCustomPropertyStorage.GetStoredValue(const AName: string): TStoredType;
|
|
begin
|
|
Result := StoredValues.StoredValue[AName];
|
|
end;
|
|
|
|
procedure TCustomPropertyStorage.SetStoredValue(const AName: string; Value: TStoredType);
|
|
begin
|
|
StoredValues.StoredValue[AName] := Value;
|
|
end;
|
|
|
|
|
|
end.
|