|
- unit uutlGraph;
-
- { Package: Utils
- Prefix: utl - UTiLs
- Beschreibung: diese Unit implementiert einen generischen Graphen }
-
- {$mode objfpc}{$H+}
-
- interface
-
- uses
- Classes, SysUtils, contnrs, uutlCommon;
-
- type
- TutlGraph = class;
- TutlGraphNodeData = class(TObject)
- public
- constructor Create; virtual;
- end;
- TutlGraphNodeDataClass = class of TutlGraphNodeData;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- TutlGraphNode = class;
- TutlGraphNodeClass = class of TutlGraphNode;
- TutlGraphNode = class(TutlInterfaceNoRefCount)
- private type
- TNodeEnumerator = class(TObject)
- private
- fOwner: TutlGraphNode;
- fPos: Integer;
- function GetCurrent: TutlGraphNode;
- public
- property Current: TutlGraphNode read GetCurrent;
- function MoveNext: Boolean;
- constructor Create(const aOwner: TutlGraphNode);
- end;
- protected
- fParent: TutlGraphNode;
- fOwner: TutlGraph;
- fData: TutlGraphNodeData;
- fItems: TObjectList;
-
- class function GetDataClass: TutlGraphNodeDataClass; virtual;
-
- function GetCount: Integer; virtual;
- function GetItems(const aIndex: Integer): TutlGraphNode; virtual;
- function AttachNode(const aNode: TutlGraphNode): Boolean; virtual;
- function DetachNode(const aNode: TutlGraphNode): Boolean; virtual;
- public
- property Parent: TutlGraphNode read fParent;
- property Owner: TutlGraph read fOwner;
- property Data: TutlGraphNodeData read fData;
- property Count: Integer read GetCount;
- property Items[const aIndex: Integer]: TutlGraphNode read GetItems; default;
-
- function AddItem: TutlGraphNode;
- function IndexOf(const aItem: TutlGraphNode): Integer;
- procedure DelItem(const aIndex: Integer);
- procedure Clear;
- function IsParent(const aNode: TutlGraphNode): Boolean;
- function Move(const aParent: TutlGraphNode): Boolean;
-
- function GetEnumerator: TNodeEnumerator;
-
- constructor Create(const aParent: TutlGraphNode; const aOwner: TutlGraph);
- destructor Destroy; override;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- TutlGraph = class(TutlInterfaceNoRefCount)
- protected
- fRootNode: TutlGraphNode;
-
- class function GetItemClass: TutlGraphNodeClass; virtual;
- public
- property RootNode: TutlGraphNode read fRootNode;
-
- constructor Create;
- destructor Destroy; override;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- generic TutlGenericGraphNode<GData: TutlGraphNodeData; GNode, GOwner> = class(TutlGraphNode)
- private type
- TGenericNodeEnumerator = class(TObject)
- private
- fOwner: TutlGraphNode;
- fPos: Integer;
- function GetCurrent: GNode;
- public
- property Current: GNode read GetCurrent;
- function MoveNext: Boolean;
- constructor Create(const aOwner: TutlGraphNode);
- end;
- private
- function GetParent: GNode;
- function GetOwner: GOwner;
- function GetData: GData;
- function GetItemsGeneric(const aIndex: Integer): GNode;
- public
- property Parent: GNode read GetParent;
- property Owner: GOwner read GetOwner;
- property Data: GData read GetData;
- property Items[const aIndex: Integer]: GNode read GetItemsGeneric; default;
-
- function AddItem: GNode;
- function IndexOf(const aItem: GNode): Integer;
- function IsParent(const aNode: GNode): Boolean;
- function Move(const aParent: GNode): Boolean;
-
- function GetEnumerator: TGenericNodeEnumerator;
-
- constructor Create(const aParent: GNode; const aOwner: GOwner);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- generic TutlGenericGraph<T: TutlGraphNode> = class(TutlGraph)
- private
- function GetRootNode: T;
- public
- property RootNode: T read GetRootNode;
- end;
-
- implementation
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //TutlGraphNodeData/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- constructor TutlGraphNodeData.Create;
- begin
- inherited Create;
- //nothing to do here
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //TutlGraphNode.TNodeEnumerator//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlGraphNode.TNodeEnumerator.GetCurrent: TutlGraphNode;
- begin
- result := fOwner.Items[fPos];
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlGraphNode.TNodeEnumerator.MoveNext: Boolean;
- begin
- inc(fPos);
- result := (fPos < fOwner.Count);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- constructor TutlGraphNode.TNodeEnumerator.Create(const aOwner: TutlGraphNode);
- begin
- inherited Create;
- fPos := -1;
- fOwner := aOwner;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //TutlGraphNode/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- class function TutlGraphNode.GetDataClass: TutlGraphNodeDataClass;
- begin
- result := TutlGraphNodeData;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlGraphNode.GetCount: Integer;
- begin
- result := fItems.Count;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlGraphNode.GetItems(const aIndex: Integer): TutlGraphNode;
- begin
- if (aIndex >= 0) and (aIndex < Count) then
- result := (fItems[aIndex] as TutlGraphNode)
- else
- raise Exception.Create(Format('index (%d) is out of Range (%d - %d)', [aIndex, 0, Count-1]));
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlGraphNode.AttachNode(const aNode: TutlGraphNode): Boolean;
- begin
- result := true;
- fItems.Add(aNode);
- aNode.fParent := self;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlGraphNode.DetachNode(const aNode: TutlGraphNode): Boolean;
- var
- i: Integer;
- begin
- result := false;
- i := fItems.IndexOf(aNode);
- if (i < 0) then
- exit;
- try
- fItems.OwnsObjects := false;
- fItems.Delete(i);
- aNode.fParent := nil;
- finally
- fItems.OwnsObjects := true;
- end;
- result := true;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlGraphNode.AddItem: TutlGraphNode;
- begin
- if Assigned(Owner) then
- result := Owner.GetItemClass().Create(self, Owner)
- else
- result := TutlGraphNode.Create(self, Owner);
- fItems.Add(result);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlGraphNode.IndexOf(const aItem: TutlGraphNode): Integer;
- begin
- result := fItems.IndexOf(aItem);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- procedure TutlGraphNode.DelItem(const aIndex: Integer);
- begin
- if (aIndex >= 0) and (aIndex < Count) then begin
- fItems.Delete(aIndex);
- end else
- raise Exception.Create(Format('index (%d) is out of Range (%d - %d)', [aIndex, 0, Count-1]));
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- procedure TutlGraphNode.Clear;
- begin
- fItems.Clear;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlGraphNode.IsParent(const aNode: TutlGraphNode): Boolean;
- var
- n: TutlGraphNode;
- begin
- n := self;
- result := true;
- while Assigned(n.Parent) do begin
- if (aNode = n.Parent) then
- exit;
- n := n.Parent;
- end;
- result := false;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlGraphNode.Move(const aParent: TutlGraphNode): Boolean;
- var
- oldParent: TutlGraphNode;
- begin
- result := false;
- if (aParent.IsParent(self)) then
- exit;
- oldParent := Parent;
- if Assigned(oldParent) and not oldParent.DetachNode(self) then
- exit;
- if not aParent.AttachNode(self) then begin
- if Assigned(oldParent) then
- oldParent.AttachNode(self);
- exit;
- end;
- result := true;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlGraphNode.GetEnumerator: TNodeEnumerator;
- begin
- result := TNodeEnumerator.Create(self);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- constructor TutlGraphNode.Create(const aParent: TutlGraphNode; const aOwner: TutlGraph);
- begin
- inherited Create;
- fParent := aParent;
- fOwner := aOwner;
- fData := GetDataClass().Create();
- fItems := TObjectList.create(true);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- destructor TutlGraphNode.Destroy;
- begin
- FreeAndNil(fData);
- FreeAndNil(fItems);
- inherited Destroy;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //TutlGraph/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- class function TutlGraph.GetItemClass: TutlGraphNodeClass;
- begin
- result := TutlGraphNode;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- constructor TutlGraph.Create;
- begin
- inherited Create;
- fRootNode := GetItemClass().Create(nil, self);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- destructor TutlGraph.Destroy;
- begin
- FreeAndNil(fRootNode);
- inherited Destroy;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //TutlGenericGraphNode.TGenericNodeEnumerator///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlGenericGraphNode.TGenericNodeEnumerator.GetCurrent: GNode;
- begin
- result := GNode(fOwner.Items[fPos]);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlGenericGraphNode.TGenericNodeEnumerator.MoveNext: Boolean;
- begin
- inc(fPos);
- result := (fPos < fOwner.Count);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- constructor TutlGenericGraphNode.TGenericNodeEnumerator.Create(const aOwner: TutlGraphNode);
- begin
- inherited Create;
- fPos := -1;
- fOwner := aOwner;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //TutlGenericGraphNode//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlGenericGraphNode.GetParent: GNode;
- begin
- result := GNode(fParent);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlGenericGraphNode.GetOwner: GOwner;
- begin
- result := GOwner(fOwner);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlGenericGraphNode.GetData: GData;
- begin
- result := GData(fData);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlGenericGraphNode.GetItemsGeneric(const aIndex: Integer): GNode;
- begin
- result := GNode(inherited GetItems(aIndex));
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlGenericGraphNode.AddItem: GNode;
- begin
- result := GNode(inherited AddItem);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlGenericGraphNode.IndexOf(const aItem: GNode): Integer;
- begin
- result := inherited IndexOf(aItem);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlGenericGraphNode.IsParent(const aNode: GNode): Boolean;
- begin
- result := inherited IsParent(aNode);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlGenericGraphNode.Move(const aParent: GNode): Boolean;
- begin
- result := inherited Move(aParent);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlGenericGraphNode.GetEnumerator: TGenericNodeEnumerator;
- begin
- result := TGenericNodeEnumerator.Create(self);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- constructor TutlGenericGraphNode.Create(const aParent: GNode; const aOwner: GOwner);
- begin
- inherited Create(TutlGraphNode(aParent), TutlGraph(aOwner));
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //TutlGenericGraph//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlGenericGraph.GetRootNode: T;
- begin
- result := (fRootNode as T);
- end;
-
- end.
|