Инспектор объектов и метаданные
·Поле Name содержит имя published-свойства в инспектируемом объекте или в его заместителе. Доступ к свойствам основан на RTTI и требует, чтобы инспектируемые объекты (или их заместители) компилировались с созданием RTTI, ·Поле Caption содержит имя свойства, под которым оно будет отображаться в инспекторе, ·Kind. Это поле декларирует особенности отображения значения свойства в инспекторе, например, значение может быть текстом, списком, множеством, сложным объектом, который редактируется специальным редактором и так далее, ·Tag используется для задания специфических данных свойства. В текущей версии инспектора он использует только для описания свойств-множеств, ·NestedType и NestedClass. Два этих поля предоставляют альтернативные возможности указания типа вложенного свойства. Здесь целесообразно отметить, что вложенные свойства рассматриваются и описываются как самостоятельные - это позволяет описать их один раз и использовать в других классах метаданных. Забегая вперед, скажу что NestedType используется в том случае, если класс метаданных регистрируется в реестре метаданных, а NestedClass - если вложенный объект описывается в известном программном модуле и доступен при компиляции. Вложенное свойство трактуется весьма широко и, в общем случае, служит для ссылки на другой класс метаданных, который может быть действительно сложным объектом, или предоставлять метаданные об одном-единственном простом свойстве. Важным здесь является то, что классы метаданных могут ссылаться на другие метаклассы и создавать внутреннюю иерархическую структуру свойств инспектируемого объекта, ·Поля Help и Hint в особых комментариях не нуждаются. Поле Kind может принимать (в данной версии инспектора) следующие значения: ·pkText - значение свойства отображается как текст, доступный для редактирования, ·pkDropDownList - значение свойства доступно для выбора из списка возможных значений, ·pkDialog - значения свойства редактируются специализированным диалогом-мастером, ·pkFolder - фиктивное свойство, не имеющее значения, но позволяющее выстроить иерархический список дочерних подсвойств, ·pkReadOnlyText - аналогично pkText, но доступно только для чтения, ·pkImmediateText - аналогично pkText, но изменение значения свойства фиксируются немедленно при любом изменении текста, ·pkBoolean - свойство отображается как CheckBox, ·pkTextList - подобно pkDropDownList, но значение свойства можно редактировать, то есть, диапазон значений не ограничен списком, ·pkSet - свойство-множество, отображается как родительское для вложенного списка элементов множества, каждый из которых представляется как логическое значение, ·pkColor - свойство для выбора цвета из заданного списка, ·pkColorRGB - подобно предыдущему, но цвет задается и редактируется в виде R.G.B и имеется возможность выбора цвета с помощью стандартного Windows-диалога. Для иллюстрации всего сказанного приведем конкретный пример. Для простоты предположим, что мы будем инспектировать объекты всем известного типа TLabel. Причем, будем считать, что пользователю доступны для инспекции только свойства Caption, Font, Color, а также координаты и размеры. Класс метаданных для TLabel будет, в данном случае, таким:
TLabel_INFO = class(TGsvObjectInspectorTypeInfo)
public
class function ChildrenInfo(Index: Integer):
PGsvObjectInspectorPropertyInfo; override;
end;
class function TLabel_INFO.ChildrenInfo(Index: Integer):
PGsvObjectInspectorPropertyInfo;
const
DSK: array[0..3] of TGsvObjectInspectorPropertyInfo = (
( Name: 'Caption'; Caption: 'Надпись'; Kind: pkImmediateText ),
( NestedClass: TGsvBounds_INFO ),
( Name: 'Font'; NestedType: 'TFont' ),
( Name: 'Color'; Caption: 'Цвет фона'; NestedType: 'TGsvColorRGB' )
);
begin
if Index <= High(DSK) then Result := @DSK[Index]
else Result := nil;
end;
GsvRegisterTypeInfo(TLabel_INFO);
Поскольку в предложенном описании даны ссылки на другие метаклассы, то продолжим пример и предоставим их реализацию.
TGsvBounds_INFO = class(TGsvObjectInspectorTypeInfo)
public
class function TypeInfo: PGsvObjectInspectorPropertyInfo; override;
class function ChildrenInfo(Index: Integer):
PGsvObjectInspectorPropertyInfo; override;
end;
class function TGsvBounds_INFO.TypeInfo: PGsvObjectInspectorPropertyInfo;
const
DSK: TGsvObjectInspectorPropertyInfo = (
Caption: 'Положение и размер'; Kind: pkFolder;
Help: 1234; Hint: 'Координаты верхнего левого угла и размеры'
);
begin
Result := @DSK;
end;
class function TGsvBounds_INFO.ChildrenInfo(Index: Integer):
PGsvObjectInspectorPropertyInfo;
const
DSK: array[0..3] of TGsvObjectInspectorPropertyInfo = (
( Name: 'Left'; Caption: 'Левый край'; Kind: pkText ),
( Name: ''; Caption: 'Верхний край'; Kind: pkText ),
( Name: 'Width'; Caption: 'Ширина'; Kind: pkText ),
( Name: 'Height'; Caption: 'Высота'; Kind: pkText )
);
begin
if Index <= High(DSK) then Result := @DSK[Index]
else Result := nil;
end;
Метакласс TGsvBounds_INFO перегружает два метода базового класса. Метод TypeInfo возвращает указатель на метаданные всего класса в целом. Это позволяет задать аттрибуты свойства в одном метаклассе и ссылаться на них из множества других метаклассов. Метод возвращает указатель на константную запись, в которой мы задаем название, вид поля и справочную информацию о свойстве. Метод ChildrenInfo описывает координаты верхнего левого угла прямоугольника и его размеры, ссылаясь на соответствующие published-свойства компонента. Метакласс для шрифта будет задавать имя шрифта, его размер, стиль и цвет:
TFont_INFO = class(TGsvObjectInspectorTypeFontInfo)
public
class function TypeInfo: PGsvObjectInspectorPropertyInfo; override;
class function ChildrenInfo(Index: Integer):
PGsvObjectInspectorPropertyInfo; override;
end;
class function TFont_INFO.TypeInfo: PGsvObjectInspectorPropertyInfo;
const
DSK: TGsvObjectInspectorPropertyInfo = (
Caption: 'Шрифт'; Kind: pkDialog
);
begin
Result := @DSK;
end;
class function TFont_INFO.ChildrenInfo(Index: Integer):
PGsvObjectInspectorPropertyInfo;
const
DSK: array[0..3] of TGsvObjectInspectorPropertyInfo = (
( Name: 'Name'; Caption: 'Имя'; Kind: pkText;
Hint: 'Имя шрифта' ),
( Name: 'Size'; Caption: 'Размер'; Kind: pkText;
Hint: 'Размер в пунктах' ),
( Name: 'Style'; Caption: 'Стиль'; Kind: pkSet;
NestedClass: TFontStyles_INFO ),
( Name: 'Color'; Caption: 'Цвет'; Kind: pkColor;
NestedClass: TGsvColor16_INFO )
);
begin
if Index <= High(DSK) then Result := @DSK[Index]
else Result := nil;
end;
Отправить комментарий