compon.inc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765
  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. FDObservers:=TObservers.Create;
  92. Result:=FDObservers;
  93. end;
  94. Procedure TComponent.Insert(AComponent: TComponent);
  95. begin
  96. If not assigned(FComponents) then
  97. FComponents:=TFpList.Create;
  98. FComponents.Add(AComponent);
  99. AComponent.FOwner:=Self;
  100. end;
  101. Procedure TComponent.ReadLeft(Reader: TReader);
  102. begin
  103. LongRec(FDesignInfo).Lo:=Reader.ReadInteger;
  104. end;
  105. Procedure TComponent.ReadTop(Reader: TReader);
  106. begin
  107. LongRec(FDesignInfo).Hi:=Reader.ReadInteger;
  108. end;
  109. Procedure TComponent.Remove(AComponent: TComponent);
  110. begin
  111. AComponent.FOwner:=Nil;
  112. If assigned(FCOmponents) then
  113. begin
  114. FComponents.Remove(AComponent);
  115. IF FComponents.Count=0 then
  116. begin
  117. FComponents.Free;
  118. FComponents:=Nil;
  119. end;
  120. end;
  121. end;
  122. Procedure TComponent.RemoveNotification(AComponent: TComponent);
  123. begin
  124. if FFreeNotifies<>nil then
  125. begin
  126. FFreeNotifies.Remove(AComponent);
  127. if FFreeNotifies.Count=0 then
  128. begin
  129. FFreeNotifies.Free;
  130. FFreeNotifies:=nil;
  131. Exclude(FComponentState,csFreeNotification);
  132. end;
  133. end;
  134. end;
  135. Procedure TComponent.SetComponentIndex(Value: Integer);
  136. Var Temp,Count : longint;
  137. begin
  138. If Not assigned(Fowner) then exit;
  139. Temp:=getcomponentindex;
  140. If temp<0 then exit;
  141. If value<0 then value:=0;
  142. Count:=Fowner.FComponents.Count;
  143. If Value>=Count then value:=count-1;
  144. If Value<>Temp then
  145. begin
  146. FOWner.FComponents.Delete(Temp);
  147. FOwner.FComponents.Insert(Value,Self);
  148. end;
  149. end;
  150. Procedure TComponent.SetReference(Enable: Boolean);
  151. var
  152. Field: ^TComponent;
  153. begin
  154. if Assigned(Owner) then
  155. begin
  156. Field := Owner.FieldAddress(Name);
  157. if Assigned(Field) then
  158. if Enable then
  159. Field^ := Self
  160. else
  161. Field^ := nil;
  162. end;
  163. end;
  164. Procedure TComponent.WriteLeft(Writer: TWriter);
  165. begin
  166. Writer.WriteInteger(LongRec(FDesignInfo).Lo);
  167. end;
  168. Procedure TComponent.WriteTop(Writer: TWriter);
  169. begin
  170. Writer.WriteInteger(LongRec(FDesignInfo).Hi);
  171. end;
  172. Procedure TComponent.ChangeName(const NewName: TComponentName);
  173. begin
  174. FName:=NewName;
  175. end;
  176. Procedure TComponent.DefineProperties(Filer: TFiler);
  177. Var Ancestor : TComponent;
  178. Temp : longint;
  179. begin
  180. Temp:=0;
  181. Ancestor:=TComponent(Filer.Ancestor);
  182. If Assigned(Ancestor) then Temp:=Ancestor.FDesignInfo;
  183. Filer.Defineproperty('Left',@readleft,@writeleft,
  184. (longrec(FDesignInfo).Lo<>Longrec(temp).Lo));
  185. Filer.Defineproperty('Top',@readtop,@writetop,
  186. (longrec(FDesignInfo).Hi<>Longrec(temp).Hi));
  187. end;
  188. Procedure TComponent.GetChildren(Proc: TGetChildProc; Root: TComponent);
  189. begin
  190. // Does nothing.
  191. end;
  192. Function TComponent.GetChildOwner: TComponent;
  193. begin
  194. Result:=Nil;
  195. end;
  196. Function TComponent.GetChildParent: TComponent;
  197. begin
  198. Result:=Self;
  199. end;
  200. Function TComponent.GetEnumerator: TComponentEnumerator;
  201. begin
  202. Result:=TComponentEnumerator.Create(Self);
  203. end;
  204. Function TComponent.GetNamePath: string;
  205. begin
  206. Result:=FName;
  207. end;
  208. Function TComponent.GetOwner: TPersistent;
  209. begin
  210. Result:=FOwner;
  211. end;
  212. Procedure TComponent.Loaded;
  213. begin
  214. Exclude(FComponentState,csLoading);
  215. end;
  216. Procedure TComponent.Loading;
  217. begin
  218. Include(FComponentState,csLoading);
  219. end;
  220. Procedure TComponent.Notification(AComponent: TComponent;
  221. Operation: TOperation);
  222. Var
  223. C : Longint;
  224. begin
  225. If (Operation=opRemove) then
  226. RemoveFreeNotification(AComponent);
  227. If Not assigned(FComponents) then
  228. exit;
  229. C:=FComponents.Count-1;
  230. While (C>=0) do
  231. begin
  232. TComponent(FComponents.Items[C]).Notification(AComponent,Operation);
  233. Dec(C);
  234. if C>=FComponents.Count then
  235. C:=FComponents.Count-1;
  236. end;
  237. end;
  238. procedure TComponent.PaletteCreated;
  239. begin
  240. end;
  241. Procedure TComponent.ReadState(Reader: TReader);
  242. begin
  243. Reader.ReadData(Self);
  244. end;
  245. procedure TComponent.RemoveFreeNotifications;
  246. var
  247. I: Integer;
  248. C: TComponent;
  249. begin
  250. If Assigned(FFreeNotifies) then
  251. begin
  252. I := FFreeNotifies.Count - 1;
  253. while I >= 0 do
  254. begin
  255. C := TComponent(FFreeNotifies.Items[I]);
  256. // Delete, so one component is not notified twice, if it is owned.
  257. FFreeNotifies.Delete(I);
  258. C.Notification (Self, opRemove);
  259. If FFreeNotifies = nil then
  260. I := 0
  261. else
  262. if I > FFreeNotifies.Count then
  263. I := FFreeNotifies.Count;
  264. Dec(I);
  265. end;
  266. FreeAndNil(FFreeNotifies);
  267. end;
  268. end;
  269. Procedure TComponent.SetAncestor(Value: Boolean);
  270. Var Runner : Longint;
  271. begin
  272. If Value then
  273. Include(FComponentState,csAncestor)
  274. else
  275. Exclude(FCOmponentState,csAncestor);
  276. if Assigned(FComponents) then
  277. For Runner:=0 To FComponents.Count-1 do
  278. TComponent(FComponents.Items[Runner]).SetAncestor(Value);
  279. end;
  280. Procedure TComponent.SetDesigning(Value: Boolean; SetChildren : Boolean = True);
  281. Var Runner : Longint;
  282. begin
  283. If Value then
  284. Include(FComponentState,csDesigning)
  285. else
  286. Exclude(FComponentState,csDesigning);
  287. if Assigned(FComponents) and SetChildren then
  288. For Runner:=0 To FComponents.Count - 1 do
  289. TComponent(FComponents.items[Runner]).SetDesigning(Value);
  290. end;
  291. Procedure TComponent.SetDesignInstance(Value: Boolean);
  292. begin
  293. If Value then
  294. Include(FComponentState,csDesignInstance)
  295. else
  296. Exclude(FComponentState,csDesignInstance);
  297. end;
  298. Procedure TComponent.SetInline(Value: Boolean);
  299. begin
  300. If Value then
  301. Include(FComponentState,csInline)
  302. else
  303. Exclude(FComponentState,csInline);
  304. end;
  305. Procedure TComponent.SetName(const NewName: TComponentName);
  306. begin
  307. If FName=NewName then exit;
  308. If (NewName<>'') and not IsValidIdent(NewName) then
  309. Raise EComponentError.CreateFmt(SInvalidName,[NewName]);
  310. If Assigned(FOwner) Then
  311. FOwner.ValidateRename(Self,FName,NewName)
  312. else
  313. ValidateRename(Nil,FName,NewName);
  314. SetReference(False);
  315. ChangeName(NewName);
  316. Setreference(True);
  317. end;
  318. Procedure TComponent.SetChildOrder(Child: TComponent; Order: Integer);
  319. begin
  320. // does nothing
  321. end;
  322. Procedure TComponent.SetParentComponent(Value: TComponent);
  323. begin
  324. // Does nothing
  325. end;
  326. Procedure TComponent.Updating;
  327. begin
  328. Include (FComponentState,csUpdating);
  329. end;
  330. Procedure TComponent.Updated;
  331. begin
  332. Exclude(FComponentState,csUpdating);
  333. end;
  334. class Procedure TComponent.UpdateRegistry(Register: Boolean; const ClassID, ProgID: string);
  335. begin
  336. // For compatibility only.
  337. end;
  338. Procedure TComponent.ValidateRename(AComponent: TComponent;
  339. const CurName, NewName: string);
  340. begin
  341. //!! This contradicts the Delphi manual.
  342. If (AComponent<>Nil) and (CompareText(CurName,NewName)<>0) and (AComponent.Owner = Self) and
  343. (FindComponent(NewName)<>Nil) then
  344. raise EComponentError.Createfmt(SDuplicateName,[newname]);
  345. If (csDesigning in FComponentState) and (FOwner<>Nil) then
  346. FOwner.ValidateRename(AComponent,Curname,Newname);
  347. end;
  348. Procedure TComponent.ValidateContainer(AComponent: TComponent);
  349. begin
  350. AComponent.ValidateInsert(Self);
  351. end;
  352. Procedure TComponent.ValidateInsert(AComponent: TComponent);
  353. begin
  354. // Does nothing.
  355. end;
  356. Procedure TComponent.WriteState(Writer: TWriter);
  357. begin
  358. Writer.WriteComponentData(Self);
  359. end;
  360. Constructor TComponent.Create(AOwner: TComponent);
  361. begin
  362. FComponentStyle:=[csInheritable];
  363. If Assigned(AOwner) then AOwner.InsertComponent(Self);
  364. end;
  365. Destructor TComponent.Destroy;
  366. begin
  367. Destroying;
  368. FreeAndNil(FObservers);
  369. RemoveFreeNotifications;
  370. DestroyComponents;
  371. If FOwner<>Nil Then FOwner.RemoveComponent(Self);
  372. inherited destroy;
  373. end;
  374. Procedure TComponent.BeforeDestruction;
  375. begin
  376. if not(csDestroying in FComponentstate) then
  377. Destroying;
  378. end;
  379. Procedure TComponent.DestroyComponents;
  380. Var acomponent: TComponent;
  381. begin
  382. While assigned(FComponents) do
  383. begin
  384. aComponent:=TComponent(FComponents.Last);
  385. Remove(aComponent);
  386. Acomponent.Destroy;
  387. end;
  388. end;
  389. Procedure TComponent.Destroying;
  390. Var Runner : longint;
  391. begin
  392. If csDestroying in FComponentstate Then Exit;
  393. include (FComponentState,csDestroying);
  394. If Assigned(FComponents) then
  395. for Runner:=0 to FComponents.Count-1 do
  396. TComponent(FComponents.Items[Runner]).Destroying;
  397. end;
  398. function TComponent.ExecuteAction(Action: TBasicAction): Boolean;
  399. begin
  400. if Action.HandlesTarget(Self) then
  401. begin
  402. Action.ExecuteTarget(Self);
  403. Result := True;
  404. end
  405. else
  406. Result := False;
  407. end;
  408. Function TComponent.FindComponent(const AName: string): TComponent;
  409. Var I : longint;
  410. C : TComponent;
  411. begin
  412. Result:=Nil;
  413. If (AName='') or Not assigned(FComponents) then exit;
  414. For i:=0 to FComponents.Count-1 do
  415. Begin
  416. c:=TComponent(FComponents[I]);
  417. If (CompareText(C.Name,AName)=0) then
  418. Exit(C);
  419. End;
  420. end;
  421. Procedure TComponent.FreeNotification(AComponent: TComponent);
  422. begin
  423. If (Owner<>Nil) and (AComponent=Owner) then exit;
  424. If not (Assigned(FFreeNotifies)) then
  425. FFreeNotifies:=TFpList.Create;
  426. If FFreeNotifies.IndexOf(AComponent)=-1 then
  427. begin
  428. FFreeNotifies.Add(AComponent);
  429. AComponent.FreeNotification (self);
  430. end;
  431. end;
  432. procedure TComponent.RemoveFreeNotification(AComponent: TComponent);
  433. begin
  434. RemoveNotification(AComponent);
  435. AComponent.RemoveNotification (self);
  436. end;
  437. Procedure TComponent.FreeOnRelease;
  438. begin
  439. if Assigned(VCLComObject) then
  440. IVCLComObject(VCLComObject).FreeOnRelease;
  441. end;
  442. Function TComponent.GetParentComponent: TComponent;
  443. begin
  444. Result:=Nil;
  445. end;
  446. Function TComponent.HasParent: Boolean;
  447. begin
  448. Result:=False;
  449. end;
  450. Procedure TComponent.InsertComponent(AComponent: TComponent);
  451. begin
  452. AComponent.ValidateContainer(Self);
  453. ValidateRename(AComponent,'',AComponent.FName);
  454. If AComponent.FOwner<>Nil then
  455. AComponent.FOwner.Remove(AComponent);
  456. Insert(AComponent);
  457. AComponent.SetReference(True);
  458. If csDesigning in FComponentState then
  459. AComponent.SetDesigning(true);
  460. Notification(AComponent,opInsert);
  461. end;
  462. Procedure TComponent.RemoveComponent(AComponent: TComponent);
  463. begin
  464. Notification(AComponent,opRemove);
  465. AComponent.SetReference(False);
  466. Remove(AComponent);
  467. Acomponent.Setdesigning(False);
  468. ValidateRename(AComponent,AComponent.FName,'');
  469. end;
  470. Function TComponent.SafeCallException(ExceptObject: TObject;
  471. ExceptAddr: CodePointer): HResult;
  472. begin
  473. if Assigned(VCLComObject) then
  474. Result := IVCLComObject(VCLComObject).SafeCallException(ExceptObject, ExceptAddr)
  475. else
  476. Result := inherited SafeCallException(ExceptObject, ExceptAddr);
  477. end;
  478. procedure TComponent.SetSubComponent(ASubComponent: Boolean);
  479. begin
  480. if ASubComponent then
  481. Include(FComponentStyle, csSubComponent)
  482. else
  483. Exclude(FComponentStyle, csSubComponent);
  484. end;
  485. function TComponent.UpdateAction(Action: TBasicAction): Boolean;
  486. begin
  487. if Action.HandlesTarget(Self) then
  488. begin
  489. Action.UpdateTarget(Self);
  490. Result := True;
  491. end
  492. else
  493. Result := False;
  494. end;
  495. function TComponent.QueryInterface({$IFDEF FPC_HAS_CONSTREF}constref{$ELSE}const{$ENDIF} IID: TGUID; out Obj): HResult;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  496. begin
  497. if Assigned(VCLComObject) then
  498. Result := IVCLComObject(VCLComObject).QueryInterface(IID, Obj)
  499. else
  500. if GetInterface(IID, Obj) then
  501. Result := S_OK
  502. else
  503. Result := E_NOINTERFACE;
  504. end;
  505. function TComponent._AddRef: Longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  506. begin
  507. if Assigned(VCLComObject) then
  508. Result := IVCLComObject(VCLComObject)._AddRef
  509. else
  510. Result := -1;
  511. end;
  512. function TComponent._Release: Longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  513. begin
  514. if Assigned(VCLComObject) then
  515. Result := IVCLComObject(VCLComObject)._Release
  516. else
  517. Result := -1;
  518. end;
  519. function TComponent.iicrGetComponent: TComponent;
  520. begin
  521. result:=self;
  522. end;
  523. function TComponent.GetTypeInfoCount(out Count: Integer): HResult; stdcall;
  524. begin
  525. if Assigned(VCLComObject) then
  526. Result := IVCLComObject(VCLComObject).GetTypeInfoCount(Count)
  527. else
  528. Result := E_NOTIMPL;
  529. end;
  530. function TComponent.GetTypeInfo(Index, LocaleID: Integer; out TypeInfo): HResult; stdcall;
  531. begin
  532. if Assigned(VCLComObject) then
  533. Result := IVCLComObject(VCLComObject).GetTypeInfo(Index, LocaleID, TypeInfo)
  534. else
  535. Result := E_NOTIMPL;
  536. end;
  537. function TComponent.GetIDsOfNames(const IID: TGUID; Names: Pointer; NameCount,
  538. LocaleID: Integer; DispIDs: Pointer): HResult; stdcall;
  539. begin
  540. if Assigned(VCLComObject) then
  541. Result := IVCLComObject(VCLComObject).GetIDsOfNames(IID, Names, NameCount, LocaleID, DispIDs)
  542. else
  543. Result := E_NOTIMPL;
  544. end;
  545. function TComponent.Invoke(DispID: Integer; const IID: TGUID;
  546. LocaleID: Integer; Flags: Word; var Params; VarResult, ExcepInfo,
  547. ArgErr: Pointer): HResult; stdcall;
  548. begin
  549. if Assigned(VCLComObject) then
  550. Result := IVCLComObject(VCLComObject).Invoke(DispID, IID, LocaleID, Flags, Params,
  551. VarResult, ExcepInfo, ArgErr)
  552. else
  553. Result := E_NOTIMPL;
  554. end;
  555. { Delta stream support }
  556. procedure TComponent.GetDeltaStreams(aProc: TGetStreamProc);
  557. begin
  558. // To be implemented by descendants
  559. end;
  560. procedure TComponent.ReadDeltaStream(const S: TStream);
  561. begin
  562. S.ReadComponent(Self);
  563. end;
  564. procedure TComponent.ReadDeltaState;
  565. var
  566. Done : boolean;
  567. begin
  568. if (csDesigning in ComponentState) then
  569. exit;
  570. Done:=False;
  571. if Assigned(FOnGetDeltaStreams) then
  572. FOnGetDeltaStreams(Self,@ReadDeltaStream,Done);
  573. if not Done then
  574. GetDeltaStreams(@ReadDeltaStream);
  575. end;