From 66c2a0c61ab2fdade6990f3f3fdfc12c8ba27e5b Mon Sep 17 00:00:00 2001 From: mattias Date: Sun, 3 Feb 2013 19:11:06 +0000 Subject: [PATCH] cody: lvl graph: autolayout on paint git-svn-id: trunk@40163 - --- components/codetools/ide/codyctrls.pas | 94 ++++++++++++++++++++++++-- 1 file changed, 88 insertions(+), 6 deletions(-) diff --git a/components/codetools/ide/codyctrls.pas b/components/codetools/ide/codyctrls.pas index eae6a772a7..b42a067883 100644 --- a/components/codetools/ide/codyctrls.pas +++ b/components/codetools/ide/codyctrls.pas @@ -233,6 +233,15 @@ type const DefaultLvlGraphNodeWith = 10; +type + TLvlGraphCtrlOption = ( + lgoAutoLayout + ); + TLvlGraphCtrlOptions = set of TLvlGraphCtrlOption; + TOnLvlGraphStructureChanged = procedure(Sender, Element: TObject; Operation: TOperation) of object; + +const + DefaultLvlGraphCtrlOptions = [lgoAutoLayout]; type TLvlGraph = class; TLvlGraphEdge = class; @@ -319,6 +328,7 @@ type function GetNodes(Index: integer): TLvlGraphNode; procedure SetDrawPosition(AValue: integer); public + Data: Pointer; // free for user data constructor Create(TheGraph: TLvlGraph; TheIndex: integer); destructor Destroy; override; procedure Invalidate; @@ -343,10 +353,12 @@ type FOnInvalidate: TNotifyEvent; FNodes: TFPList; // list of TLvlGraphNode fLevels: TFPList; + FOnStructureChanged: TOnLvlGraphStructureChanged; function GetLevelCount: integer; function GetLevels(Index: integer): TLvlGraphLevel; function GetNodes(Index: integer): TLvlGraphNode; procedure SetLevelCount(AValue: integer); + procedure InternalRemoveNode(Node: TLvlGraphNode); procedure InternalRemoveLevel(Lvl: TLvlGraphLevel); protected public @@ -356,7 +368,9 @@ type procedure Clear; procedure Invalidate; + procedure StructureChanged(Element: TObject; Operation: TOperation); property OnInvalidate: TNotifyEvent read FOnInvalidate write FOnInvalidate; + property OnStructureChanged: TOnLvlGraphStructureChanged read FOnStructureChanged write FOnStructureChanged;// node, edge, level was added/deleted // nodes function NodeCount: integer; @@ -389,21 +403,26 @@ type end; TLvlGraphControlFlag = ( - lgcNeedInvalidate + lgcNeedInvalidate, + lgcNeedAutoLayout, + lgcIgnoreGraphInvalidate ); TLvlGraphControlFlags = set of TLvlGraphControlFlag; { TCustomLvlGraphControl } TCustomLvlGraphControl = class(TCustomControl) - procedure FGraphInvalidate(Sender: TObject); private FGraph: TLvlGraph; FNodeWidth: integer; + FOptions: TLvlGraphCtrlOptions; fUpdateLock: integer; FFlags: TLvlGraphControlFlags; procedure SetNodeWidth(AValue: integer); + procedure SetOptions(AValue: TLvlGraphCtrlOptions); protected + procedure GraphInvalidate(Sender: TObject); virtual; + procedure GraphStructureChanged(Sender, Element: TObject; {%H-}Operation: TOperation); virtual; procedure DoSetBounds(ALeft, ATop, AWidth, AHeight: integer); override; procedure Paint; override; public @@ -417,6 +436,7 @@ type procedure BeginUpdate; procedure EndUpdate; property NodeWidth: integer read FNodeWidth write SetNodeWidth default DefaultLvlGraphNodeWith; + property Options: TLvlGraphCtrlOptions read FOptions write SetOptions default DefaultLvlGraphCtrlOptions; end; { TLvlGraphControl } @@ -637,6 +657,8 @@ begin FGraph.fLevels.Add(Self); FIndex:=TheIndex; fNodes:=TFPList.Create; + if Graph<>nil then + Graph.StructureChanged(Self,opInsert); end; destructor TLvlGraphLevel.Destroy; @@ -645,8 +667,10 @@ var begin for i:=0 to Count-1 do Nodes[i].OnLevelDestroy; - Graph.InternalRemoveLevel(Self); + if Count>0 then + raise Exception.Create(''); FreeAndNil(fNodes); + Graph.InternalRemoveLevel(Self); inherited Destroy; end; @@ -688,11 +712,23 @@ end; { TCustomLvlGraphControl } -procedure TCustomLvlGraphControl.FGraphInvalidate(Sender: TObject); +procedure TCustomLvlGraphControl.GraphInvalidate(Sender: TObject); begin + if lgcIgnoreGraphInvalidate in FFlags then exit; Invalidate; end; +procedure TCustomLvlGraphControl.GraphStructureChanged(Sender, + Element: TObject; Operation: TOperation); +begin + if ((Element is TLvlGraphNode) + or (Element is TLvlGraphEdge)) then begin + debugln(['TCustomLvlGraphControl.GraphStructureChanged ']); + if lgoAutoLayout in FOptions then + Include(FFlags,lgcNeedAutoLayout); + end; +end; + procedure TCustomLvlGraphControl.SetNodeWidth(AValue: integer); begin if FNodeWidth=AValue then Exit; @@ -700,6 +736,12 @@ begin Invalidate; end; +procedure TCustomLvlGraphControl.SetOptions(AValue: TLvlGraphCtrlOptions); +begin + if FOptions=AValue then Exit; + FOptions:=AValue; +end; + procedure TCustomLvlGraphControl.DoSetBounds(ALeft, ATop, AWidth, AHeight: integer); begin @@ -715,7 +757,19 @@ var j: Integer; Node: TLvlGraphNode; begin + debugln(['TCustomLvlGraphControl.Paint ']); inherited Paint; + + if (lgoAutoLayout in FOptions) + and (lgcNeedAutoLayout in FFlags) then begin + Include(FFlags,lgcIgnoreGraphInvalidate); + try + AutoLayout; + finally + Exclude(FFlags,lgcIgnoreGraphInvalidate); + end; + end; + // background Canvas.Brush.Style:=bsSolid; Canvas.Brush.Color:=Color; @@ -744,8 +798,10 @@ end; constructor TCustomLvlGraphControl.Create(AOwner: TComponent); begin inherited Create(AOwner); + FOptions:=DefaultLvlGraphCtrlOptions; FGraph:=TLvlGraph.Create; - FGraph.OnInvalidate:=@FGraphInvalidate; + FGraph.OnInvalidate:=@GraphInvalidate; + FGraph.OnStructureChanged:=@GraphStructureChanged; FNodeWidth:=DefaultLvlGraphNodeWith; end; @@ -774,6 +830,8 @@ var DrawHeight: Integer; Palette: TCodyCtrlPalette; begin + debugln(['TCustomLvlGraphControl.AutoLayout ',DbgSName(Self),' ClientRect=',dbgs(ClientRect)]); + Exclude(FFlags,lgcNeedAutoLayout); BeginUpdate; try if Caption<>'' then begin @@ -888,6 +946,13 @@ begin Levels[LevelCount-1].Free; end; +procedure TLvlGraph.InternalRemoveNode(Node: TLvlGraphNode); +begin + FNodes.Remove(Node); + Node.FGraph:=nil; + StructureChanged(Node,opRemove); +end; + function TLvlGraph.GetLevels(Index: integer): TLvlGraphLevel; begin Result:=TLvlGraphLevel(fLevels[Index]); @@ -931,6 +996,12 @@ begin OnInvalidate(Self); end; +procedure TLvlGraph.StructureChanged(Element: TObject; Operation: TOperation); +begin + if Assigned(OnStructureChanged) then + OnStructureChanged(Self,Element,Operation); +end; + function TLvlGraph.NodeCount: integer; begin Result:=FNodes.Count; @@ -950,6 +1021,7 @@ begin LevelCount:=1; Result:=FNodeClass.Create(Self,aCaption,Levels[0]); FNodes.Add(Result); + StructureChanged(Result,opInsert); end else Result:=nil; end; @@ -972,8 +1044,10 @@ function TLvlGraph.GetEdge(Source, Target: TLvlGraphNode; begin Result:=Source.FindOutEdge(Target); if Result<>nil then exit; - if CreateIfNotExists then + if CreateIfNotExists then begin Result:=FEdgeClass.Create(Source,Target); + StructureChanged(Result,opInsert); + end; end; procedure TLvlGraph.InternalRemoveLevel(Lvl: TLvlGraphLevel); @@ -986,6 +1060,7 @@ begin // update level Index for i:=Lvl.Index to LevelCount-1 do Levels[i].FIndex:=i; + StructureChanged(Lvl,opRemove); end; procedure TLvlGraph.CreateTopologicalLevels; @@ -1312,11 +1387,16 @@ begin end; destructor TLvlGraphEdge.Destroy; +var + OldGraph: TLvlGraph; begin + OldGraph:=Source.Graph; Source.FOutEdges.Remove(Self); Target.FInEdges.Remove(Self); FSource:=nil; FTarget:=nil; + if OldGraph<>nil then + OldGraph.StructureChanged(Self,opRemove); inherited Destroy; end; @@ -1408,6 +1488,8 @@ destructor TLvlGraphNode.Destroy; begin Clear; UnbindLevel; + if Graph<>nil then + Graph.InternalRemoveNode(Self); inherited Destroy; end;