unit ListSort; { Description =========== Contains the classes TSortedList and TBatchWork. You will find more details in the help-files. Disclaimer ========== The author disclaims all warranties, expressed or implied, including, without limitation, the warranties of merchantability and of fitness for any purpose. The author assumes no liability for damages, direct or consequential, which may result from the use of this component/units. Restrictions on Using the Unit / Component ========================================== This archive and its contents is copyright 1998,99 by Dieter Steinwedel. ALL RIGHTS ARE RESERVED BY DIETER STEINWEDEL. You are allowed to use it freely subject to the following restrictions: • You are not allowed delete or alter the author's name and copyright in any manner • You are not allowed to publish a copy, modified version or compilation neither for payment in any kind nor freely if the author has not agreed • You are allowed to create a link to the download in the WWW These restrictions and terms apply to you as long as you use this archive. I won't change these conditions when I have published the archive. But I reserve the right to alter these conditions for a newer archive version. The archive version is the archive's date. Changes can found on my homepage. Contact ======= homepage: http://godard.oec.uni-osnabrueck.de/student_home/dsteinwe/delphi/DietersDelphiSite.htm } interface uses Classes, SysUtils; type TCompareFunction = function (Sender: TObject; Item1, Item2: Pointer): integer of object; TOnListEvent = procedure (Sender: TObject; Item: Pointer) of object; TBatchControlEvent = procedure(Sender: TObject; Item:pointer) of object; TSortedList = class(TList) private FCompare:TCompareFunction; FOnAdd:TOnListEvent; FOnModify:TOnListEvent; FOnErase:TOnListEvent; FAllowDuplicates: boolean; public constructor Create; function Add(Item: Pointer): integer; procedure Clear; {MP}reintroduce;{/MP} procedure Delete(Index:integer); function FindObject(Item : Pointer) : integer; function Insert(Index: Integer; Item: Pointer): integer; function Rearrange(Item: Pointer):integer; procedure Remove(Item:Pointer); procedure Sort; property AllowDuplicates: boolean read FAllowDuplicates write FAllowDuplicates; property OnAdd: TOnListEvent read FOnAdd write FOnAdd; property OnCompare: TCompareFunction read FCompare write FCompare; property OnModify: TOnListEvent read FOnModify write FOnModify; property OnErase: TOnListEvent read FOnErase write FOnErase; end; TBatchControl = class(TComponent) private FOnProcess: TBatchControlEvent; FList: TSortedList; public property List: TSortedList read FList write FList; constructor Create(AOwner: TComponent); override; destructor Destroy; override; procedure Execute; published property OnProcess: TBatchControlEvent read FOnProcess write FOnProcess; end; procedure Register; implementation procedure Register; begin {MP}RegisterComponents({'Misc'}'DragDrop', [TBatchControl]); end; { SortedList ------------------------------------------------------ } constructor TSortedList.Create; begin inherited Create; FAllowDuplicates := true; end; function TSortedList.Add(Item : Pointer) : integer; var nCount : integer; bFound : Boolean; begin nCount := 0; bFound := False; if Assigned(FCompare) then begin { search the list of objects until we find the correct position for the new object we are adding } while (not bFound) and (nCount < Count) do begin if (FCompare(self,Items[nCount],Item) >= 0) then bFound := True else inc(nCount); end; if bFound then begin if FAllowDuplicates or (FCompare(self,Items[nCount],Item)<>0) then begin inherited Insert(nCount,Item); Result := nCount; end else Result := -1; end else Result := inherited Add(Item); end else Result:=inherited Add(Item); if Assigned(FOnAdd) then FOnAdd(self,Item); end; function TSortedList.Insert(Index: Integer; Item: Pointer):integer; var nCount : integer; bFound : Boolean; begin nCount := 0; bFound := False; if Assigned(FCompare) then begin { search the list of objects until we find the correct position for the new object we are adding } while (not bFound) and (nCount < Count) do begin if (FCompare(self,Items[nCount],Item) >= 0) then bFound := True else inc(nCount); end; if bFound then begin if FAllowDuplicates or (FCompare(self,Items[nCount],Item)<>0) then begin inherited Insert(nCount,Item); Result := nCount; end else Result := -1; end else Result := inherited Add(Item); end else begin inherited Insert(Index,Item); Result:=Index; end; if Assigned(FOnAdd) then FOnAdd(self,Item); end; function TSortedList.FindObject(Item : Pointer) : integer; { Find the object using the compare method and a binary chop search } var nResult : integer; nLow : integer; nHigh : integer; nCompare : integer; nCheckPos : integer; begin nLow := 0; nHigh := Count-1; nResult := -1; { keep searching until found or no more items to search } while (nResult = -1) and (nLow <= nHigh) do begin nCheckPos := (nLow + nHigh) div 2; nCompare := FCompare(self, Item,Items[nCheckPos]); if (nCompare = -1) then nHigh := nCheckPos - 1 { less than } else if (nCompare = 1) then nLow := nCheckPos + 1 { greater than } else nResult := nCheckPos; { equal to } end; FindObject := nResult; end; procedure TSortedList.Sort; procedure QuickSort(ILo, IHi:integer); var Lo, Hi:integer; MidItem: pointer; begin Lo:=ILo; Hi:=IHi; MidItem:=Items[(Lo+Hi) div 2]; repeat while FCompare(self,Items[Lo],MidItem)=-1 do inc(Lo); while FCompare(self,Items[Hi],MidItem)=1 do dec(Hi); if Lo<=Hi then begin Exchange(Lo,Hi); inc(Lo); dec(Hi); end; until Lo>Hi; if Hi>ILo then QuickSort(ILo,Hi); if Lo0 then begin Quicksort(0,Count-1); if (FAllowDuplicates=false) and (count>=2) then begin for i:=count-1 downto 1 do if FCompare(self,Items[i],Items[i-1])=0 then delete(i); end; end; end else raise Exception.Create('Compare methode is not assigned!') end; procedure TSortedList.Clear; begin while Count>0 do Delete(Count-1); end; function TSortedList.Rearrange(Item: Pointer):integer; begin Remove(Item); Result:=Add(Item); if Assigned(FOnModify) then FOnModify(self,Item); end; procedure TSortedList.Delete(Index:integer); begin if Assigned(FOnErase) then FOnErase(self,Items[Index]); inherited Delete(Index); end; procedure TSortedList.Remove(Item:Pointer); begin if Assigned(FOnErase) then FOnErase(self,Item); inherited Remove(Item); end; { BatchControl ------------------------------------------------------ } constructor TBatchControl.Create(AOwner: TComponent); begin inherited Create(AOwner); FList:=TSortedList.Create; end; destructor TBatchControl.Destroy; begin FList.free; inherited Destroy; end; procedure TBatchControl.Execute; begin if Assigned(FOnProcess) then begin while (FList.Count>0) do begin FOnProcess(self,FList.Items[FList.Count-1]); if (FList.Items[FList.Count-1]<>nil) then FList.Delete(FList.Count-1); end; end else raise Exception.Create('No OnProcess-method defined!'); end; end.