mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-16 10:39:30 +02:00
cody: lvlgraph: highlight node under mouse
git-svn-id: trunk@40311 -
This commit is contained in:
parent
bec25eb2c8
commit
9895968bea
@ -230,19 +230,6 @@ type
|
||||
property OnUTF8KeyPress;
|
||||
end;
|
||||
|
||||
const
|
||||
DefaultLvlGraphNodeWith = 10;
|
||||
DefaultLvlGraphNodeCaptionScale = 0.7;
|
||||
|
||||
type
|
||||
TLvlGraphCtrlOption = (
|
||||
lgoAutoLayout
|
||||
);
|
||||
TLvlGraphCtrlOptions = set of TLvlGraphCtrlOption;
|
||||
TOnLvlGraphStructureChanged = procedure(Sender, Element: TObject; Operation: TOperation) of object;
|
||||
|
||||
const
|
||||
DefaultLvlGraphCtrlOptions = [lgoAutoLayout];
|
||||
type
|
||||
TLvlGraph = class;
|
||||
TLvlGraphEdge = class;
|
||||
@ -343,6 +330,9 @@ type
|
||||
end;
|
||||
TLvlGraphLevelClass = class of TLvlGraphLevel;
|
||||
|
||||
TOnLvlGraphStructureChanged = procedure(Sender, Element: TObject;
|
||||
Operation: TOperation) of object;
|
||||
|
||||
{ TLvlGraph }
|
||||
|
||||
TLvlGraph = class(TPersistent)
|
||||
@ -403,6 +393,21 @@ type
|
||||
procedure ConsistencyCheck(WithBackEdge: boolean);
|
||||
end;
|
||||
|
||||
const
|
||||
DefaultLvlGraphNodeWith = 10;
|
||||
DefaultLvlGraphNodeCaptionScale = 0.7;
|
||||
|
||||
type
|
||||
TLvlGraphCtrlOption = (
|
||||
lgoAutoLayout, // automatic graph layout after graph was changed
|
||||
lgoHighlightNodeOnMouse // when mouse over node highlight node and its edges
|
||||
);
|
||||
TLvlGraphCtrlOptions = set of TLvlGraphCtrlOption;
|
||||
|
||||
const
|
||||
DefaultLvlGraphCtrlOptions = [lgoAutoLayout,lgoHighlightNodeOnMouse];
|
||||
|
||||
type
|
||||
TLvlGraphControlFlag = (
|
||||
lgcNeedInvalidate,
|
||||
lgcNeedAutoLayout,
|
||||
@ -415,11 +420,15 @@ type
|
||||
TCustomLvlGraphControl = class(TCustomControl)
|
||||
private
|
||||
FGraph: TLvlGraph;
|
||||
FMouseOverNode: TLvlGraphNode;
|
||||
FNodeCaptionScale: single;
|
||||
FNodeWidth: integer;
|
||||
FOptions: TLvlGraphCtrlOptions;
|
||||
fUpdateLock: integer;
|
||||
FFlags: TLvlGraphControlFlags;
|
||||
procedure DrawEdges(Highlighted: boolean);
|
||||
procedure DrawNodes;
|
||||
procedure SetMouseOverNode(AValue: TLvlGraphNode);
|
||||
procedure SetNodeWidth(AValue: integer);
|
||||
procedure SetOptions(AValue: TLvlGraphCtrlOptions);
|
||||
protected
|
||||
@ -427,6 +436,7 @@ type
|
||||
procedure GraphStructureChanged(Sender, Element: TObject; {%H-}Operation: TOperation); virtual;
|
||||
procedure DoSetBounds(ALeft, ATop, AWidth, AHeight: integer); override;
|
||||
procedure Paint; override;
|
||||
procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
|
||||
public
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
destructor Destroy; override;
|
||||
@ -436,7 +446,9 @@ type
|
||||
procedure Invalidate; override;
|
||||
procedure BeginUpdate;
|
||||
procedure EndUpdate;
|
||||
function GetNodeAt(X,Y: integer): TLvlGraphNode;
|
||||
property NodeWidth: integer read FNodeWidth write SetNodeWidth default DefaultLvlGraphNodeWith;
|
||||
property MouseOverNode: TLvlGraphNode read FMouseOverNode write SetMouseOverNode;
|
||||
property Options: TLvlGraphCtrlOptions read FOptions write SetOptions default DefaultLvlGraphCtrlOptions;
|
||||
property NodeCaptionScale: single read FNodeCaptionScale write FNodeCaptionScale default DefaultLvlGraphNodeCaptionScale;
|
||||
end;
|
||||
@ -733,6 +745,8 @@ procedure TCustomLvlGraphControl.GraphStructureChanged(Sender,
|
||||
begin
|
||||
if ((Element is TLvlGraphNode)
|
||||
or (Element is TLvlGraphEdge)) then begin
|
||||
if FMouseOverNode=Element then
|
||||
FMouseOverNode:=nil;
|
||||
debugln(['TCustomLvlGraphControl.GraphStructureChanged ']);
|
||||
if lgoAutoLayout in FOptions then
|
||||
Include(FFlags,lgcNeedAutoLayout);
|
||||
@ -746,6 +760,73 @@ begin
|
||||
Invalidate;
|
||||
end;
|
||||
|
||||
procedure TCustomLvlGraphControl.SetMouseOverNode(AValue: TLvlGraphNode);
|
||||
begin
|
||||
if FMouseOverNode=AValue then Exit;
|
||||
FMouseOverNode:=AValue;
|
||||
Invalidate;
|
||||
end;
|
||||
|
||||
procedure TCustomLvlGraphControl.DrawEdges(Highlighted: boolean);
|
||||
var
|
||||
i: Integer;
|
||||
Level: TLvlGraphLevel;
|
||||
j: Integer;
|
||||
Node: TLvlGraphNode;
|
||||
k: Integer;
|
||||
Edge: TLvlGraphEdge;
|
||||
TargetNode: TLvlGraphNode;
|
||||
NodeHighlighted: Boolean;
|
||||
begin
|
||||
for i:=0 to Graph.LevelCount-1 do begin
|
||||
Level:=Graph.Levels[i];
|
||||
for j:=0 to Level.Count-1 do begin
|
||||
Node:=Level.Nodes[j];
|
||||
for k:=0 to Node.OutEdgeCount-1 do begin
|
||||
Edge:=Node.OutEdges[k];
|
||||
TargetNode:=Edge.Target;
|
||||
NodeHighlighted:=(Node=MouseOverNode) or (TargetNode=MouseOverNode);
|
||||
if NodeHighlighted<>Highlighted then continue;
|
||||
if TargetNode.Level.Index>Level.Index then begin
|
||||
// normal dependency
|
||||
if NodeHighlighted then
|
||||
Canvas.Pen.Color:=clGray
|
||||
else
|
||||
Canvas.Pen.Color:=clSilver;
|
||||
Canvas.Line(Level.DrawPosition+NodeWidth, Node.DrawCenter,
|
||||
TargetNode.Level.DrawPosition, TargetNode.DrawCenter);
|
||||
end else begin
|
||||
// cycle dependency
|
||||
Canvas.Pen.Color:=clRed;
|
||||
Canvas.Line(Level.DrawPosition, Node.DrawCenter,
|
||||
TargetNode.Level.DrawPosition+NodeWidth, TargetNode.DrawCenter);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TCustomLvlGraphControl.DrawNodes;
|
||||
var
|
||||
i: Integer;
|
||||
Level: TLvlGraphLevel;
|
||||
j: Integer;
|
||||
Node: TLvlGraphNode;
|
||||
begin
|
||||
Canvas.Brush.Style:=bsSolid;
|
||||
for i:=0 to Graph.LevelCount-1 do begin
|
||||
Level:=Graph.Levels[i];
|
||||
for j:=0 to Level.Count-1 do begin
|
||||
Node:=Level.Nodes[j];
|
||||
//debugln(['TCustomLvlGraphControl.Paint ',Node.Caption,' ',dbgs(FPColorToTColor(Node.Color)),' Level.DrawPosition=',Level.DrawPosition,' Node.DrawPosition=',Node.DrawPosition,' ',Node.DrawPositionEnd]);
|
||||
Canvas.Brush.Color:=FPColorToTColor(Node.Color);
|
||||
Canvas.Pen.Color:=Darker(Canvas.Brush.Color);
|
||||
Canvas.Rectangle(Level.DrawPosition, Node.DrawPosition,
|
||||
Level.DrawPosition+NodeWidth, Node.DrawPositionEnd);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TCustomLvlGraphControl.SetOptions(AValue: TLvlGraphCtrlOptions);
|
||||
begin
|
||||
if FOptions=AValue then Exit;
|
||||
@ -766,10 +847,7 @@ var
|
||||
Level: TLvlGraphLevel;
|
||||
j: Integer;
|
||||
Node: TLvlGraphNode;
|
||||
k: Integer;
|
||||
Edge: TLvlGraphEdge;
|
||||
begin
|
||||
debugln(['TCustomLvlGraphControl.Paint ']);
|
||||
inherited Paint;
|
||||
|
||||
Canvas.Font.Assign(Font);
|
||||
@ -797,41 +875,10 @@ begin
|
||||
Canvas.TextOut((ClientWidth-w) div 2,round(0.25*TxtH),Caption);
|
||||
end;
|
||||
|
||||
// draw edges
|
||||
for i:=0 to Graph.LevelCount-1 do begin
|
||||
Level:=Graph.Levels[i];
|
||||
for j:=0 to Level.Count-1 do begin
|
||||
Node:=Level.Nodes[j];
|
||||
for k:=0 to Node.OutEdgeCount-1 do begin
|
||||
Edge:=Node.OutEdges[k];
|
||||
if Edge.Target.Level.Index>Level.Index then begin
|
||||
// normal dependency
|
||||
Canvas.Pen.Color:=clSilver;
|
||||
Canvas.Line(Level.DrawPosition+NodeWidth,Node.DrawCenter,
|
||||
Edge.Target.Level.DrawPosition,Edge.Target.DrawCenter);
|
||||
end else begin
|
||||
// cycle dependency
|
||||
Canvas.Pen.Color:=clRed;
|
||||
Canvas.Line(Level.DrawPosition,Node.DrawCenter,
|
||||
Edge.Target.Level.DrawPosition+NodeWidth,Edge.Target.DrawCenter);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
// draw nodes
|
||||
Canvas.Brush.Style:=bsSolid;
|
||||
for i:=0 to Graph.LevelCount-1 do begin
|
||||
Level:=Graph.Levels[i];
|
||||
for j:=0 to Level.Count-1 do begin
|
||||
Node:=Level.Nodes[j];
|
||||
//debugln(['TCustomLvlGraphControl.Paint ',Node.Caption,' ',dbgs(FPColorToTColor(Node.Color)),' Level.DrawPosition=',Level.DrawPosition,' Node.DrawPosition=',Node.DrawPosition,' ',Node.DrawPositionEnd]);
|
||||
Canvas.Brush.Color:=FPColorToTColor(Node.Color);
|
||||
Canvas.Pen.Color:=Darker(Canvas.Brush.Color);
|
||||
Canvas.Rectangle(Level.DrawPosition,Node.DrawPosition,
|
||||
Level.DrawPosition+NodeWidth,Node.DrawPositionEnd);
|
||||
end;
|
||||
end;
|
||||
// draw edges and nodes
|
||||
DrawEdges(false); // draw normal edges
|
||||
DrawEdges(true); // draw highlighted edges
|
||||
DrawNodes;
|
||||
|
||||
// draw captions
|
||||
Canvas.Brush.Style:=bsClear;
|
||||
@ -847,6 +894,12 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TCustomLvlGraphControl.MouseMove(Shift: TShiftState; X, Y: Integer);
|
||||
begin
|
||||
inherited MouseMove(Shift, X, Y);
|
||||
MouseOverNode:=GetNodeAt(X,Y);
|
||||
end;
|
||||
|
||||
constructor TCustomLvlGraphControl.Create(AOwner: TComponent);
|
||||
begin
|
||||
inherited Create(AOwner);
|
||||
@ -961,6 +1014,26 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TCustomLvlGraphControl.GetNodeAt(X, Y: integer): TLvlGraphNode;
|
||||
var
|
||||
l: Integer;
|
||||
Level: TLvlGraphLevel;
|
||||
n: Integer;
|
||||
Node: TLvlGraphNode;
|
||||
begin
|
||||
Result:=nil;
|
||||
// check in reverse painting order
|
||||
for l:=Graph.LevelCount-1 downto 0 do begin
|
||||
Level:=Graph.Levels[l];
|
||||
if (x<Level.DrawPosition) or (x>=Level.DrawPosition+NodeWidth) then continue;
|
||||
for n:=Level.Count-1 downto 0 do begin
|
||||
Node:=Level.Nodes[n];
|
||||
if (y<Node.DrawPosition) or (y>=Node.DrawPositionEnd) then continue;
|
||||
exit(Node);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
type
|
||||
|
||||
{ TGraphLevelerNode - used by TLvlGraph.UpdateLevels }
|
||||
|
Loading…
Reference in New Issue
Block a user