ListSort.pas 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. unit ListSort;
  2. {
  3. Description
  4. ===========
  5. Contains the classes TSortedList and TBatchWork. You will find more
  6. details in the help-files.
  7. Disclaimer
  8. ==========
  9. The author disclaims all warranties, expressed or implied, including,
  10. without limitation, the warranties of merchantability and of fitness
  11. for any purpose. The author assumes no liability for damages, direct or
  12. consequential, which may result from the use of this component/units.
  13. Restrictions on Using the Unit / Component
  14. ==========================================
  15. This archive and its contents is copyright 1998,99 by Dieter Steinwedel.
  16. ALL RIGHTS ARE RESERVED BY DIETER STEINWEDEL. You are allowed to use it
  17. freely subject to the following restrictions:
  18. • You are not allowed delete or alter the author's name and
  19. copyright in any manner
  20. • You are not allowed to publish a copy, modified version or
  21. compilation neither for payment in any kind nor freely if the
  22. author has not agreed
  23. • You are allowed to create a link to the download in the WWW
  24. These restrictions and terms apply to you as long as you use this
  25. archive. I won't change these conditions when I have published the
  26. archive. But I reserve the right to alter these conditions for a
  27. newer archive version. The archive version is the archive's date.
  28. Changes can found on my homepage.
  29. Contact
  30. =======
  31. homepage: http://godard.oec.uni-osnabrueck.de/student_home/dsteinwe/delphi/DietersDelphiSite.htm
  32. }
  33. interface
  34. uses Classes, SysUtils;
  35. type
  36. TCompareFunction = function (Sender: TObject; Item1, Item2: Pointer): integer of object;
  37. TOnListEvent = procedure (Sender: TObject; Item: Pointer) of object;
  38. TBatchControlEvent = procedure(Sender: TObject; Item:pointer) of object;
  39. TSortedList = class(TList)
  40. private
  41. FCompare:TCompareFunction;
  42. FOnAdd:TOnListEvent;
  43. FOnModify:TOnListEvent;
  44. FOnErase:TOnListEvent;
  45. FAllowDuplicates: boolean;
  46. public
  47. constructor Create;
  48. function Add(Item: Pointer): integer;
  49. procedure Clear; {MP}reintroduce;{/MP}
  50. procedure Delete(Index:integer);
  51. function FindObject(Item : Pointer) : integer;
  52. function Insert(Index: Integer; Item: Pointer): integer;
  53. function Rearrange(Item: Pointer):integer;
  54. procedure Remove(Item:Pointer);
  55. procedure Sort;
  56. property AllowDuplicates: boolean read FAllowDuplicates write FAllowDuplicates;
  57. property OnAdd: TOnListEvent read FOnAdd write FOnAdd;
  58. property OnCompare: TCompareFunction read FCompare write FCompare;
  59. property OnModify: TOnListEvent read FOnModify write FOnModify;
  60. property OnErase: TOnListEvent read FOnErase write FOnErase;
  61. end;
  62. TBatchControl = class(TComponent)
  63. private
  64. FOnProcess: TBatchControlEvent;
  65. FList: TSortedList;
  66. public
  67. property List: TSortedList read FList write FList;
  68. constructor Create(AOwner: TComponent); override;
  69. destructor Destroy; override;
  70. procedure Execute;
  71. published
  72. property OnProcess: TBatchControlEvent read FOnProcess write FOnProcess;
  73. end;
  74. procedure Register;
  75. implementation
  76. procedure Register;
  77. begin
  78. {MP}RegisterComponents({'Misc'}'DragDrop', [TBatchControl]);
  79. end;
  80. { SortedList ------------------------------------------------------ }
  81. constructor TSortedList.Create;
  82. begin
  83. inherited Create;
  84. FAllowDuplicates := true;
  85. end;
  86. function TSortedList.Add(Item : Pointer) : integer;
  87. var
  88. nCount : integer;
  89. bFound : Boolean;
  90. begin
  91. nCount := 0;
  92. bFound := False;
  93. if Assigned(FCompare) then
  94. begin
  95. { search the list of objects until we find the
  96. correct position for the new object we are adding }
  97. while (not bFound) and (nCount < Count) do
  98. begin
  99. if (FCompare(self,Items[nCount],Item) >= 0) then bFound := True
  100. else inc(nCount);
  101. end;
  102. if bFound then
  103. begin
  104. if FAllowDuplicates or (FCompare(self,Items[nCount],Item)<>0) then
  105. begin
  106. inherited Insert(nCount,Item);
  107. Result := nCount;
  108. end
  109. else Result := -1;
  110. end else Result := inherited Add(Item);
  111. end
  112. else Result:=inherited Add(Item);
  113. if Assigned(FOnAdd) then FOnAdd(self,Item);
  114. end;
  115. function TSortedList.Insert(Index: Integer; Item: Pointer):integer;
  116. var
  117. nCount : integer;
  118. bFound : Boolean;
  119. begin
  120. nCount := 0;
  121. bFound := False;
  122. if Assigned(FCompare) then
  123. begin
  124. { search the list of objects until we find the
  125. correct position for the new object we are adding }
  126. while (not bFound) and (nCount < Count) do
  127. begin
  128. if (FCompare(self,Items[nCount],Item) >= 0) then bFound := True
  129. else inc(nCount);
  130. end;
  131. if bFound then
  132. begin
  133. if FAllowDuplicates or (FCompare(self,Items[nCount],Item)<>0) then
  134. begin
  135. inherited Insert(nCount,Item);
  136. Result := nCount;
  137. end
  138. else Result := -1;
  139. end else Result := inherited Add(Item);
  140. end
  141. else
  142. begin
  143. inherited Insert(Index,Item);
  144. Result:=Index;
  145. end;
  146. if Assigned(FOnAdd) then FOnAdd(self,Item);
  147. end;
  148. function TSortedList.FindObject(Item : Pointer) : integer;
  149. { Find the object using the compare method and
  150. a binary chop search }
  151. var
  152. nResult : integer;
  153. nLow : integer;
  154. nHigh : integer;
  155. nCompare : integer;
  156. nCheckPos : integer;
  157. begin
  158. nLow := 0;
  159. nHigh := Count-1;
  160. nResult := -1;
  161. { keep searching until found or no more items to search }
  162. while (nResult = -1) and (nLow <= nHigh) do
  163. begin
  164. nCheckPos := (nLow + nHigh) div 2;
  165. nCompare := FCompare(self, Item,Items[nCheckPos]);
  166. if (nCompare = -1) then nHigh := nCheckPos - 1 { less than }
  167. else if (nCompare = 1) then nLow := nCheckPos + 1 { greater than }
  168. else nResult := nCheckPos; { equal to }
  169. end;
  170. FindObject := nResult;
  171. end;
  172. procedure TSortedList.Sort;
  173. procedure QuickSort(ILo, IHi:integer);
  174. var Lo, Hi:integer;
  175. MidItem: pointer;
  176. begin
  177. Lo:=ILo;
  178. Hi:=IHi;
  179. MidItem:=Items[(Lo+Hi) div 2];
  180. repeat
  181. while FCompare(self,Items[Lo],MidItem)=-1 do inc(Lo);
  182. while FCompare(self,Items[Hi],MidItem)=1 do dec(Hi);
  183. if Lo<=Hi then
  184. begin
  185. Exchange(Lo,Hi);
  186. inc(Lo);
  187. dec(Hi);
  188. end;
  189. until Lo>Hi;
  190. if Hi>ILo then QuickSort(ILo,Hi);
  191. if Lo<IHi then Quicksort(Lo,IHi);
  192. end;
  193. var i:integer;
  194. begin
  195. if Assigned(FCompare) then
  196. begin
  197. if Count>0 then
  198. begin
  199. Quicksort(0,Count-1);
  200. if (FAllowDuplicates=false) and (count>=2) then
  201. begin
  202. for i:=count-1 downto 1 do
  203. if FCompare(self,Items[i],Items[i-1])=0 then
  204. delete(i);
  205. end;
  206. end;
  207. end
  208. else raise Exception.Create('Compare methode is not assigned!')
  209. end;
  210. procedure TSortedList.Clear;
  211. begin
  212. while Count>0 do Delete(Count-1);
  213. end;
  214. function TSortedList.Rearrange(Item: Pointer):integer;
  215. begin
  216. Remove(Item);
  217. Result:=Add(Item);
  218. if Assigned(FOnModify) then FOnModify(self,Item);
  219. end;
  220. procedure TSortedList.Delete(Index:integer);
  221. begin
  222. if Assigned(FOnErase) then FOnErase(self,Items[Index]);
  223. inherited Delete(Index);
  224. end;
  225. procedure TSortedList.Remove(Item:Pointer);
  226. begin
  227. if Assigned(FOnErase) then FOnErase(self,Item);
  228. inherited Remove(Item);
  229. end;
  230. { BatchControl ------------------------------------------------------ }
  231. constructor TBatchControl.Create(AOwner: TComponent);
  232. begin
  233. inherited Create(AOwner);
  234. FList:=TSortedList.Create;
  235. end;
  236. destructor TBatchControl.Destroy;
  237. begin
  238. FList.free;
  239. inherited Destroy;
  240. end;
  241. procedure TBatchControl.Execute;
  242. begin
  243. if Assigned(FOnProcess) then
  244. begin
  245. while (FList.Count>0) do
  246. begin
  247. FOnProcess(self,FList.Items[FList.Count-1]);
  248. if (FList.Items[FList.Count-1]<>nil) then
  249. FList.Delete(FList.Count-1);
  250. end;
  251. end
  252. else raise Exception.Create('No OnProcess-method defined!');
  253. end;
  254. end.