lazarus/ide/packages/idedebugger/debuggertreeview.pas
2022-01-26 19:28:39 +01:00

206 lines
5.4 KiB
ObjectPascal

unit DebuggerTreeView;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, laz.VirtualTrees, LMessages;
type
TDbgTreeNodeData = record
Item: TObject;
CachedText: Array of String;
end;
PDbgTreeNodeData = ^TDbgTreeNodeData;
{ TDbgTreeView }
TDbgTreeView = class(TLazVirtualStringTree)
private
function GetNodeItem(Node: PVirtualNode): TObject;
function GetNodeText(Node: PVirtualNode; AColumn: integer): String;
procedure SetNodeItem(Node: PVirtualNode; AValue: TObject);
procedure SetNodeText(Node: PVirtualNode; AColumn: integer; AValue: String);
protected
procedure ValidateNodeDataSize(var Size: Integer); override;
procedure DoFreeNode(Node: PVirtualNode); override;
function DetermineLineImageAndSelectLevel(Node: PVirtualNode;
var LineImage: TLineImage): Integer; override;
procedure HandleMouseDblClick(var Message: TLMMouse; const HitInfo: THitInfo); override;
procedure DoGetText(Node: PVirtualNode; Column: TColumnIndex;
TextType: TVSTTextType; var AText: String); override;
public
function GetNodeData(Node: PVirtualNode): PDbgTreeNodeData; reintroduce;
function GetFocusedNode(OnlySelected: Boolean = True): PVirtualNode;
function FocusedData(OnlySelected: Boolean = True): PDbgTreeNodeData;
function FocusedItem(OnlySelected: Boolean = True): TObject;
procedure SelectNode(Node: PVirtualNode; ASetFocus: boolean = True);
function FindNodeForItem(AnItem: TObject): PVirtualNode;
procedure DeleteNodeEx(Node: PVirtualNode; FreeItem: Boolean; Reindex: Boolean = True);
property NodeItem[Node: PVirtualNode]: TObject read GetNodeItem write SetNodeItem;
property NodeText[Node: PVirtualNode; AColumn: integer]: String read GetNodeText write SetNodeText;
end;
implementation
{ TDbgTreeView }
function TDbgTreeView.GetNodeItem(Node: PVirtualNode): TObject;
var
Data: PDbgTreeNodeData;
begin
Result := nil;
Data := GetNodeData(Node);
if Data <> nil then
Result := Data^.Item;
end;
function TDbgTreeView.GetNodeText(Node: PVirtualNode; AColumn: integer): String;
var
Data: PDbgTreeNodeData;
begin
Result := '';
Data := GetNodeData(Node);
if (Data <> nil) and (AColumn < Length(Data^.CachedText)) then
Result := Data^.CachedText[AColumn];
end;
procedure TDbgTreeView.SetNodeItem(Node: PVirtualNode; AValue: TObject);
var
Data: PDbgTreeNodeData;
begin
Data := GetNodeData(Node);
if Data <> nil then
Data^.Item := AValue;
end;
procedure TDbgTreeView.SetNodeText(Node: PVirtualNode; AColumn: integer;
AValue: String);
var
Data: PDbgTreeNodeData;
begin
Data := GetNodeData(Node);
if Data <> nil then begin
if AColumn >= Length(Data^.CachedText) then
SetLength(Data^.CachedText, AColumn + 1);
Data^.CachedText[AColumn] := AValue;
end;
end;
procedure TDbgTreeView.ValidateNodeDataSize(var Size: Integer);
begin
Size := SizeOf(TDbgTreeNodeData);
end;
procedure TDbgTreeView.DoFreeNode(Node: PVirtualNode);
begin
PDbgTreeNodeData(GetNodeData(Node))^ := Default(TDbgTreeNodeData);
inherited DoFreeNode(Node);
end;
function TDbgTreeView.DetermineLineImageAndSelectLevel(Node: PVirtualNode;
var LineImage: TLineImage): Integer;
begin
Result := inherited DetermineLineImageAndSelectLevel(Node, LineImage);
if Length(LineImage) > 1 then
LineImage[0] := ltNone
else
if (Length(LineImage) > 0) and (LineImage[0] <> ltNone) then
LineImage[0] := ltRight;
end;
procedure TDbgTreeView.HandleMouseDblClick(var Message: TLMMouse;
const HitInfo: THitInfo);
begin
inherited HandleMouseDblClick(Message, HitInfo);
if (HitInfo.HitNode = nil) and (HitInfo.HitColumn < 0) then
DoNodeDblClick(HitInfo);
end;
procedure TDbgTreeView.DoGetText(Node: PVirtualNode; Column: TColumnIndex;
TextType: TVSTTextType; var AText: String);
begin
if Assigned(OnGetText) then begin
inherited DoGetText(Node, Column, TextType, AText);
end
else begin
AText := NodeText[Node, Column];
end;
end;
function TDbgTreeView.GetNodeData(Node: PVirtualNode): PDbgTreeNodeData;
begin
Result := PDbgTreeNodeData(inherited GetNodeData(Node));
end;
function TDbgTreeView.GetFocusedNode(OnlySelected: Boolean): PVirtualNode;
begin
Result := FocusedNode;
if (Result = nil) or (OnlySelected and not Selected[Result]) then
Result := nil;
end;
function TDbgTreeView.FocusedData(OnlySelected: Boolean): PDbgTreeNodeData;
var
VNode: PVirtualNode;
begin
Result := nil;
VNode := FocusedNode;
if (VNode = nil) or (OnlySelected and not Selected[VNode]) then
exit;
Result := PDbgTreeNodeData(GetNodeData(VNode));
end;
function TDbgTreeView.FocusedItem(OnlySelected: Boolean): TObject;
var
Data: PDbgTreeNodeData;
begin
Result := nil;
Data := FocusedData(OnlySelected);
if Data <> nil then
Result := Data^.Item;
end;
procedure TDbgTreeView.SelectNode(Node: PVirtualNode; ASetFocus: boolean);
begin
ClearSelection;
FocusedNode := Node;
Selected[Node] := True;
end;
function TDbgTreeView.FindNodeForItem(AnItem: TObject): PVirtualNode;
var
VNode: PVirtualNode;
begin
for VNode in NoInitNodes do begin
if GetNodeItem(VNode) = AnItem then
exit(VNode);
end;
Result := nil;
end;
procedure TDbgTreeView.DeleteNodeEx(Node: PVirtualNode; FreeItem: Boolean;
Reindex: Boolean);
var
Item: TObject;
begin
if Node = nil then
exit;
Item := GetNodeItem(Node);
DeleteNode(Node, Reindex);
if FreeItem then
Item.Free;
end;
initialization
RegisterClass(TDbgTreeView);
end.