CnAutoOption.pas 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699
  1. {******************************************************************************}
  2. { CnPack For Delphi/C++Builder }
  3. { 中国人自己的开放源码第三方开发包 }
  4. { (C)Copyright 2001-2018 CnPack 开发组 }
  5. { ------------------------------------ }
  6. { }
  7. { 本开发包是开源的自由软件,您可以遵照 CnPack 的发布协议来修 }
  8. { 改和重新发布这一程序。 }
  9. { }
  10. { 发布这一开发包的目的是希望它有用,但没有任何担保。甚至没有 }
  11. { 适合特定目的而隐含的担保。更详细的情况请参阅 CnPack 发布协议。 }
  12. { }
  13. { 您应该已经和开发包一起收到一份 CnPack 发布协议的副本。如果 }
  14. { 还没有,可访问我们的网站: }
  15. { }
  16. { 网站地址:http://www.cnpack.org }
  17. { 电子邮件:master@cnpack.org }
  18. { }
  19. {******************************************************************************}
  20. unit CnAutoOption;
  21. {* |<PRE>
  22. ================================================================================
  23. * 软件名称:不可视工具组件包
  24. * 单元名称:自动参数设置类定义单元
  25. * 单元作者:周劲羽 (zjy@cnpack.org)
  26. * 开发平台:PWin2000 SP4 + Delphi 5.01
  27. * 兼容测试:PWin9X/2000/XP + Delphi 5/6/7
  28. * 本 地 化:该单元中的字符串均符合本地化处理方式
  29. * 单元标识:$Id$
  30. * 备 注:该单元定义了自动参数设置信息类
  31. * 用于在运行时使用树状结构根据设置信息对象显示通用的设置界面。
  32. ================================================================================
  33. |</PRE>}
  34. interface
  35. {$I CnPack.inc}
  36. uses
  37. Windows, Messages, SysUtils, Classes, Graphics, Controls, Contnrs,
  38. {$IFDEF COMPILER6_UP} Variants, {$ENDIF COMPILER6_UP}
  39. TypInfo, Forms;
  40. type
  41. { Exception }
  42. EInvalidPropItem = Exception;
  43. {* 无效的属性信息项异常 }
  44. { TCnBaseOption }
  45. TCnOptionGroup = class;
  46. TCnOptionClass = class of TCnBaseOption;
  47. {* 设置信息类类型 }
  48. TCnBaseOption = class(TPersistent)
  49. {* 设置信息基础类 }
  50. private
  51. FIsStored: Boolean;
  52. FOwner: TCnOptionGroup;
  53. FText: string;
  54. FVisible: Boolean;
  55. public
  56. constructor Create(AOwner: TCnOptionGroup); virtual;
  57. {* 类构造器,参数为所有者 }
  58. procedure Assign(Source: TPersistent); override;
  59. {* 对象赋值方法,使用 RTTI 来自动对发布属性赋值,子类只需要处理非发布属性
  60. 即可,子类如果 override 该方法,需要 inherited }
  61. property Owner: TCnOptionGroup read FOwner;
  62. {* 设置项的所有者 }
  63. published
  64. property IsStored: Boolean read FIsStored write FIsStored;
  65. {* 标识该项设置是否保存到设置文件中 }
  66. property Text: string read FText write FText;
  67. {* 设置项显示的标题 }
  68. end;
  69. { TCnOptionCustom }
  70. TCnOptionCustom = class(TCnBaseOption)
  71. {* 使用一个按钮进行设置的参数项类 }
  72. private
  73. FOnClick: TNotifyEvent;
  74. FCaption: string;
  75. published
  76. property OnClick: TNotifyEvent read FOnClick write FOnClick;
  77. {* 设置按钮点击事件 }
  78. property Caption: string read FCaption write FCaption;
  79. {* 设置按钮标题 }
  80. end;
  81. { TCnOptionItem }
  82. TCnOptionItem = class(TCnBaseOption)
  83. {* 属性设置项类,该类实例与一个运行期需要配置的对象属性关联 }
  84. private
  85. FDefaultValue: Variant;
  86. FInstance: TObject;
  87. FList: TStrings;
  88. FMaxValue: Variant;
  89. FMinValue: Variant;
  90. FPropName: string;
  91. FValue: Variant;
  92. function GetDefaultValue: Variant;
  93. procedure SetList(Value: TStrings);
  94. function GetPropInfo: PPropInfo;
  95. function GetPropKind: TTypeKind;
  96. function GetPropValue: Variant;
  97. procedure SetPropValue(const Value: Variant);
  98. function GetMaxValue: Variant;
  99. function GetMinValue: Variant;
  100. procedure SetDefaultValue(const Value: Variant);
  101. procedure SetMaxValue(const Value: Variant);
  102. procedure SetMinValue(const Value: Variant);
  103. protected
  104. procedure ClearValue;
  105. public
  106. constructor Create(AOwner: TCnOptionGroup); override;
  107. {* 类构造器,参数为所有者 }
  108. destructor Destroy; override;
  109. {* 类析构器 }
  110. procedure ApplyOption;
  111. {* 应用当前的设置到对象属性 }
  112. procedure DefaultOption;
  113. {* 恢复设置为原对象属性的默认值 }
  114. procedure ResetOption;
  115. {* 恢复设置为原对象属性的当前值 }
  116. property PropInfo: PPropInfo read GetPropInfo;
  117. {* 关联对象的属性类型信息,如果属性不正确,会弹出 EInvalidPropItem 异常 }
  118. property PropKind: TTypeKind read GetPropKind;
  119. {* 关联对象属性的类型,如果属性不正确,会弹出 EInvalidPropItem 异常 }
  120. property PropValue: Variant read GetPropValue write SetPropValue;
  121. {* 关联对象属性的值,可读取和修改。如果属性不正确,会弹出 EInvalidPropItem 异常 }
  122. property Value: Variant read FValue write FValue;
  123. {* 可用来临时存放当前设置值 }
  124. published
  125. property DefaultValue: Variant read GetDefaultValue write SetDefaultValue;
  126. {* 关联对象属性的默认值,如果没有指定,会自动从属性定义中查找。
  127. 如果没有设置默认值且属性不正确,会弹出 EInvalidPropItem 异常 }
  128. property Instance: TObject read FInstance write FInstance;
  129. {* 关联的对象实例 }
  130. property List: TStrings read FList write SetList;
  131. {* 附加显示信息,如果关联对象属性为枚举或集合,该字符串列表用来保存每一个
  132. 枚举项的描述信息。如果关联对象属性为字符串类型,该列表可用来保存可选择
  133. 的下拉列表值。如果关联对象属性为整数类型,该列表可用来保存下拉列表值,
  134. 属性整数对应列表索引 }
  135. property MaxValue: Variant read GetMaxValue write SetMaxValue;
  136. {* 关联对象属性允许的最大值 }
  137. property MinValue: Variant read GetMinValue write SetMinValue;
  138. {* 关联对象属性允许的最小值 }
  139. property PropName: string read FPropName write FPropName;
  140. {* 关联对象属性的名称 }
  141. end;
  142. { TCnOptionGroup }
  143. TCnOptionGroup = class(TCnBaseOption)
  144. private
  145. FList: TObjectList;
  146. function GetCount: Integer;
  147. function GetItems(Index: Integer): TCnBaseOption;
  148. procedure SetItems(Index: Integer; Value: TCnBaseOption);
  149. protected
  150. property List: TObjectList read FList;
  151. public
  152. constructor Create(AOwner: TCnOptionGroup); override;
  153. {* 类构造器,参数为所有者 }
  154. destructor Destroy; override;
  155. {* 类析构器 }
  156. function Add(Item: TCnBaseOption): Integer;
  157. {* 增加一个子设置项 }
  158. function AddGroup(const AText: string): TCnOptionGroup;
  159. {* 增加一个新的子设置组,参数为标题 }
  160. function AddCustom(const AText: string; OnClick: TNotifyEvent; const ACaption:
  161. string = ''): TCnOptionCustom;
  162. {* 增加一个新的按钮设置项 }
  163. function AddItem(AInstance: TObject; const APropName: string; const AText:
  164. string = ''; const AList: string = ''): TCnOptionItem; overload;
  165. {* 增加一个子属性设置项,参数见 TCnOptionItem 定义,其中 AList 为多行文本字符串 }
  166. function AddItem(AInstance: TObject; const APropName: string; const AText:
  167. string; const AList: string; ADefaultValue, AMinValue, AMaxValue: Variant):
  168. TCnOptionItem; overload;
  169. {* 增加一个子属性设置项,参数见 TCnOptionItem 定义,其中 AList 为多行文本字符串 }
  170. procedure Assign(Source: TPersistent); override;
  171. {* 对象赋值方法 }
  172. procedure Clear;
  173. {* 清空所有子项 }
  174. procedure Delete(Index: Integer);
  175. {* 删除并释放一个子项 }
  176. function IndexOf(Item: TCnBaseOption): Integer;
  177. {* 查找子项,返回索引号 }
  178. procedure Insert(Index: Integer; Item: TCnBaseOption);
  179. {* 在指定位置插入一个子项 }
  180. procedure Move(CurIndex, NewIndex: Integer);
  181. {* 移动子项到新的位置 }
  182. property Count: Integer read GetCount;
  183. {* 子项的总数 }
  184. property Items[Index: Integer]: TCnBaseOption read GetItems write SetItems;
  185. default;
  186. {* 设置参数子项数组 }
  187. end;
  188. function IsBooleanType(PInfo: PTypeInfo): Boolean;
  189. function IsBoolType(PInfo: PTypeInfo): Boolean;
  190. implementation
  191. {$IFDEF DEBUG}
  192. uses
  193. CnDebug;
  194. {$ENDIF}
  195. type
  196. TPersistentHack = class(TPersistent);
  197. function VarToIntVar(const Value: Variant): Variant;
  198. var
  199. R, E: Integer;
  200. S: string;
  201. begin
  202. Result := Null;
  203. try
  204. if VarIsNull(Value) then
  205. Exit;
  206. S := Trim(VarToStr(Value));
  207. if S <> '' then
  208. begin
  209. Val(S, R, E);
  210. if E = 0 then
  211. Result := R;
  212. end;
  213. except
  214. ;
  215. end;
  216. end;
  217. function VarToFloatVar(const Value: Variant): Variant;
  218. var
  219. R: Extended;
  220. begin
  221. if TextToFloat(PChar(VarToStr(Value)), R, fvExtended) then
  222. Result := R
  223. else
  224. Result := Null;
  225. end;
  226. function IsBoolType(PInfo: PTypeInfo): Boolean;
  227. begin
  228. Result := (PInfo^.Kind = tkEnumeration) and
  229. (GetTypeData(PInfo)^.MinValue < 0); // Longbool/wordbool/bytebool
  230. end;
  231. function IsBooleanType(PInfo: PTypeInfo): Boolean;
  232. begin
  233. Result := (PInfo.Kind = tkEnumeration) and
  234. (GetTypeData(PInfo)^.BaseType^ = TypeInfo(Boolean));
  235. end;
  236. { TCnBaseOption }
  237. constructor TCnBaseOption.Create(AOwner: TCnOptionGroup);
  238. begin
  239. inherited Create;
  240. FOwner := AOwner;
  241. FText := '';
  242. FVisible := True;
  243. FIsStored := True;
  244. end;
  245. procedure TCnBaseOption.Assign(Source: TPersistent);
  246. var
  247. Stream: TMemoryStream;
  248. Reader: TReader;
  249. Writer: TWriter;
  250. Count: Integer;
  251. PropIdx: Integer;
  252. PropList: PPropList;
  253. PropName: string;
  254. PropInfo: PPropInfo;
  255. begin
  256. if Source is ClassType then
  257. begin
  258. // 使用 RTTI 来保证赋值所有 published 属性(流不能传递值为 Default 的属性)
  259. Count := GetPropList(Self.ClassInfo, tkProperties - [tkArray, tkRecord,
  260. tkInterface], nil);
  261. GetMem(PropList, Count * SizeOf(Pointer));
  262. try
  263. GetPropList(ClassInfo, tkProperties - [tkArray, tkRecord,
  264. tkInterface], @PropList^[0]);
  265. for PropIdx := 0 to Count - 1 do
  266. begin
  267. PropInfo := PropList^[PropIdx];
  268. PropName := string(PropInfo^.Name);
  269. case PropInfo^.PropType^^.Kind of
  270. tkInteger, tkChar, tkWChar, tkClass, tkEnumeration, tkSet:
  271. SetOrdProp(Self, PropInfo, GetOrdProp(Source, PropInfo));
  272. tkFloat:
  273. SetFloatProp(Self, PropInfo, GetFloatProp(Source, PropInfo));
  274. tkString, tkLString, tkWString{$IFDEF UNICODE_STRING}, tkUString{$ENDIF}:
  275. SetStrProp(Self, PropInfo, GetStrProp(Source, PropInfo));
  276. tkVariant:
  277. SetVariantProp(Self, PropInfo, GetVariantProp(Source, PropInfo));
  278. tkInt64:
  279. SetInt64Prop(Self, PropInfo, GetInt64Prop(Source, PropInfo));
  280. tkMethod:
  281. SetMethodProp(Self, PropInfo, GetMethodProp(Source, PropInfo));
  282. end;
  283. end;
  284. finally
  285. FreeMem(PropList);
  286. end;
  287. // 使用流来传递自定义的属性
  288. Stream := nil;
  289. Reader := nil;
  290. Writer := nil;
  291. try
  292. Stream := TMemoryStream.Create;
  293. Writer := TWriter.Create(Stream, 4096);
  294. TPersistentHack(Source).DefineProperties(Writer);
  295. Writer.FlushBuffer;
  296. Stream.Position := 0;
  297. Reader := TReader.Create(Stream, 4096);
  298. TPersistentHack(Self).DefineProperties(Reader);
  299. finally
  300. FreeAndNil(Reader);
  301. FreeAndNil(Writer);
  302. FreeAndNil(Stream);
  303. end;
  304. end
  305. else
  306. inherited Assign(Source);
  307. end;
  308. { TCnOptionItem }
  309. constructor TCnOptionItem.Create(AOwner: TCnOptionGroup);
  310. begin
  311. inherited;
  312. FValue := Null;
  313. FList := TStringList.Create;
  314. end;
  315. destructor TCnOptionItem.Destroy;
  316. begin
  317. ClearValue;
  318. FList.Free;
  319. inherited;
  320. end;
  321. procedure TCnOptionItem.ApplyOption;
  322. var
  323. SrcObj, DstObj: TPersistent;
  324. begin
  325. if (PropKind = tkClass) and not VarIsNull(Value) then
  326. begin
  327. {$IFDEF WIN64}
  328. SrcObj := TPersistent(Integer(Value));
  329. DstObj := TPersistent(Integer(PropValue));
  330. {$ELSE}
  331. Integer(SrcObj) := Value;
  332. Integer(DstObj) := PropValue;
  333. {$ENDIF}
  334. if (SrcObj is TPersistent) and (DstObj is TPersistent) and (SrcObj <> DstObj) then
  335. DstObj.Assign(SrcObj)
  336. else
  337. PropValue := Value;
  338. end
  339. else
  340. begin
  341. PropValue := Value;
  342. end;
  343. end;
  344. procedure TCnOptionItem.ClearValue;
  345. var
  346. Obj: TObject;
  347. begin
  348. if (PropKind = tkClass) and not VarIsNull(Value) and (Value <> PropValue) then
  349. begin
  350. {$IFDEF WIN64}
  351. Obj := TObject(Integer(Value));
  352. {$ELSE}
  353. Integer(Obj) := Value;
  354. {$ENDIF}
  355. Obj.Free;
  356. end;
  357. Value := Null;
  358. end;
  359. procedure TCnOptionItem.DefaultOption;
  360. var
  361. SrcObj, DstObj: TPersistent;
  362. begin
  363. if (PropKind = tkClass) and not VarIsNull(DefaultValue) then
  364. begin
  365. {$IFDEF WIN64}
  366. SrcObj := TPersistent(Integer(DefaultValue));
  367. DstObj := TPersistent(Integer(PropValue));
  368. {$ELSE}
  369. Integer(SrcObj) := DefaultValue;
  370. Integer(DstObj) := PropValue;
  371. {$ENDIF}
  372. if (SrcObj is TPersistent) and (DstObj is TPersistent) and (SrcObj <> DstObj) then
  373. DstObj.Assign(SrcObj)
  374. else
  375. PropValue := DefaultValue;
  376. end
  377. else
  378. begin
  379. PropValue := DefaultValue;
  380. end;
  381. ResetOption;
  382. end;
  383. procedure TCnOptionItem.ResetOption;
  384. var
  385. SrcObj, DstObj: TPersistent;
  386. begin
  387. ClearValue;
  388. if PropKind = tkClass then
  389. begin
  390. {$IFDEF WIN64}
  391. SrcObj := TPersistent(Integer(PropValue));
  392. {$ELSE}
  393. Integer(SrcObj) := PropValue;
  394. {$ENDIF}
  395. if SrcObj is TFont then
  396. DstObj := TFont.Create
  397. else if SrcObj is TStrings then
  398. DstObj := TStringList.Create
  399. else
  400. DstObj := nil;
  401. if DstObj <> nil then
  402. begin
  403. DstObj.Assign(SrcObj);
  404. Value := Integer(DstObj);
  405. end
  406. else
  407. Value := PropValue;
  408. end
  409. else
  410. begin
  411. Value := PropValue;
  412. end;
  413. end;
  414. function TCnOptionItem.GetDefaultValue: Variant;
  415. begin
  416. if not VarIsNull(FDefaultValue) then
  417. Result := FDefaultValue
  418. else if PropKind in [tkInteger, tkChar, tkEnumeration, tkSet, tkWChar] then
  419. Result := PropInfo^.Default
  420. else
  421. Result := PropValue;
  422. end;
  423. procedure TCnOptionItem.SetList(Value: TStrings);
  424. begin
  425. FList.Assign(Value);
  426. end;
  427. function TCnOptionItem.GetMaxValue: Variant;
  428. begin
  429. if not VarIsNull(FMaxValue) then
  430. Result := FMaxValue
  431. else
  432. begin
  433. if PropKind in [tkInteger, tkChar, tkEnumeration, tkWChar] then
  434. Result := GetTypeData(PropInfo^.PropType^)^.MaxValue
  435. else
  436. Result := Null;
  437. end;
  438. end;
  439. function TCnOptionItem.GetMinValue: Variant;
  440. begin
  441. if not VarIsNull(FMinValue) then
  442. Result := FMinValue
  443. else
  444. begin
  445. if PropKind in [tkInteger, tkChar, tkEnumeration, tkWChar] then
  446. Result := GetTypeData(PropInfo^.PropType^)^.MinValue
  447. else
  448. Result := Null;
  449. end;
  450. end;
  451. function TCnOptionItem.GetPropInfo: PPropInfo;
  452. begin
  453. Result := TypInfo.GetPropInfo(Instance, PropName);
  454. if Result = nil then
  455. raise EInvalidPropItem.CreateFmt('Invalid property define: %s.%s',
  456. [Instance.ClassName, PropName]);
  457. end;
  458. function TCnOptionItem.GetPropKind: TTypeKind;
  459. begin
  460. Result := PropInfo^.PropType^^.Kind;
  461. end;
  462. function TCnOptionItem.GetPropValue: Variant;
  463. begin
  464. Result := TypInfo.GetPropValue(Instance, PropName, False);
  465. end;
  466. procedure TCnOptionItem.SetPropValue(const Value: Variant);
  467. var
  468. Obj: TObject;
  469. begin
  470. case PropInfo.PropType^^.Kind of
  471. tkInteger, tkChar, tkWChar, tkEnumeration, tkSet, tkFloat,
  472. tkString, tkLString, tkWString, tkVariant, tkInt64{$IFDEF UNICODE_STRING}, tkUString{$ENDIF}:
  473. begin
  474. if IsBooleanType(PropInfo.PropType^) then
  475. begin
  476. if Value <> 0 then
  477. TypInfo.SetEnumProp(Instance, PropInfo, BooleanIdents[True])
  478. else
  479. TypInfo.SetEnumProp(Instance, PropInfo, BooleanIdents[False]);
  480. end
  481. else if IsBoolType(PropInfo.PropType^) then
  482. begin
  483. if Value <> 0 then
  484. TypInfo.SetOrdProp(Instance, PropName, -1)
  485. else
  486. TypInfo.SetOrdProp(Instance, PropName, 0)
  487. end
  488. else
  489. TypInfo.SetPropValue(Instance, PropName, Value);
  490. end;
  491. tkClass:
  492. begin
  493. {$IFDEF WIN64}
  494. Obj := TObject(Integer(Value));
  495. {$ELSE}
  496. Integer(Obj) := Value;
  497. {$ENDIF}
  498. SetObjectProp(Instance, PropInfo, Obj);
  499. end;
  500. else
  501. ;
  502. end;
  503. end;
  504. procedure TCnOptionItem.SetDefaultValue(const Value: Variant);
  505. begin
  506. FDefaultValue := Null;
  507. if not VarIsNull(Value) then
  508. case PropInfo.PropType^^.Kind of
  509. tkInteger, tkEnumeration, tkSet, tkInt64:
  510. FDefaultValue := VarToIntVar(Value);
  511. tkFloat:
  512. FDefaultValue := VarToFloatVar(Value);
  513. tkChar, tkWChar, tkString, tkLString, tkWString{$IFDEF UNICODE_STRING}, tkUString{$ENDIF}:
  514. FDefaultValue := VarToStr(Value);
  515. else
  516. FDefaultValue := Value;
  517. end;
  518. end;
  519. procedure TCnOptionItem.SetMaxValue(const Value: Variant);
  520. begin
  521. FMaxValue := VarToIntVar(Value);
  522. end;
  523. procedure TCnOptionItem.SetMinValue(const Value: Variant);
  524. begin
  525. FMinValue := VarToIntVar(Value);
  526. end;
  527. { TCnOptionGroup }
  528. constructor TCnOptionGroup.Create(AOwner: TCnOptionGroup);
  529. begin
  530. inherited;
  531. FList := TObjectList.Create;
  532. end;
  533. destructor TCnOptionGroup.Destroy;
  534. begin
  535. FList.Free;
  536. inherited;
  537. end;
  538. function TCnOptionGroup.Add(Item: TCnBaseOption): Integer;
  539. begin
  540. if Item.FOwner <> nil then
  541. Item.FOwner.FList.Extract(Item);
  542. Result := FList.Add(Item);
  543. Item.FOwner := Self;
  544. end;
  545. function TCnOptionGroup.AddGroup(const AText: string): TCnOptionGroup;
  546. begin
  547. Result := TCnOptionGroup.Create(Self);
  548. Result.FText := AText;
  549. Add(Result);
  550. end;
  551. function TCnOptionGroup.AddCustom(const AText: string;
  552. OnClick: TNotifyEvent; const ACaption: string): TCnOptionCustom;
  553. begin
  554. Result := TCnOptionCustom.Create(Self);
  555. Result.FText := AText;
  556. Result.FCaption := ACaption;
  557. Result.FOnClick := OnClick;
  558. Add(Result);
  559. end;
  560. function TCnOptionGroup.AddItem(AInstance: TObject; const APropName: string;
  561. const AText: string = ''; const AList: string = ''): TCnOptionItem;
  562. begin
  563. Result := AddItem(AInstance, APropName, AText, AList, Null, Null, Null);
  564. end;
  565. function TCnOptionGroup.AddItem(AInstance: TObject; const APropName: string;
  566. const AText: string; const AList: string; ADefaultValue, AMinValue,
  567. AMaxValue: Variant): TCnOptionItem;
  568. begin
  569. Result := TCnOptionItem.Create(Self);
  570. Result.Instance := AInstance;
  571. Result.PropName := APropName;
  572. if AText <> '' then
  573. Result.Text := AText
  574. else
  575. Result.Text := APropName;
  576. Result.List.Text := AList;
  577. Result.DefaultValue := ADefaultValue;
  578. Result.MinValue := AMinValue;
  579. Result.MaxValue := AMaxValue;
  580. Add(Result);
  581. end;
  582. procedure TCnOptionGroup.Assign(Source: TPersistent);
  583. var
  584. i: Integer;
  585. Item: TCnBaseOption;
  586. begin
  587. inherited Assign(Source);
  588. if Source is TCnOptionGroup then
  589. begin
  590. Clear;
  591. for i := 0 to TCnOptionGroup(Source).Count - 1 do
  592. begin
  593. Item := TCnOptionClass(TCnOptionGroup(Source).Items[i].ClassType).Create(Self);
  594. Item.Assign(TCnOptionGroup(Source).Items[i]);
  595. Add(Item);
  596. end;
  597. end;
  598. end;
  599. procedure TCnOptionGroup.Clear;
  600. begin
  601. FList.Clear;
  602. end;
  603. procedure TCnOptionGroup.Delete(Index: Integer);
  604. begin
  605. FList.Delete(Index);
  606. end;
  607. function TCnOptionGroup.IndexOf(Item: TCnBaseOption): Integer;
  608. begin
  609. Result := FList.IndexOf(Item);
  610. end;
  611. procedure TCnOptionGroup.Insert(Index: Integer; Item: TCnBaseOption);
  612. begin
  613. FList.Insert(Index, Item);
  614. end;
  615. procedure TCnOptionGroup.Move(CurIndex, NewIndex: Integer);
  616. begin
  617. FList.Move(CurIndex, NewIndex);
  618. end;
  619. function TCnOptionGroup.GetCount: Integer;
  620. begin
  621. Result := FList.Count;
  622. end;
  623. function TCnOptionGroup.GetItems(Index: Integer): TCnBaseOption;
  624. begin
  625. Result := TCnOptionItem(FList[Index]);
  626. end;
  627. procedure TCnOptionGroup.SetItems(Index: Integer; Value: TCnBaseOption);
  628. begin
  629. TCnBaseOption(FList[Index]).Assign(Value);
  630. end;
  631. end.