compon.inc 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796
  1. {%MainUnit classes.pp}
  2. {
  3. This file is part of the Free Component Library (FCL)
  4. Copyright (c) 1999-2000 by the Free Pascal development team
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {****************************************************************************}
  12. {* TComponentEnumerator *}
  13. {****************************************************************************}
  14. constructor TComponentEnumerator.Create(AComponent: TComponent);
  15. begin
  16. inherited Create;
  17. FComponent := AComponent;
  18. FPosition := -1;
  19. end;
  20. function TComponentEnumerator.GetCurrent: TComponent;
  21. begin
  22. Result := FComponent.Components[FPosition];
  23. end;
  24. function TComponentEnumerator.MoveNext: Boolean;
  25. begin
  26. Inc(FPosition);
  27. Result := FPosition < FComponent.ComponentCount;
  28. end;
  29. {****************************************************************************}
  30. {* TComponent *}
  31. {****************************************************************************}
  32. function TComponent.GetComObject: IUnknown;
  33. begin
  34. { Check if VCLComObject is not assigned - we need to create it by }
  35. { the call to CreateVCLComObject routine. If in the end we are still }
  36. { have no valid VCLComObject pointer we need to raise an exception }
  37. if not Assigned(VCLComObject) then
  38. begin
  39. if Assigned(CreateVCLComObjectProc) then
  40. CreateVCLComObjectProc(Self);
  41. if not Assigned(VCLComObject) then
  42. raise EComponentError.CreateFmt(SNoComSupport,[Name]);
  43. end;
  44. { VCLComObject is IVCComObject but we need to return IUnknown }
  45. IVCLComObject(VCLComObject).QueryInterface(IUnknown, Result);
  46. end;
  47. Function TComponent.GetComponent(AIndex: Integer): TComponent;
  48. begin
  49. If not assigned(FComponents) then
  50. Result:=Nil
  51. else
  52. Result:=TComponent(FComponents.Items[Aindex]);
  53. end;
  54. function TComponent.IsImplementorOf (const Intf:IInterface):boolean;
  55. var ref : IInterfaceComponentReference;
  56. begin
  57. result:=assigned(intf) and supports(intf,IInterfaceComponentReference,ref);
  58. if result then
  59. result:=ref.getcomponent=self;
  60. end;
  61. procedure TComponent.ReferenceInterface(const intf:IInterface;op:TOperation);
  62. var ref : IInterfaceComponentReference;
  63. comp : TComponent;
  64. begin
  65. if assigned(intf) and supports(intf,IInterfaceComponentReference,ref) then
  66. begin
  67. comp:=ref.getcomponent;
  68. if op = opInsert then
  69. comp.FreeNotification(Self)
  70. else
  71. comp.RemoveFreeNotification(Self);
  72. end;
  73. end;
  74. Function TComponent.GetComponentCount: Integer;
  75. begin
  76. If not assigned(FComponents) then
  77. result:=0
  78. else
  79. Result:=FComponents.Count;
  80. end;
  81. Function TComponent.GetComponentIndex: Integer;
  82. begin
  83. If Assigned(FOwner) and Assigned(FOwner.FComponents) then
  84. Result:=FOWner.FComponents.IndexOf(Self)
  85. else
  86. Result:=-1;
  87. end;
  88. function TComponent.GetObservers: TObservers;
  89. begin
  90. if FDObservers=Nil then
  91. begin
  92. FDObservers:=TObservers.Create;
  93. FDObservers.OnCanObserve:=@CanObserve;
  94. FDObservers.OnObserverAdded:=@ObserverAdded;
  95. end;
  96. Result:=FDObservers;
  97. end;
  98. function TComponent.CanObserve(const ID: Integer): Boolean;
  99. begin
  100. Result:=False;
  101. end;
  102. procedure TComponent.ObserverAdded(const ID: Integer; const Observer: IObserver);
  103. begin
  104. // Do nothing, can be used in descendants
  105. end;
  106. Procedure TComponent.Insert(AComponent: TComponent);
  107. begin
  108. If not assigned(FComponents) then
  109. FComponents:=TFpList.Create;
  110. FComponents.Add(AComponent);
  111. AComponent.FOwner:=Self;
  112. end;
  113. Procedure TComponent.ReadLeft(Reader: TReader);
  114. begin
  115. LongRec(FDesignInfo).Lo:=Reader.ReadInteger;
  116. end;
  117. Procedure TComponent.ReadTop(Reader: TReader);
  118. begin
  119. LongRec(FDesignInfo).Hi:=Reader.ReadInteger;
  120. end;
  121. Procedure TComponent.Remove(AComponent: TComponent);
  122. begin
  123. AComponent.FOwner:=Nil;
  124. If assigned(FCOmponents) then
  125. begin
  126. FComponents.Remove(AComponent);
  127. IF FComponents.Count=0 then
  128. begin
  129. FComponents.Free;
  130. FComponents:=Nil;
  131. end;
  132. end;
  133. end;
  134. Procedure TComponent.RemoveNotification(AComponent: TComponent);
  135. begin
  136. if FFreeNotifies<>nil then
  137. begin
  138. FFreeNotifies.Remove(AComponent);
  139. if FFreeNotifies.Count=0 then
  140. begin
  141. FFreeNotifies.Free;
  142. FFreeNotifies:=nil;
  143. Exclude(FComponentState,csFreeNotification);
  144. end;
  145. end;
  146. end;
  147. Procedure TComponent.SetComponentIndex(Value: Integer);
  148. Var Temp,Count : longint;
  149. begin
  150. If Not assigned(Fowner) then exit;
  151. Temp:=getcomponentindex;
  152. If temp<0 then exit;
  153. If value<0 then value:=0;
  154. Count:=Fowner.FComponents.Count;
  155. If Value>=Count then value:=count-1;
  156. If Value<>Temp then
  157. begin
  158. FOWner.FComponents.Delete(Temp);
  159. FOwner.FComponents.Insert(Value,Self);
  160. end;
  161. end;
  162. Procedure TComponent.SetReference(Enable: Boolean);
  163. var
  164. Field: ^TComponent;
  165. begin
  166. if Assigned(Owner) then
  167. begin
  168. Field := Owner.FieldAddress(Name);
  169. if Assigned(Field) then
  170. if Enable then
  171. Field^ := Self
  172. else
  173. Field^ := nil;
  174. end;
  175. end;
  176. Procedure TComponent.WriteLeft(Writer: TWriter);
  177. begin
  178. Writer.WriteInteger(LongRec(FDesignInfo).Lo);
  179. end;
  180. Procedure TComponent.WriteTop(Writer: TWriter);
  181. begin
  182. Writer.WriteInteger(LongRec(FDesignInfo).Hi);
  183. end;
  184. Procedure TComponent.ChangeName(const NewName: TComponentName);
  185. begin
  186. FName:=NewName;
  187. end;
  188. Procedure TComponent.DefineProperties(Filer: TFiler);
  189. Var Ancestor : TComponent;
  190. Temp : longint;
  191. begin
  192. Temp:=0;
  193. Ancestor:=TComponent(Filer.Ancestor);
  194. If Assigned(Ancestor) then Temp:=Ancestor.FDesignInfo;
  195. Filer.Defineproperty('Left',@readleft,@writeleft,
  196. (longrec(FDesignInfo).Lo<>Longrec(temp).Lo));
  197. Filer.Defineproperty('Top',@readtop,@writetop,
  198. (longrec(FDesignInfo).Hi<>Longrec(temp).Hi));
  199. end;
  200. Procedure TComponent.GetChildren(Proc: TGetChildProc; Root: TComponent);
  201. begin
  202. // Does nothing.
  203. end;
  204. Function TComponent.GetChildOwner: TComponent;
  205. begin
  206. Result:=Nil;
  207. end;
  208. Function TComponent.GetChildParent: TComponent;
  209. begin
  210. Result:=Self;
  211. end;
  212. Function TComponent.GetEnumerator: TComponentEnumerator;
  213. begin
  214. Result:=TComponentEnumerator.Create(Self);
  215. end;
  216. Function TComponent.GetNamePath: string;
  217. begin
  218. Result:=FName;
  219. end;
  220. Function TComponent.GetOwner: TPersistent;
  221. begin
  222. Result:=FOwner;
  223. end;
  224. Procedure TComponent.Loaded;
  225. begin
  226. Exclude(FComponentState,csLoading);
  227. end;
  228. Procedure TComponent.Loading;
  229. begin
  230. Include(FComponentState,csLoading);
  231. end;
  232. Procedure TComponent.Notification(AComponent: TComponent;
  233. Operation: TOperation);
  234. Var
  235. C : Longint;
  236. begin
  237. If (Operation=opRemove) then
  238. RemoveFreeNotification(AComponent);
  239. If Not assigned(FComponents) then
  240. exit;
  241. C:=FComponents.Count-1;
  242. While (C>=0) do
  243. begin
  244. TComponent(FComponents.Items[C]).Notification(AComponent,Operation);
  245. Dec(C);
  246. if C>=FComponents.Count then
  247. C:=FComponents.Count-1;
  248. end;
  249. end;
  250. procedure TComponent.PaletteCreated;
  251. begin
  252. end;
  253. Procedure TComponent.ReadState(Reader: TReader);
  254. begin
  255. Reader.ReadData(Self);
  256. end;
  257. procedure TComponent.RemoveFreeNotifications;
  258. var
  259. I: Integer;
  260. C: TComponent;
  261. begin
  262. If Assigned(FFreeNotifies) then
  263. begin
  264. I := FFreeNotifies.Count - 1;
  265. while I >= 0 do
  266. begin
  267. C := TComponent(FFreeNotifies.Items[I]);
  268. // Delete, so one component is not notified twice, if it is owned.
  269. FFreeNotifies.Delete(I);
  270. C.Notification (Self, opRemove);
  271. If FFreeNotifies = nil then
  272. I := 0
  273. else
  274. if I > FFreeNotifies.Count then
  275. I := FFreeNotifies.Count;
  276. Dec(I);
  277. end;
  278. FreeAndNil(FFreeNotifies);
  279. end;
  280. end;
  281. Procedure TComponent.SetAncestor(Value: Boolean);
  282. Var Runner : Longint;
  283. begin
  284. If Value then
  285. Include(FComponentState,csAncestor)
  286. else
  287. Exclude(FCOmponentState,csAncestor);
  288. if Assigned(FComponents) then
  289. For Runner:=0 To FComponents.Count-1 do
  290. TComponent(FComponents.Items[Runner]).SetAncestor(Value);
  291. end;
  292. Procedure TComponent.SetDesigning(Value: Boolean; SetChildren : Boolean = True);
  293. Var Runner : Longint;
  294. begin
  295. If Value then
  296. Include(FComponentState,csDesigning)
  297. else
  298. Exclude(FComponentState,csDesigning);
  299. if Assigned(FComponents) and SetChildren then
  300. For Runner:=0 To FComponents.Count - 1 do
  301. TComponent(FComponents.items[Runner]).SetDesigning(Value);
  302. end;
  303. Procedure TComponent.SetDesignInstance(Value: Boolean);
  304. begin
  305. If Value then
  306. Include(FComponentState,csDesignInstance)
  307. else
  308. Exclude(FComponentState,csDesignInstance);
  309. end;
  310. Procedure TComponent.SetInline(Value: Boolean);
  311. begin
  312. If Value then
  313. Include(FComponentState,csInline)
  314. else
  315. Exclude(FComponentState,csInline);
  316. end;
  317. Procedure TComponent.SetName(const NewName: TComponentName);
  318. begin
  319. If FName=NewName then exit;
  320. If (NewName<>'') and not IsValidIdent(NewName) then
  321. Raise EComponentError.CreateFmt(SInvalidName,[NewName]);
  322. If Assigned(FOwner) Then
  323. FOwner.ValidateRename(Self,FName,NewName)
  324. else
  325. ValidateRename(Nil,FName,NewName);
  326. SetReference(False);
  327. ChangeName(NewName);
  328. Setreference(True);
  329. end;
  330. Procedure TComponent.SetChildOrder(Child: TComponent; Order: Integer);
  331. begin
  332. // does nothing
  333. end;
  334. Procedure TComponent.SetParentComponent(Value: TComponent);
  335. begin
  336. // Does nothing
  337. end;
  338. Procedure TComponent.Updating;
  339. begin
  340. Include (FComponentState,csUpdating);
  341. end;
  342. Procedure TComponent.Updated;
  343. begin
  344. Exclude(FComponentState,csUpdating);
  345. end;
  346. class Procedure TComponent.UpdateRegistry(Register: Boolean; const ClassID, ProgID: string);
  347. begin
  348. // For compatibility only.
  349. end;
  350. Procedure TComponent.ValidateRename(AComponent: TComponent;
  351. const CurName, NewName: string);
  352. begin
  353. //!! This contradicts the Delphi manual.
  354. If (AComponent<>Nil) and (CompareText(CurName,NewName)<>0) and (AComponent.Owner = Self) and
  355. (FindComponent(NewName)<>Nil) then
  356. raise EComponentError.Createfmt(SDuplicateName,[newname]);
  357. If (csDesigning in FComponentState) and (FOwner<>Nil) then
  358. FOwner.ValidateRename(AComponent,Curname,Newname);
  359. end;
  360. Procedure TComponent.ValidateContainer(AComponent: TComponent);
  361. begin
  362. if Assigned(aComponent) then
  363. AComponent.ValidateInsert(Self);
  364. end;
  365. Procedure TComponent.ValidateInsert(AComponent: TComponent);
  366. begin
  367. // Does nothing.
  368. end;
  369. Procedure TComponent.WriteState(Writer: TWriter);
  370. begin
  371. Writer.WriteComponentData(Self);
  372. end;
  373. Constructor TComponent.Create(AOwner: TComponent);
  374. begin
  375. FComponentStyle:=[csInheritable];
  376. If Assigned(AOwner) then AOwner.InsertComponent(Self);
  377. end;
  378. Destructor TComponent.Destroy;
  379. begin
  380. Destroying;
  381. FreeAndNil(FObservers);
  382. RemoveFreeNotifications;
  383. DestroyComponents;
  384. If FOwner<>Nil Then FOwner.RemoveComponent(Self);
  385. inherited destroy;
  386. end;
  387. function TComponent.ToString : RTLString;
  388. begin
  389. Case ToStringNameMode of
  390. snmName :
  391. Result:=Name;
  392. snmClassName :
  393. Result:=Inherited;
  394. snmNameClassName :
  395. begin
  396. Result:=Inherited;
  397. if (Name<>'') then
  398. Result:=Name+' ('+Result+')';
  399. end;
  400. end;
  401. end;
  402. Procedure TComponent.BeforeDestruction;
  403. begin
  404. if not(csDestroying in FComponentstate) then
  405. Destroying;
  406. end;
  407. Procedure TComponent.DestroyComponents;
  408. Var acomponent: TComponent;
  409. begin
  410. While assigned(FComponents) do
  411. begin
  412. aComponent:=TComponent(FComponents.Last);
  413. Remove(aComponent);
  414. Acomponent.Destroy;
  415. end;
  416. end;
  417. Procedure TComponent.Destroying;
  418. Var Runner : longint;
  419. begin
  420. If csDestroying in FComponentstate Then Exit;
  421. include (FComponentState,csDestroying);
  422. If Assigned(FComponents) then
  423. for Runner:=0 to FComponents.Count-1 do
  424. TComponent(FComponents.Items[Runner]).Destroying;
  425. end;
  426. function TComponent.ExecuteAction(Action: TBasicAction): Boolean;
  427. begin
  428. if Action.HandlesTarget(Self) then
  429. begin
  430. Action.ExecuteTarget(Self);
  431. Result := True;
  432. end
  433. else
  434. Result := False;
  435. end;
  436. Function TComponent.FindComponent(const AName: string): TComponent;
  437. Var I : longint;
  438. C : TComponent;
  439. begin
  440. Result:=Nil;
  441. If (AName='') or Not assigned(FComponents) then exit;
  442. For i:=0 to FComponents.Count-1 do
  443. Begin
  444. c:=TComponent(FComponents[I]);
  445. If (CompareText(C.Name,AName)=0) then
  446. Exit(C);
  447. End;
  448. end;
  449. Procedure TComponent.FreeNotification(AComponent: TComponent);
  450. begin
  451. If (Owner<>Nil) and (AComponent=Owner) then exit;
  452. If not (Assigned(FFreeNotifies)) then
  453. FFreeNotifies:=TFpList.Create;
  454. If FFreeNotifies.IndexOf(AComponent)=-1 then
  455. begin
  456. FFreeNotifies.Add(AComponent);
  457. AComponent.FreeNotification (self);
  458. end;
  459. end;
  460. procedure TComponent.RemoveFreeNotification(AComponent: TComponent);
  461. begin
  462. RemoveNotification(AComponent);
  463. AComponent.RemoveNotification (self);
  464. end;
  465. Procedure TComponent.FreeOnRelease;
  466. begin
  467. if Assigned(VCLComObject) then
  468. IVCLComObject(VCLComObject).FreeOnRelease;
  469. end;
  470. Function TComponent.GetParentComponent: TComponent;
  471. begin
  472. Result:=Nil;
  473. end;
  474. Function TComponent.HasParent: Boolean;
  475. begin
  476. Result:=False;
  477. end;
  478. Procedure TComponent.InsertComponent(AComponent: TComponent);
  479. begin
  480. AComponent.ValidateContainer(Self);
  481. ValidateRename(AComponent,'',AComponent.FName);
  482. If AComponent.FOwner<>Nil then
  483. AComponent.FOwner.Remove(AComponent);
  484. Insert(AComponent);
  485. AComponent.SetReference(True);
  486. If csDesigning in FComponentState then
  487. AComponent.SetDesigning(true);
  488. Notification(AComponent,opInsert);
  489. end;
  490. Procedure TComponent.RemoveComponent(AComponent: TComponent);
  491. begin
  492. Notification(AComponent,opRemove);
  493. AComponent.SetReference(False);
  494. Remove(AComponent);
  495. Acomponent.Setdesigning(False);
  496. ValidateRename(AComponent,AComponent.FName,'');
  497. end;
  498. Function TComponent.SafeCallException(ExceptObject: TObject;
  499. ExceptAddr: CodePointer): HResult;
  500. begin
  501. if Assigned(VCLComObject) then
  502. Result := IVCLComObject(VCLComObject).SafeCallException(ExceptObject, ExceptAddr)
  503. else
  504. Result := inherited SafeCallException(ExceptObject, ExceptAddr);
  505. end;
  506. procedure TComponent.SetSubComponent(ASubComponent: Boolean);
  507. begin
  508. if ASubComponent then
  509. Include(FComponentStyle, csSubComponent)
  510. else
  511. Exclude(FComponentStyle, csSubComponent);
  512. end;
  513. function TComponent.UpdateAction(Action: TBasicAction): Boolean;
  514. begin
  515. if Action.HandlesTarget(Self) then
  516. begin
  517. Action.UpdateTarget(Self);
  518. Result := True;
  519. end
  520. else
  521. Result := False;
  522. end;
  523. function TComponent.QueryInterface({$IFDEF FPC_HAS_CONSTREF}constref{$ELSE}const{$ENDIF} IID: TGUID; out Obj): HResult;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  524. begin
  525. if Assigned(VCLComObject) then
  526. Result := IVCLComObject(VCLComObject).QueryInterface(IID, Obj)
  527. else
  528. if GetInterface(IID, Obj) then
  529. Result := S_OK
  530. else
  531. Result := E_NOINTERFACE;
  532. end;
  533. function TComponent._AddRef: Longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  534. begin
  535. if Assigned(VCLComObject) then
  536. Result := IVCLComObject(VCLComObject)._AddRef
  537. else
  538. Result := -1;
  539. end;
  540. function TComponent._Release: Longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  541. begin
  542. if Assigned(VCLComObject) then
  543. Result := IVCLComObject(VCLComObject)._Release
  544. else
  545. Result := -1;
  546. end;
  547. function TComponent.iicrGetComponent: TComponent;
  548. begin
  549. result:=self;
  550. end;
  551. function TComponent.GetTypeInfoCount(out Count: Integer): HResult; stdcall;
  552. begin
  553. if Assigned(VCLComObject) then
  554. Result := IVCLComObject(VCLComObject).GetTypeInfoCount(Count)
  555. else
  556. Result := E_NOTIMPL;
  557. end;
  558. function TComponent.GetTypeInfo(Index, LocaleID: Integer; out TypeInfo): HResult; stdcall;
  559. begin
  560. if Assigned(VCLComObject) then
  561. Result := IVCLComObject(VCLComObject).GetTypeInfo(Index, LocaleID, TypeInfo)
  562. else
  563. Result := E_NOTIMPL;
  564. end;
  565. function TComponent.GetIDsOfNames(const IID: TGUID; Names: Pointer; NameCount,
  566. LocaleID: Integer; DispIDs: Pointer): HResult; stdcall;
  567. begin
  568. if Assigned(VCLComObject) then
  569. Result := IVCLComObject(VCLComObject).GetIDsOfNames(IID, Names, NameCount, LocaleID, DispIDs)
  570. else
  571. Result := E_NOTIMPL;
  572. end;
  573. function TComponent.Invoke(DispID: Integer; const IID: TGUID;
  574. LocaleID: Integer; Flags: Word; var Params; VarResult, ExcepInfo,
  575. ArgErr: Pointer): HResult; stdcall;
  576. begin
  577. if Assigned(VCLComObject) then
  578. Result := IVCLComObject(VCLComObject).Invoke(DispID, IID, LocaleID, Flags, Params,
  579. VarResult, ExcepInfo, ArgErr)
  580. else
  581. Result := E_NOTIMPL;
  582. end;
  583. { Delta stream support }
  584. procedure TComponent.GetDeltaStreams(aProc: TGetStreamProc);
  585. begin
  586. // To be implemented by descendants
  587. end;
  588. procedure TComponent.ReadDeltaStream(const S: TStream);
  589. begin
  590. S.ReadComponent(Self);
  591. end;
  592. procedure TComponent.ReadDeltaState;
  593. var
  594. Done : boolean;
  595. begin
  596. if (csDesigning in ComponentState) then
  597. exit;
  598. Done:=False;
  599. if Assigned(FOnGetDeltaStreams) then
  600. FOnGetDeltaStreams(Self,@ReadDeltaStream,Done);
  601. if not Done then
  602. GetDeltaStreams(@ReadDeltaStream);
  603. end;