unit U_Common_Classes; interface uses Windows, Messages, SysUtils, Variants, Classes, Contnrs, RtlConsts; type //Tolik 12/12/2019 -- TMyObject = Class(TObject) public RelationList: TList; Constructor Create; Destructor Destroy;override; End; TMyList = class(TList) private //FList: PPointerList; //FCount: Integer; //FCapacity: Integer; RelationList: TList; protected procedure Put(Index: Integer; Item: Pointer); overload; public function Add(Item: Pointer): Integer; overload; {function Add(Item: TMyObject): Integer; overload; function Add(Item: TMyList): Integer; overload;} procedure Clear; overload; procedure Delete(Index: Integer); overload; procedure Insert(Index: Integer; Item: Pointer); overload; function ExtractItem(Item: Pointer; Direction: TList.TDirection): Pointer; //overload; procedure Assign(ListA: TList; AOperator: TListAssignOp = laCopy; ListB: TList = nil); overload; function Remove(Item: Pointer): Integer; overload; function RemoveItem(Item: Pointer; Direction: TList.TDirection): Integer; overload; property Items[Index: Integer]: Pointer read Get write Put; default; Constructor create; Destructor destroy; override; end; TMyObjectList = class(TMyList) private FOwnsObjects: Boolean; protected procedure Notify(Ptr: Pointer; Action: TListNotification); override; function GetItem(Index: Integer): TObject; //inline; procedure SetItem(Index: Integer; AObject: TObject); //inline; public constructor Create; overload; constructor Create(AOwnsObjects: Boolean); overload; destructor destroy; reintroduce; procedure Clear; function Add(AObject: TObject): Integer; overload; function Extract(Item: TObject): TObject; //inline; function ExtractItem(Item: TObject; Direction: TList.TDirection): TObject; //inline; function Remove(AObject: TObject): Integer; overload; inline; function RemoveItem(AObject: TObject; ADirection: TList.TDirection): Integer; //inline; function IndexOf(AObject: TObject): Integer;// inline; function IndexOfItem(AObject: TObject; ADirection: TList.TDirection): Integer; //inline; function FindInstanceOf(AClass: TClass; AExact: Boolean = True; AStartAt: Integer = 0): Integer; procedure Insert(Index: Integer; AObject: TObject); //inline; function First: TObject; //inline; function Last: TObject; //inline; property OwnsObjects: Boolean read FOwnsObjects write FOwnsObjects; property Items[Index: Integer]: TObject read GetItem write SetItem; default; end; // implementation function isMytype(aObj: Pointer):Boolean; begin Result := False; if aObj <> nil then begin try if TObject(aObj) is tMyObject then Result := True else if TObject(aObj) is TMyList then Result := True; except on E: Exception do; end; end; end; // Tolik 12/12/2019 -- //---------- My Object ---------------------------------- constructor TMyObject.create; begin inherited; RelationList := TList.create; end; Destructor TMyObject.destroy; var i, j, ObjectIndex: Integer; RelList: TMyList; canDelObj: Boolean; begin if assigned(RelationList) then begin for i := RelationList.Count - 1 downto 0 do begin try if isMytype(RelationList[i]) then begin RelList := TMyList(RelationList[i]); if RelList <> nil then begin candelObj := True; while canDelObj do begin ObjectIndex := RelList.IndexOf(Self); if ObjectIndex <> -1 then candelObj := True else candelObj := False; if candelObj then RelList[ObjectIndex] := nil; end; end; end else beep; Except On E: Exception do; end; end; freeAndNil(RelationList); end else begin beep; end; //inherited; end; // ---------------- My List --------------------------------------- function TMyList.Add(Item: Pointer): Integer; //function TMyList.Add(Item: TMyObject): Integer; begin Result := inherited Add(Item); if Item <> nil then if assigned(TMyObject(Item).RelationList) then begin if TMyObject(Item).RelationList.IndexOf(Self) = -1 then TMyObject(Item).RelationList.Add(Self); end else beep; end; { function TMyList.Add(Item: TMyList): Integer; var s: string; begin Result := inherited Add(Item); if Item <> nil then begin s := TObject(Item).ClassName; if assigned(TMyObject(Item).RelationList) then begin if TMyObject(Item).RelationList.IndexOf(Self) = -1 then TMyObject(Item).RelationList.Add(Self); end else beep; end; end; } procedure TMyList.Clear; var i: Integer; //ListObj: TMyObject; ListObj: TObject; begin for i := 0 to Count - 1 do begin ListObj := TObject(Items[i]); if ListObj <> nil then begin if assigned(TMyObject(ListObj).RelationList) then TMyObject(ListObj).RelationList.Remove(Self) else beep; end; end; inherited; end; procedure TMyList.Delete(Index: Integer); var ListObj: TMyObject; begin if Index > -1 then if Index < Count then begin ListObj := Items[Index]; if ListObj <> nil then begin if assigned(ListObj.RelationList) then ListObj.RelationList.Remove(Self) else beep; end; end; inherited; end; procedure TMyList.Insert(Index: Integer; Item: Pointer); begin inherited; if Item <> nil then begin if assigned(TmyObject(Item).RelationList) then begin if TmyObject(Item).RelationList.IndexOf(Self) = -1 then TmyObject(Item).RelationList.Add(Self); end else beep; end; end; procedure TMyList.Put(Index: Integer; Item: Pointer); var ListObj: TMyObject; begin ListObj := nil; if Index > -1 then if Index < Count then ListObj := TMyObject(Items[Index]); inherited; if ListObj <> nil then try if Self.IndexOf(ListObj) = -1 then begin if assigned(ListObj.RelationList) then ListObj.RelationList.Remove(Self) else beep; end; Except on E: Exception do; end; if Item <> nil then try if assigned(TMyObject(Item).RelationList) then begin if TMyObject(Item).RelationList.IndexOf(Self) = -1 then TMyObject(Item).RelationList.Add(Self); end else beep; Except on E: Exception do; end; end; function TMyList.ExtractItem(Item: Pointer; Direction: TList.TDirection): Pointer; begin Result := inherited ExtractItem(Item, Direction); if Result <> nil then if Self.IndexOf(Result) = -1 then begin if assigned(TmyObject(Result).RelationList) then TmyObject(Result).RelationList.Remove(Self) else beep; end; end; procedure TMyList.Assign(ListA: TList; AOperator: TListAssignOp; ListB: TList); var I: Integer; LTemp, LSource: TList; begin // ListB given? if ListB <> nil then begin LSource := ListB; Assign(ListA); end else LSource := ListA; // on with the show case AOperator of // 12345, 346 = 346 : only those in the new list laCopy: begin Clear; Capacity := LSource.Capacity; for I := 0 to LSource.Count - 1 do Add(LSource[I]); end; // 12345, 346 = 34 : intersection of the two lists laAnd: for I := Count - 1 downto 0 do if LSource.IndexOf(Items[I]) = -1 then Delete(I); // 12345, 346 = 123456 : union of the two lists laOr: for I := 0 to LSource.Count - 1 do if IndexOf(LSource[I]) = -1 then Add(LSource[I]); // 12345, 346 = 1256 : only those not in both lists laXor: begin LTemp := TList.Create; // Temp holder of 4 byte values try LTemp.Capacity := LSource.Count; for I := 0 to LSource.Count - 1 do if IndexOf(LSource[I]) = -1 then LTemp.Add(LSource[I]); for I := Count - 1 downto 0 do if LSource.IndexOf(Items[I]) <> -1 then Delete(I); I := Count + LTemp.Count; if Capacity < I then Capacity := I; for I := 0 to LTemp.Count - 1 do Add(LTemp[I]); finally LTemp.Free; end; end; // 12345, 346 = 125 : only those unique to source laSrcUnique: for I := Count - 1 downto 0 do if LSource.IndexOf(Items[I]) <> -1 then Delete(I); // 12345, 346 = 6 : only those unique to dest laDestUnique: begin LTemp := TList.Create; try LTemp.Capacity := LSource.Count; for I := LSource.Count - 1 downto 0 do if IndexOf(LSource[I]) = -1 then LTemp.Add(LSource[I]); Assign(LTemp); finally LTemp.Free; end; end; end; end; function TMyList.Remove(Item: Pointer): Integer; begin Result := RemoveItem(Item, TList.TDirection.FromBeginning); end; function TMyList.RemoveItem(Item: Pointer; Direction: TList.TDirection): Integer; begin Result := IndexOfItem(Item, Direction); if Result >= 0 then Delete(Result); end; Constructor TMyList.create; begin inherited; RelationList:= TList.Create; end; Destructor TMyList.destroy; var i, SelIndex: Integer; SelObject: TMyObject; begin Clear; try for i := 0 to RelationList.Count - 1 do begin SelIndex := TList(RelationList[i]).IndexOf(Self); if SelIndex > -1 then TList(RelationList[i])[SelIndex] := nil; end; except On E: Exception do; end; RelationList.Free; inherited; end; // ---------------- TMyObjectList ---------------------------------- function TMyObjectList.Add(AObject: TObject): Integer; begin Result := inherited Add(AObject); end; constructor TMyObjectList.Create; begin inherited Create; FOwnsObjects := True; end; constructor TMyObjectList.Create(AOwnsObjects: Boolean); begin inherited Create; FOwnsObjects := AOwnsObjects; end; destructor TMyObjectList.destroy; begin if FOwnsObjects then begin end; inherited; end; procedure TMyObjectList.Clear; begin inherited; end; function TMyObjectList.Extract(Item: TObject): TObject; begin Result := TObject(inherited Extract(Item)); end; function TMyObjectList.ExtractItem(Item: TObject; Direction: TList.TDirection): TObject; begin Result := TObject(inherited ExtractItem(Item, Direction)); end; function TMyObjectList.FindInstanceOf(AClass: TClass; AExact: Boolean; AStartAt: Integer): Integer; var I: Integer; begin Result := -1; for I := AStartAt to Count - 1 do if (AExact and (Items[I].ClassType = AClass)) or (not AExact and Items[I].InheritsFrom(AClass)) then begin Result := I; break; end; end; function TMyObjectList.First: TObject; begin Result := TObject(inherited First); end; function TMyObjectList.GetItem(Index: Integer): TObject; begin Result := inherited Items[Index]; end; function TMyObjectList.IndexOf(AObject: TObject): Integer; begin Result := inherited IndexOf(AObject); end; function TMyObjectList.IndexOfItem(AObject: TObject; ADirection: TList.TDirection): Integer; begin Result := inherited IndexOfItem(AObject, ADirection); end; procedure TMyObjectList.Insert(Index: Integer; AObject: TObject); begin inherited Insert(Index, AObject); end; function TMyObjectList.Last: TObject; begin Result := TObject(inherited Last); end; procedure TMyObjectList.Notify(Ptr: Pointer; Action: TListNotification); begin if (Action = lnDeleted) and OwnsObjects then TObject(Ptr).Free; inherited Notify(Ptr, Action); end; function TMyObjectList.Remove(AObject: TObject): Integer; begin Result := inherited Remove(AObject); end; function TMyObjectList.RemoveItem(AObject: TObject; ADirection: TList.TDirection): Integer; begin Result := inherited RemoveItem(AObject, ADirection); end; procedure TMyObjectList.SetItem(Index: Integer; AObject: TObject); begin inherited Items[Index] := AObject; end; end.