ideintf: object inspector refactoring from Alexander S. Klenin (Mantis #0012871)

- extract IsCurrentEditorAvailable function
 - use CanEditRowValue function
 - move favorite and restricted properties into a separate unit
 - restrict visibility of public fields
 - remove duplicated code in TObjectInspectorDlg.CreateNoteBook

git-svn-id: trunk@17970 -
This commit is contained in:
paul 2008-12-29 03:06:09 +00:00
parent 62627a79ff
commit 8af15edac9
6 changed files with 807 additions and 855 deletions

1
.gitattributes vendored
View File

@ -2881,6 +2881,7 @@ ideintf/objectinspector.lrs svneol=native#text/plain
ideintf/objectinspector.pp svneol=native#text/plain
ideintf/objectinspector_img.lrs svneol=native#text/plain
ideintf/objinspstrconsts.pas svneol=native#text/pascal
ideintf/oifavouriteproperties.pas svneol=native#text/pascal
ideintf/packageintf.pas svneol=native#text/pascal
ideintf/projectintf.pas svneol=native#text/pascal
ideintf/projectresourcesintf.pas svneol=native#text/pascal

View File

@ -26,7 +26,7 @@ uses
Classes, SysUtils, LCLProc, Forms, Controls, Buttons, StdCtrls, TypInfo,
ExtCtrls, Dialogs, Menus, ComCtrls, Grids, CustomTimer,
CodeToolManager, CodeCache,
LazIDEIntf, ProjectIntf, ObjectInspector, PropEdits,
LazIDEIntf, ProjectIntf, ObjectInspector, OIFavouriteProperties, PropEdits,
DialogProcs, FileUtil, LazConf, BaseIDEIntf, LazConfigStorage,
LazarusIDEStrConsts;

View File

@ -34,8 +34,8 @@ unit CompatibilityRestrictions;
interface
uses
Classes, Forms, SysUtils, InterfaceBase, ObjectInspector, PackageSystem, PackageDefs,
ComponentReg, Laz_XMLRead, Laz_XMLWrite, Laz_DOM, LazConf, LCLProc, StringHashList;
Classes, Forms, SysUtils, InterfaceBase, ObjectInspector, OIFavouriteProperties, PackageSystem,
PackageDefs, ComponentReg, Laz_XMLRead, Laz_XMLWrite, Laz_DOM, LazConf, LCLProc, StringHashList;
type
TReadRestrictedEvent = procedure (const RestrictedName, WidgetSetName: String) of object;
@ -242,7 +242,7 @@ begin
if AClass = nil then
begin
// add as generic widgetset issue
Inc(FRestrictedProperties.WidgetSetRestrictions[DirNameToLCLPlatform(WidgetSetName)]);
FRestrictedProperties.WidgetSetRestrictions[DirNameToLCLPlatform(WidgetSetName)] := FRestrictedProperties.WidgetSetRestrictions[DirNameToLCLPlatform(WidgetSetName)] + 1;
Exit;
end;

View File

@ -49,6 +49,7 @@ uses
MenuIntf,
NewItemIntf,
ObjectInspector,
OIFavouriteProperties,
ObjInspStrConsts,
PackageIntf,
ProjectIntf,

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,667 @@
{ $Id: oifavouriteproperties.pas 17395 2008-11-15 03:53:22Z paul $}
{
*****************************************************************************
* *
* See the file COPYING.modifiedLGPL.txt, included in this distribution, *
* for details about the copyright. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* *
*****************************************************************************
}
unit OIFavouriteProperties;
{$MODE OBJFPC}{$H+}
interface
uses
// FCL
SysUtils, Classes,
// LCL
InterfaceBase, LazConfigStorage, PropEdits;
type
TWidgetSetRestrictionsArray = array [TLCLPlatform] of Integer;
{ TOIFavouriteProperty
BaseClassName }
TOIFavouriteProperty = class
protected
BaseClass: TPersistentClass;
BaseClassname: string;
PropertyName: string;
Include: boolean; // include or exclude
public
constructor Create(ABaseClass: TPersistentClass;
const APropertyName: string; TheInclude: boolean);
function Constrains(AnItem: TOIFavouriteProperty): boolean;
function IsFavourite(AClass: TPersistentClass;
const APropertyName: string): boolean;
function Compare(AFavourite: TOIFavouriteProperty): integer;
procedure SaveToConfig(ConfigStore: TConfigStorage; const Path: string);
procedure Assign(Src: TOIFavouriteProperty); virtual;
function CreateCopy: TOIFavouriteProperty;
function DebugReportAsString: string;
end;
{ TOIRestrictedProperty}
TOIRestrictedProperty = class(TOIFavouriteProperty)
protected
FWidgetSets: TLCLPlatforms;
public
function IsRestricted(AClass: TPersistentClass;
const APropertyName: string): TLCLPlatforms;
procedure CheckRestrictions(
AClass: TClass; var ARestrictions: TWidgetSetRestrictionsArray);
property WidgetSets: TLCLPlatforms read FWidgetSets write FWidgetSets;
end;
{ TOIFavouriteProperties }
TOIFavouriteProperties = class
private
FItems: TFPList; // list of TOIFavouriteProperty
FModified: Boolean;
FSorted: Boolean;
FDoublesDeleted: Boolean;
protected
function GetCount: integer; virtual;
function GetItems(Index: integer): TOIFavouriteProperty; virtual;
public
constructor Create;
destructor Destroy; override;
procedure Clear; virtual;
procedure Assign(Src: TOIFavouriteProperties); virtual;
function CreateCopy: TOIFavouriteProperties;
function Contains(AnItem: TOIFavouriteProperty): Boolean; virtual;
procedure Add(NewItem: TOIFavouriteProperty); virtual;
procedure AddNew(NewItem: TOIFavouriteProperty);
procedure Remove(AnItem: TOIFavouriteProperty); virtual;
procedure DeleteConstraints(AnItem: TOIFavouriteProperty); virtual;
function IsFavourite(
AClass: TPersistentClass; const PropertyName: string): boolean;
function AreFavourites(
Selection: TPersistentSelectionList; const PropertyName: string): boolean;
procedure LoadFromConfig(ConfigStore: TConfigStorage; const Path: string);
procedure SaveToConfig(ConfigStore: TConfigStorage; const Path: string);
procedure MergeConfig(ConfigStore: TConfigStorage; const Path: string);
procedure SaveNewItemsToConfig(
ConfigStore: TConfigStorage;
const Path: string; BaseFavourites: TOIFavouriteProperties);
procedure Sort; virtual;
procedure DeleteDoubles; virtual;
function IsEqual(TheFavourites: TOIFavouriteProperties): boolean;
function GetSubtractList(FavouritesToSubtract: TOIFavouriteProperties): TList;
procedure WriteDebugReport;
public
property Items[Index: integer]: TOIFavouriteProperty read GetItems; default;
property Count: integer read GetCount;
property Modified: Boolean read FModified write FModified;
property Sorted: Boolean read FSorted;
property DoublesDeleted: boolean read FDoublesDeleted;
end;
TOIFavouritePropertiesClass = class of TOIFavouriteProperties;
{ TOIRestrictedProperties }
TOIRestrictedProperties = class(TOIFavouriteProperties)
protected
FWidgetSetRestrictions: TWidgetSetRestrictionsArray;
public
constructor Create;
function IsRestricted(AClass: TPersistentClass;
const PropertyName: string): TLCLPlatforms;
function AreRestricted(Selection: TPersistentSelectionList;
const PropertyName: string): TLCLPlatforms;
property WidgetSetRestrictions: TWidgetSetRestrictionsArray
read FWidgetSetRestrictions;
end;
implementation
uses
LCLProc;
function CompareOIFavouriteProperties(Data1, Data2: Pointer): integer;
var
Favourite1: TOIFavouriteProperty;
Favourite2: TOIFavouriteProperty;
begin
Favourite1:=TOIFavouriteProperty(Data1);
Favourite2:=TOIFavouriteProperty(Data2);
Result:=Favourite1.Compare(Favourite2)
end;
{ TOIFavouriteProperties }
function TOIFavouriteProperties.GetCount: integer;
begin
Result:=FItems.Count;
end;
function TOIFavouriteProperties.GetItems(Index: integer): TOIFavouriteProperty;
begin
Result:=TOIFavouriteProperty(FItems[Index]);
end;
constructor TOIFavouriteProperties.Create;
begin
FItems:=TFPList.Create;
end;
destructor TOIFavouriteProperties.Destroy;
begin
Clear;
FreeAndNil(FItems);
inherited Destroy;
end;
procedure TOIFavouriteProperties.Clear;
var
i: Integer;
begin
for i:=0 to FItems.Count-1 do
TObject(FItems[i]).Free;
FItems.Clear;
FSorted:=true;
end;
procedure TOIFavouriteProperties.Assign(Src: TOIFavouriteProperties);
var
i: Integer;
begin
Clear;
for i:=0 to Src.Count-1 do
FItems.Add(Src[i].CreateCopy);
FModified:=Src.Modified;
FDoublesDeleted:=Src.DoublesDeleted;
FSorted:=Src.Sorted;
end;
function TOIFavouriteProperties.CreateCopy: TOIFavouriteProperties;
begin
Result:=TOIFavouriteProperties.Create;
Result.Assign(Self);
end;
function TOIFavouriteProperties.Contains(AnItem: TOIFavouriteProperty
): Boolean;
var
i: Integer;
begin
for i:=Count-1 downto 0 do begin
if Items[i].Compare(AnItem)=0 then begin
Result:=true;
exit;
end;
end;
Result:=false;
end;
procedure TOIFavouriteProperties.Add(NewItem: TOIFavouriteProperty);
begin
FItems.Add(NewItem);
FSorted:=(Count<=1)
or (FSorted and (Items[Count-1].Compare(Items[Count-2])<0));
FDoublesDeleted:=FSorted
and ((Count<=1) or (Items[Count-1].Compare(Items[Count-2])<>0));
Modified:=true;
end;
procedure TOIFavouriteProperties.AddNew(NewItem: TOIFavouriteProperty);
begin
if Contains(NewItem) then
NewItem.Free
else
Add(NewItem);
end;
procedure TOIFavouriteProperties.Remove(AnItem: TOIFavouriteProperty);
begin
Modified:=FItems.Remove(AnItem)>=0;
end;
procedure TOIFavouriteProperties.DeleteConstraints(
AnItem: TOIFavouriteProperty);
// delete all items, that would constrain AnItem
var
i: Integer;
CurItem: TOIFavouriteProperty;
begin
for i:=Count-1 downto 0 do begin
CurItem:=Items[i];
if CurItem.Constrains(AnItem) then begin
FItems.Delete(i);
Modified:=true;
CurItem.Free;
end;
end;
end;
function TOIFavouriteProperties.IsFavourite(AClass: TPersistentClass;
const PropertyName: string): boolean;
var
i: Integer;
CurItem: TOIFavouriteProperty;
BestItem: TOIFavouriteProperty;
begin
if (AClass=nil) or (PropertyName='') then begin
Result:=false;
exit;
end;
BestItem:=nil;
for i:=0 to Count-1 do begin
CurItem:=Items[i];
if not CurItem.IsFavourite(AClass,PropertyName) then continue;
if (BestItem=nil)
or (AClass.InheritsFrom(BestItem.BaseClass)) then begin
//debugln('TOIFavouriteProperties.IsFavourite ',AClass.ClassName,' ',PropertyName);
BestItem:=CurItem;
end;
end;
Result:=(BestItem<>nil) and BestItem.Include;
end;
function TOIFavouriteProperties.AreFavourites(
Selection: TPersistentSelectionList; const PropertyName: string): boolean;
var
i: Integer;
begin
Result:=(Selection<>nil) and (Selection.Count>0);
if not Result then exit;
for i:=0 to Selection.Count-1 do begin
if not IsFavourite(TPersistentClass(Selection[i].ClassType),PropertyName)
then begin
Result:=false;
exit;
end;
end;
end;
procedure TOIFavouriteProperties.LoadFromConfig(ConfigStore: TConfigStorage;
const Path: string);
var
NewCount: LongInt;
i: Integer;
NewItem: TOIFavouriteProperty;
p: String;
NewPropertyName: String;
NewInclude: Boolean;
NewBaseClassname: String;
NewBaseClass: TPersistentClass;
begin
Clear;
NewCount:=ConfigStore.GetValue(Path+'Count',0);
for i:=0 to NewCount-1 do begin
p:=Path+'Item'+IntToStr(i)+'/';
NewPropertyName:=ConfigStore.GetValue(p+'PropertyName','');
if (NewPropertyName='') or (not IsValidIdent(NewPropertyName)) then
continue;
NewInclude:=ConfigStore.GetValue(p+'Include',true);
NewBaseClassname:=ConfigStore.GetValue(p+'BaseClass','');
if (NewBaseClassname='') or (not IsValidIdent(NewBaseClassname)) then
continue;
NewBaseClass:=GetClass(NewBaseClassname);
NewItem:=TOIFavouriteProperty.Create(NewBaseClass,NewPropertyName,
NewInclude);
NewItem.BaseClassName:=NewBaseClassname;
Add(NewItem);
end;
{$IFDEF DebugFavouriteroperties}
debugln('TOIFavouriteProperties.LoadFromConfig END');
WriteDebugReport;
{$ENDIF}
end;
procedure TOIFavouriteProperties.SaveToConfig(ConfigStore: TConfigStorage;
const Path: string);
var
i: Integer;
begin
ConfigStore.SetDeleteValue(Path+'Count',Count,0);
for i:=0 to Count-1 do
Items[i].SaveToConfig(ConfigStore,Path+'Item'+IntToStr(i)+'/');
end;
procedure TOIFavouriteProperties.MergeConfig(ConfigStore: TConfigStorage;
const Path: string);
var
NewFavourites: TOIFavouriteProperties;
OldItem: TOIFavouriteProperty;
NewItem: TOIFavouriteProperty;
cmp: LongInt;
NewIndex: Integer;
OldIndex: Integer;
begin
NewFavourites:=TOIFavouritePropertiesClass(ClassType).Create;
{$IFDEF DebugFavouriteroperties}
debugln('TOIFavouriteProperties.MergeConfig ',dbgsName(NewFavourites),' ',dbgsName(NewFavourites.FItems));
{$ENDIF}
try
// load config
NewFavourites.LoadFromConfig(ConfigStore,Path);
// sort both to see the differences
NewFavourites.DeleteDoubles; // descending
DeleteDoubles; // descending
// add all new things from NewFavourites
NewIndex:=0;
OldIndex:=0;
while (NewIndex<NewFavourites.Count) do begin
NewItem:=NewFavourites[NewIndex];
if OldIndex>=Count then begin
// item only exists in config -> move to this list
NewFavourites.FItems[NewIndex]:=nil;
inc(NewIndex);
FItems.Insert(OldIndex,NewItem);
inc(OldIndex);
end else begin
OldItem:=Items[OldIndex];
cmp:=OldItem.Compare(NewItem);
//debugln('TOIFavouriteProperties.MergeConfig cmp=',dbgs(cmp),' OldItem=[',OldItem.DebugReportAsString,'] NewItem=[',NewItem.DebugReportAsString,']');
if cmp=0 then begin
// item already exists in this list
inc(NewIndex);
inc(OldIndex);
end else if cmp<0 then begin
// item exists only in old favourites
// -> next old
inc(OldIndex);
end else begin
// item only exists in config -> move to this list
NewFavourites.FItems[NewIndex]:=nil;
inc(NewIndex);
FItems.Insert(OldIndex,NewItem);
inc(OldIndex);
end;
end;
end;
finally
NewFavourites.Free;
end;
{$IFDEF DebugFavouriteroperties}
debugln('TOIFavouriteProperties.MergeConfig END');
WriteDebugReport;
{$ENDIF}
end;
procedure TOIFavouriteProperties.SaveNewItemsToConfig(
ConfigStore: TConfigStorage; const Path: string;
BaseFavourites: TOIFavouriteProperties);
// Save all items, that are in this list and not in BaseFavourites
// It does not save, if an item in BaseFavourites is missing in this list
var
SubtractList: TList;
i: Integer;
CurItem: TOIFavouriteProperty;
begin
SubtractList:=GetSubtractList(BaseFavourites);
try
ConfigStore.SetDeleteValue(Path+'Count',SubtractList.Count,0);
{$IFDEF DebugFavouriteroperties}
debugln('TOIFavouriteProperties.SaveNewItemsToConfig A Count=',dbgs(SubtractList.Count));
{$ENDIF}
for i:=0 to SubtractList.Count-1 do begin
CurItem:=TOIFavouriteProperty(SubtractList[i]);
CurItem.SaveToConfig(ConfigStore,Path+'Item'+IntToStr(i)+'/');
{$IFDEF DebugFavouriteroperties}
debugln(' i=',dbgs(i),' ',CurItem.DebugReportAsString);
{$ENDIF}
end;
finally
SubtractList.Free;
end;
end;
procedure TOIFavouriteProperties.Sort;
begin
if FSorted then exit;
FItems.Sort(@CompareOIFavouriteProperties);
end;
procedure TOIFavouriteProperties.DeleteDoubles;
// This also sorts
var
i: Integer;
begin
if FDoublesDeleted then exit;
Sort;
for i:=Count-1 downto 1 do begin
if Items[i].Compare(Items[i-1])=0 then begin
Items[i].Free;
FItems.Delete(i);
end;
end;
FDoublesDeleted:=true;
end;
function TOIFavouriteProperties.IsEqual(TheFavourites: TOIFavouriteProperties
): boolean;
var
i: Integer;
begin
Result:=false;
DeleteDoubles;
TheFavourites.DeleteDoubles;
if Count<>TheFavourites.Count then exit;
for i:=Count-1 downto 1 do
if Items[i].Compare(TheFavourites.Items[i])<>0 then exit;
Result:=true;
end;
function TOIFavouriteProperties.GetSubtractList(
FavouritesToSubtract: TOIFavouriteProperties): TList;
// create a list of TOIFavouriteProperty of all items in this list
// and not in FavouritesToSubtract
var
SelfIndex: Integer;
SubtractIndex: Integer;
CurItem: TOIFavouriteProperty;
cmp: LongInt;
begin
Result:=TList.Create;
DeleteDoubles; // this also sorts descending
FavouritesToSubtract.DeleteDoubles; // this also sorts descending
SelfIndex:=0;
SubtractIndex:=0;
while SelfIndex<Count do begin
CurItem:=Items[SelfIndex];
if SubtractIndex>=FavouritesToSubtract.Count then begin
// item does not exist in SubtractIndex -> add it
Result.Add(CurItem);
inc(SelfIndex);
end else begin
cmp:=CurItem.Compare(FavouritesToSubtract[SubtractIndex]);
//debugln('TOIFavouriteProperties.GetSubtractList cmp=',dbgs(cmp),' CurItem=[',CurItem.DebugReportAsString,'] SubtractItem=[',FavouritesToSubtract[SubtractIndex].DebugReportAsString,']');
if cmp=0 then begin
// item exists in SubtractIndex -> skip
inc(SubtractIndex);
inc(SelfIndex);
end else if cmp>0 then begin
// item does not exist in FavouritesToSubtract -> add it
Result.Add(CurItem);
inc(SelfIndex);
end else begin
// item exists only in FavouritesToSubtract -> skip
inc(SubtractIndex);
end;
end;
end;
end;
procedure TOIFavouriteProperties.WriteDebugReport;
var
i: Integer;
begin
debugln('TOIFavouriteProperties.WriteDebugReport Count=',dbgs(Count));
for i:=0 to Count-1 do
debugln(' i=',dbgs(i),' ',Items[i].DebugReportAsString);
end;
{ TOIFavouriteProperty }
constructor TOIFavouriteProperty.Create(ABaseClass: TPersistentClass;
const APropertyName: string; TheInclude: boolean);
begin
BaseClass:=ABaseClass;
PropertyName:=APropertyName;
Include:=TheInclude;
end;
function TOIFavouriteProperty.Constrains(AnItem: TOIFavouriteProperty
): boolean;
// true if this item constrains AnItem
// This item constrains AnItem, if this is the opposite (Include) and
// AnItem has the same or greater scope
begin
Result:=(Include<>AnItem.Include)
and (CompareText(PropertyName,AnItem.PropertyName)=0)
and (BaseClass.InheritsFrom(AnItem.BaseClass));
end;
function TOIFavouriteProperty.IsFavourite(AClass: TPersistentClass;
const APropertyName: string): boolean;
begin
Result:=(CompareText(PropertyName,APropertyName)=0)
and (AClass.InheritsFrom(BaseClass));
end;
function TOIFavouriteProperty.Compare(AFavourite: TOIFavouriteProperty
): integer;
function CompareBaseClass: integer;
begin
if BaseClass<>nil then begin
if AFavourite.BaseClass<>nil then
Result:=ComparePointers(BaseClass,AFavourite.BaseClass)
else
Result:=CompareText(BaseClass.ClassName,AFavourite.BaseClassName);
end else begin
if AFavourite.BaseClass<>nil then
Result:=CompareText(BaseClassName,AFavourite.BaseClass.ClassName)
else
Result:=CompareText(BaseClassName,AFavourite.BaseClassName);
end;
end;
begin
// first compare PropertyName
Result:=CompareText(PropertyName,AFavourite.PropertyName);
if Result<>0 then exit;
// then compare Include
if Include<>AFavourite.Include then begin
if Include then
Result:=1
else
Result:=-1;
exit;
end;
// then compare BaseClass and BaseClassName
Result:=CompareBaseClass;
end;
procedure TOIFavouriteProperty.SaveToConfig(ConfigStore: TConfigStorage;
const Path: string);
begin
if BaseClass<>nil then
ConfigStore.SetDeleteValue(Path+'BaseClass',BaseClass.ClassName,'')
else
ConfigStore.SetDeleteValue(Path+'BaseClass',BaseClassName,'');
ConfigStore.SetDeleteValue(Path+'PropertyName',PropertyName,'');
ConfigStore.SetDeleteValue(Path+'Include',Include,true);
end;
procedure TOIFavouriteProperty.Assign(Src: TOIFavouriteProperty);
begin
BaseClassName:=Src.BaseClassName;
BaseClass:=Src.BaseClass;
PropertyName:=Src.PropertyName;
Include:=Src.Include;
end;
function TOIFavouriteProperty.CreateCopy: TOIFavouriteProperty;
begin
Result:=TOIFavouriteProperty.Create(BaseClass,PropertyName,Include);
Result.BaseClass:=BaseClass;
end;
function TOIFavouriteProperty.DebugReportAsString: string;
begin
Result:='PropertyName="'+PropertyName+'"'
+' Include='+dbgs(Include)
+' BaseClassName="'+BaseClassName+'"'
+' BaseClass='+dbgsName(BaseClass);
end;
{ TOIRestrictedProperty }
procedure TOIRestrictedProperty.CheckRestrictions(
AClass: TClass; var ARestrictions: TWidgetSetRestrictionsArray);
var
lclPlatform: TLCLPlatform;
begin
if AClass.InheritsFrom(BaseClass) and (PropertyName = '') then
for lclPlatform := Low(TLCLPlatform) to High(TLCLPlatform) do
if lclPlatform in WidgetSets then
Inc(ARestrictions[lclPlatform]);
end;
function TOIRestrictedProperty.IsRestricted(AClass: TPersistentClass;
const APropertyName: string): TLCLPlatforms;
begin
//DebugLn('IsRestricted ', AClass.ClassName, ' ?= ', BaseClass.ClassName, ' ', APropertyName, ' ?= ', PropertyName);
Result := [];
if (CompareText(PropertyName,APropertyName) = 0)
and (AClass.InheritsFrom(BaseClass)) then Result := WidgetSets;
end;
{ TOIRestrictedProperties }
constructor TOIRestrictedProperties.Create;
var
P: TLCLPlatform;
begin
inherited Create;
for P := Low(TLCLPlatform) to High(TLCLPlatform) do
FWidgetSetRestrictions[P] := 0;
end;
function TOIRestrictedProperties.IsRestricted(AClass: TPersistentClass;
const PropertyName: string): TLCLPlatforms;
var
I: Integer;
CurItem: TOIRestrictedProperty;
begin
Result := [];
if (AClass=nil) or (PropertyName='') then Exit;
for I := 0 to Count - 1 do
begin
if not (Items[I] is TOIRestrictedProperty) then Continue;
CurItem:=Items[I] as TOIRestrictedProperty;
Result := Result + CurItem.IsRestricted(AClass,PropertyName);
end;
end;
function TOIRestrictedProperties.AreRestricted(
Selection: TPersistentSelectionList;
const PropertyName: string): TLCLPlatforms;
var
I: Integer;
begin
Result := [];
if Selection = nil then Exit;
for i:=0 to Selection.Count-1 do
begin
Result := Result + IsRestricted(TPersistentClass(Selection[i].ClassType), PropertyName);
end;
end;
end.