mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-19 23:49:36 +02:00
IdeDebugger: Rewrite DebugTreeView, embed control into data row, optimize updating (lock and defer) - Change array-navigation-bar to display with data row
This commit is contained in:
parent
927d0f8980
commit
6da483640e
@ -2,34 +2,47 @@ object ArrayNavigationBar: TArrayNavigationBar
|
||||
Left = 0
|
||||
Height = 24
|
||||
Top = 0
|
||||
Width = 457
|
||||
AutoSize = True
|
||||
Width = 436
|
||||
ClientHeight = 24
|
||||
ClientWidth = 457
|
||||
ClientWidth = 436
|
||||
TabOrder = 0
|
||||
DesignLeft = 518
|
||||
DesignTop = 777
|
||||
object btnArrayStart: TSpeedButton
|
||||
AnchorSideLeft.Control = Owner
|
||||
AnchorSideTop.Control = Owner
|
||||
AnchorSideBottom.Control = Owner
|
||||
AnchorSideBottom.Side = asrBottom
|
||||
Left = 0
|
||||
Height = 24
|
||||
Top = 0
|
||||
Width = 23
|
||||
Align = alLeft
|
||||
Anchors = [akTop, akLeft, akBottom]
|
||||
Caption = '|<'
|
||||
Flat = True
|
||||
OnClick = BtnChangePageClicked
|
||||
end
|
||||
object btnArrayFastDown: TSpeedButton
|
||||
AnchorSideLeft.Control = btnArrayStart
|
||||
AnchorSideLeft.Side = asrBottom
|
||||
AnchorSideTop.Control = Owner
|
||||
AnchorSideBottom.Control = Owner
|
||||
AnchorSideBottom.Side = asrBottom
|
||||
Left = 23
|
||||
Height = 24
|
||||
Top = 0
|
||||
Width = 23
|
||||
Align = alLeft
|
||||
Anchors = [akTop, akLeft, akBottom]
|
||||
Caption = '<<'
|
||||
Flat = True
|
||||
OnClick = BtnChangePageClicked
|
||||
end
|
||||
object edArrayStart: TLazIntegerEdit
|
||||
AnchorSideLeft.Control = btnArrayFastDown
|
||||
AnchorSideLeft.Side = asrBottom
|
||||
AnchorSideTop.Control = Owner
|
||||
AnchorSideBottom.Control = Owner
|
||||
AnchorSideBottom.Side = asrBottom
|
||||
Left = 46
|
||||
Height = 24
|
||||
Top = 0
|
||||
@ -37,52 +50,85 @@ object ArrayNavigationBar: TArrayNavigationBar
|
||||
Value = 0
|
||||
MinValue = -9223372036854775808
|
||||
MaxValue = 9223372036854775807
|
||||
Align = alLeft
|
||||
SetDecimalKeys = '#'
|
||||
HexIndicator = '$'
|
||||
ToggleHexKeys = '$x'
|
||||
OctIndicator = '&'
|
||||
ToggleOctKeys = '&'
|
||||
BinIndicator = '%'
|
||||
ToggleBinKeys = '%'
|
||||
Alignment = taRightJustify
|
||||
Anchors = [akTop, akLeft, akBottom]
|
||||
AutoSize = False
|
||||
TabOrder = 1
|
||||
Text = '0'
|
||||
OnEditingDone = edArrayStartEditingDone
|
||||
OnKeyDown = edArrayStartKeyDown
|
||||
end
|
||||
object btnArrayFastUp: TSpeedButton
|
||||
AnchorSideLeft.Control = edArrayStart
|
||||
AnchorSideLeft.Side = asrBottom
|
||||
AnchorSideTop.Control = Owner
|
||||
AnchorSideBottom.Control = Owner
|
||||
AnchorSideBottom.Side = asrBottom
|
||||
Left = 106
|
||||
Height = 24
|
||||
Top = 0
|
||||
Width = 23
|
||||
Align = alLeft
|
||||
Anchors = [akTop, akLeft, akBottom]
|
||||
Caption = '>>'
|
||||
Flat = True
|
||||
OnClick = BtnChangePageClicked
|
||||
end
|
||||
object btnArrayEnd: TSpeedButton
|
||||
AnchorSideLeft.Control = btnArrayFastUp
|
||||
AnchorSideLeft.Side = asrBottom
|
||||
AnchorSideTop.Control = Owner
|
||||
AnchorSideBottom.Control = Owner
|
||||
AnchorSideBottom.Side = asrBottom
|
||||
Left = 129
|
||||
Height = 24
|
||||
Top = 0
|
||||
Width = 23
|
||||
Align = alLeft
|
||||
Anchors = [akTop, akLeft, akBottom]
|
||||
Caption = '>|'
|
||||
Flat = True
|
||||
OnClick = BtnChangePageClicked
|
||||
end
|
||||
object Label1: TLabel
|
||||
AnchorSideLeft.Control = btnArrayEnd
|
||||
AnchorSideLeft.Side = asrBottom
|
||||
AnchorSideTop.Control = Owner
|
||||
AnchorSideBottom.Control = Owner
|
||||
AnchorSideBottom.Side = asrBottom
|
||||
Left = 152
|
||||
Height = 24
|
||||
Top = 0
|
||||
Width = 4
|
||||
Align = alLeft
|
||||
Anchors = [akTop, akLeft, akBottom]
|
||||
AutoSize = False
|
||||
end
|
||||
object btnArrayPageDec: TSpeedButton
|
||||
AnchorSideLeft.Control = Label1
|
||||
AnchorSideLeft.Side = asrBottom
|
||||
AnchorSideTop.Control = Owner
|
||||
AnchorSideBottom.Control = Owner
|
||||
AnchorSideBottom.Side = asrBottom
|
||||
Left = 156
|
||||
Height = 24
|
||||
Top = 0
|
||||
Width = 23
|
||||
Align = alLeft
|
||||
Anchors = [akTop, akLeft, akBottom]
|
||||
Caption = '-'
|
||||
Flat = True
|
||||
OnClick = BtnChangeSizeClicked
|
||||
end
|
||||
object edArrayPageSize: TLazIntegerEdit
|
||||
AnchorSideLeft.Control = btnArrayPageDec
|
||||
AnchorSideLeft.Side = asrBottom
|
||||
AnchorSideTop.Control = Owner
|
||||
AnchorSideBottom.Control = Owner
|
||||
AnchorSideBottom.Side = asrBottom
|
||||
Left = 179
|
||||
Height = 24
|
||||
Top = 0
|
||||
@ -90,38 +136,63 @@ object ArrayNavigationBar: TArrayNavigationBar
|
||||
Value = 10
|
||||
MinValue = 1
|
||||
MaxValue = 5000
|
||||
Align = alLeft
|
||||
SetDecimalKeys = '#'
|
||||
HexIndicator = '$'
|
||||
ToggleHexKeys = '$x'
|
||||
OctIndicator = '&'
|
||||
ToggleOctKeys = '&'
|
||||
BinIndicator = '%'
|
||||
ToggleBinKeys = '%'
|
||||
AllowMinus = False
|
||||
Alignment = taRightJustify
|
||||
Anchors = [akTop, akLeft, akBottom]
|
||||
AutoSize = False
|
||||
TabOrder = 0
|
||||
Text = '10'
|
||||
OnEditingDone = edArrayPageSizeEditingDone
|
||||
OnKeyDown = edArrayPageSizeKeyDown
|
||||
end
|
||||
object btnArrayPageInc: TSpeedButton
|
||||
AnchorSideLeft.Control = edArrayPageSize
|
||||
AnchorSideLeft.Side = asrBottom
|
||||
AnchorSideTop.Control = Owner
|
||||
AnchorSideBottom.Control = Owner
|
||||
AnchorSideBottom.Side = asrBottom
|
||||
Left = 219
|
||||
Height = 24
|
||||
Top = 0
|
||||
Width = 23
|
||||
Align = alLeft
|
||||
Anchors = [akTop, akLeft, akBottom]
|
||||
Caption = '+'
|
||||
Flat = True
|
||||
OnClick = BtnChangeSizeClicked
|
||||
end
|
||||
object lblBounds: TLabel
|
||||
AnchorSideLeft.Control = btnArrayPageInc
|
||||
AnchorSideLeft.Side = asrBottom
|
||||
AnchorSideTop.Control = Owner
|
||||
AnchorSideBottom.Control = Owner
|
||||
AnchorSideBottom.Side = asrBottom
|
||||
Left = 252
|
||||
Height = 24
|
||||
Top = 0
|
||||
Width = 1
|
||||
Align = alLeft
|
||||
Anchors = [akTop, akLeft, akBottom]
|
||||
BorderSpacing.Left = 10
|
||||
Layout = tlCenter
|
||||
Visible = False
|
||||
end
|
||||
object cbEnforceBound: TCheckBox
|
||||
AnchorSideLeft.Control = lblBounds
|
||||
AnchorSideLeft.Side = asrBottom
|
||||
AnchorSideTop.Control = Owner
|
||||
AnchorSideBottom.Control = Owner
|
||||
AnchorSideBottom.Side = asrBottom
|
||||
Left = 263
|
||||
Height = 24
|
||||
Top = 0
|
||||
Width = 106
|
||||
Align = alLeft
|
||||
Anchors = [akTop, akLeft, akBottom]
|
||||
BorderSpacing.Left = 10
|
||||
Caption = 'cbEnforceBound'
|
||||
Checked = True
|
||||
|
@ -5,8 +5,8 @@ unit ArrayNavigationFrame;
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, Math, Forms, Controls, Buttons, StdCtrls, LCLType, SpinEx, LazNumEdit,
|
||||
IDEImagesIntf, IdeDebuggerStringConstants;
|
||||
Classes, SysUtils, Math, Forms, Controls, Buttons, StdCtrls, LCLType, ExtCtrls, SpinEx,
|
||||
LazNumEdit, IDEImagesIntf, laz.VirtualTrees, IdeDebuggerStringConstants, DebuggerTreeView;
|
||||
|
||||
type
|
||||
|
||||
@ -44,6 +44,8 @@ type
|
||||
FOnSizeChanged: TNotifyEvent;
|
||||
FOwnerData: pointer;
|
||||
FShowBoundInfo: Boolean;
|
||||
FTree: TDbgTreeView;
|
||||
FNode: PVirtualNode;
|
||||
function GetIndex: int64;
|
||||
function GetIndexOffs: int64;
|
||||
function GetLimitedPageSize: int64;
|
||||
@ -56,9 +58,17 @@ type
|
||||
procedure SetShowBoundInfo(AValue: Boolean);
|
||||
procedure UpdateBoundsInfo;
|
||||
procedure DoOnSizeChanged;
|
||||
function EnforceBounds: boolean;
|
||||
procedure DoParentResized(Sender: TObject);
|
||||
protected
|
||||
procedure BoundsChanged; override;
|
||||
procedure VisibleChanged; override;
|
||||
procedure CreateWnd; override;
|
||||
procedure SetParent(AParent: TWinControl); override;
|
||||
public
|
||||
constructor Create(TheOwner: TComponent); override;
|
||||
procedure Loaded; override;
|
||||
constructor Create(TheOwner: TComponent; ATree: TDbgTreeView; ANode: PVirtualNode); reintroduce;
|
||||
destructor Destroy; override;
|
||||
function PreferredHeight: integer;
|
||||
property LowBound: int64 read FLowBound write SetLowBound;
|
||||
property HighBound: int64 read FHighBound write SetHighBound;
|
||||
property ShowBoundInfo: Boolean read FShowBoundInfo write SetShowBoundInfo;
|
||||
@ -98,7 +108,7 @@ begin
|
||||
edArrayStart.Value := FLowBound
|
||||
else
|
||||
if Sender = btnArrayFastDown then begin
|
||||
if (v < FLowBound) or (v > FHighBound) then
|
||||
if not EnforceBounds then
|
||||
edArrayStart.Value := edArrayStart.Value - edArrayPageSize.Value
|
||||
else
|
||||
edArrayStart.Value := max(edArrayStart.Value - edArrayPageSize.Value,
|
||||
@ -106,7 +116,7 @@ begin
|
||||
end
|
||||
else
|
||||
if Sender = btnArrayFastUp then begin
|
||||
if (v < FLowBound) or (v > FHighBound) then
|
||||
if not EnforceBounds then
|
||||
edArrayStart.Value := edArrayStart.Value + edArrayPageSize.Value
|
||||
else
|
||||
edArrayStart.Value := min(edArrayStart.Value + edArrayPageSize.Value,
|
||||
@ -167,9 +177,9 @@ begin
|
||||
end;
|
||||
VK_DOWN: begin
|
||||
if ssCtrl in Shift then
|
||||
edArrayPageSize.Value := Max(10, v - 5)
|
||||
edArrayPageSize.Value := Max(1, v - 5)
|
||||
else
|
||||
edArrayPageSize.Value := Max(10, v - 1);
|
||||
edArrayPageSize.Value := Max(1, v - 1);
|
||||
end;
|
||||
VK_PRIOR: begin
|
||||
if ssCtrl in Shift then
|
||||
@ -181,7 +191,10 @@ begin
|
||||
if ssCtrl in Shift then
|
||||
edArrayPageSize.Value := 10
|
||||
else
|
||||
edArrayPageSize.Value := Max(10, v - 10);
|
||||
if v > 10 then
|
||||
edArrayPageSize.Value := Max(10, v - 10)
|
||||
else
|
||||
edArrayPageSize.Value := 1;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
@ -219,7 +232,7 @@ begin
|
||||
if (not FHardLimits) and (ssAlt in Shift) then
|
||||
cbEnforceBound.Checked := False;
|
||||
|
||||
OutOfBnd := (not FHardLimits) and (not cbEnforceBound.Checked);
|
||||
OutOfBnd := not EnforceBounds;
|
||||
|
||||
v := edArrayStart.CurrentValue;
|
||||
PgSz := edArrayPageSize.CurrentValue;
|
||||
@ -272,7 +285,7 @@ var
|
||||
begin
|
||||
Result := edArrayPageSize.Value;
|
||||
idx := edArrayStart.Value;
|
||||
if (idx >= FLowBound) and (idx <= FHighBound) then
|
||||
if EnforceBounds then
|
||||
Result := Max(1, Min(Result, FHighBound + 1 - idx));
|
||||
end;
|
||||
|
||||
@ -307,10 +320,13 @@ begin
|
||||
edArrayPageSize.Value := AValue;
|
||||
end;
|
||||
|
||||
procedure TArrayNavigationBar.Loaded;
|
||||
function TArrayNavigationBar.PreferredHeight: integer;
|
||||
var
|
||||
w, h: Integer;
|
||||
begin
|
||||
inherited Loaded;
|
||||
Constraints.MinWidth := btnArrayPageInc.Left + btnArrayPageInc.Width;
|
||||
cbEnforceBound.GetPreferredSize(w, Result);
|
||||
edArrayStart.GetPreferredSize(w, h);
|
||||
Result := max(Result, h);
|
||||
end;
|
||||
|
||||
procedure TArrayNavigationBar.SetShowBoundInfo(AValue: Boolean);
|
||||
@ -324,7 +340,7 @@ end;
|
||||
|
||||
procedure TArrayNavigationBar.UpdateBoundsInfo;
|
||||
begin
|
||||
if FHardLimits or cbEnforceBound.Checked then begin
|
||||
if EnforceBounds then begin
|
||||
edArrayPageSize.Visible := FHighBound + 1 - FLowBound > edArrayPageSize.MinValue;
|
||||
btnArrayPageInc.Visible := FHighBound + 1 - FLowBound > edArrayPageSize.MinValue;
|
||||
btnArrayPageDec.Visible := FHighBound + 1 - FLowBound > edArrayPageSize.MinValue;
|
||||
@ -350,8 +366,89 @@ begin
|
||||
FOnSizeChanged(Self);
|
||||
end;
|
||||
|
||||
constructor TArrayNavigationBar.Create(TheOwner: TComponent);
|
||||
function TArrayNavigationBar.EnforceBounds: boolean;
|
||||
begin
|
||||
Result := FHardLimits or cbEnforceBound.Checked;
|
||||
end;
|
||||
|
||||
procedure TArrayNavigationBar.DoParentResized(Sender: TObject);
|
||||
begin
|
||||
if (edArrayStart = nil) or (Parent = nil) or (not HandleAllocated) or (not IsVisible) then
|
||||
exit;
|
||||
|
||||
if (edArrayStart.Left+edArrayStart.Width + Left < 1) or
|
||||
(edArrayStart.Left+ Left > Parent.ClientWidth - 1) or
|
||||
(edArrayStart.Top+Top > Parent.ClientHeight + FTree.Header.Height - 1) or
|
||||
(not Visible)
|
||||
then
|
||||
edArrayStart.BorderSpacing.Top := 1
|
||||
else
|
||||
edArrayStart.BorderSpacing.Top := 0;
|
||||
|
||||
if (edArrayPageSize.Left+edArrayPageSize.Width + Left < 1) or
|
||||
(edArrayPageSize.Left+ Left > Parent.ClientWidth - 1) or
|
||||
(edArrayPageSize.Top+Top > Parent.ClientHeight + FTree.Header.Height - 1) or
|
||||
(not Visible)
|
||||
then
|
||||
edArrayPageSize.BorderSpacing.Top := 1
|
||||
else
|
||||
edArrayPageSize.BorderSpacing.Top := 0;
|
||||
|
||||
if (cbEnforceBound.Left+cbEnforceBound.Width + Left < 1) or
|
||||
(cbEnforceBound.Left+ Left > Parent.ClientWidth - 1) or
|
||||
(cbEnforceBound.Top+Top > Parent.ClientHeight + FTree.Header.Height - 1) or
|
||||
(not Visible)
|
||||
then
|
||||
cbEnforceBound.BorderSpacing.Top := 1
|
||||
else
|
||||
cbEnforceBound.BorderSpacing.Top := 0;
|
||||
|
||||
end;
|
||||
|
||||
procedure TArrayNavigationBar.BoundsChanged;
|
||||
begin
|
||||
inherited BoundsChanged;
|
||||
if HandleAllocated and IsVisible then begin
|
||||
DoParentResized(nil);
|
||||
end;
|
||||
|
||||
//if btnToggle <> nil then
|
||||
// btnToggle.Width := btnToggle.Height;
|
||||
end;
|
||||
|
||||
procedure TArrayNavigationBar.VisibleChanged;
|
||||
begin
|
||||
inherited VisibleChanged;
|
||||
if HandleAllocated and IsVisible then begin
|
||||
FTree.NodeControlHeight[FNode] := Max(15, PreferredHeight);
|
||||
DoParentResized(nil);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TArrayNavigationBar.CreateWnd;
|
||||
begin
|
||||
inherited CreateWnd;
|
||||
FTree.NodeControlHeight[FNode] := Max(15, PreferredHeight);
|
||||
DoParentResized(nil);
|
||||
end;
|
||||
|
||||
procedure TArrayNavigationBar.SetParent(AParent: TWinControl);
|
||||
begin
|
||||
if (AParent = nil) and (Parent <> nil) then
|
||||
Parent.RemoveHandlerOnResize(@DoParentResized);
|
||||
inherited SetParent(AParent);
|
||||
if Parent <> nil then begin
|
||||
Parent.AddHandlerOnResize(@DoParentResized);
|
||||
if HandleAllocated and IsVisible then
|
||||
DoParentResized(nil);
|
||||
end;
|
||||
end;
|
||||
|
||||
constructor TArrayNavigationBar.Create(TheOwner: TComponent; ATree: TDbgTreeView;
|
||||
ANode: PVirtualNode);
|
||||
begin
|
||||
FTree := ATree;
|
||||
FNode := ANode;
|
||||
inherited Create(TheOwner);
|
||||
Name := '';
|
||||
Constraints.MinWidth := btnArrayPageInc.Left + btnArrayPageInc.Width;
|
||||
@ -388,5 +485,12 @@ begin
|
||||
cbEnforceBound.Caption := arrnavEnforceBounds;
|
||||
end;
|
||||
|
||||
destructor TArrayNavigationBar.Destroy;
|
||||
begin
|
||||
if (Parent <> nil) then
|
||||
Parent.RemoveHandlerOnResize(@DoParentResized);
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
|
@ -49,30 +49,28 @@ object BreakpointGroupFrame: TBreakpointGroupFrame
|
||||
Caption = 'ToolButtonDivider1'
|
||||
Style = tbsDivider
|
||||
end
|
||||
object StaticText1: TStaticText
|
||||
object StaticText1: TLabel
|
||||
Left = 60
|
||||
Height = 16
|
||||
Height = 15
|
||||
Top = 2
|
||||
Width = 57
|
||||
AutoSize = True
|
||||
Width = 56
|
||||
BorderSpacing.Left = 5
|
||||
BorderSpacing.Right = 5
|
||||
Caption = 'StaticText1'
|
||||
TabOrder = 0
|
||||
Layout = tlCenter
|
||||
OnDragDrop = FrameDragDrop
|
||||
OnDragOver = FrameDragOver
|
||||
OnMouseDown = StaticText1MouseDown
|
||||
end
|
||||
object StaticText2: TStaticText
|
||||
Left = 117
|
||||
Height = 16
|
||||
object StaticText2: TLabel
|
||||
Left = 116
|
||||
Height = 15
|
||||
Top = 2
|
||||
Width = 57
|
||||
AutoSize = True
|
||||
Width = 56
|
||||
BorderSpacing.Left = 5
|
||||
BorderSpacing.Right = 5
|
||||
Caption = 'StaticText2'
|
||||
TabOrder = 1
|
||||
Layout = tlCenter
|
||||
OnDragDrop = FrameDragDrop
|
||||
OnDragOver = FrameDragOver
|
||||
OnMouseDown = StaticText1MouseDown
|
||||
@ -80,7 +78,6 @@ object BreakpointGroupFrame: TBreakpointGroupFrame
|
||||
end
|
||||
object Panel1: TPanel
|
||||
AnchorSideTop.Control = ToolBar1
|
||||
AnchorSideRight.Control = ToolBar1
|
||||
AnchorSideRight.Side = asrBottom
|
||||
AnchorSideBottom.Control = ToolBar1
|
||||
AnchorSideBottom.Side = asrBottom
|
||||
@ -88,10 +85,9 @@ object BreakpointGroupFrame: TBreakpointGroupFrame
|
||||
Height = 22
|
||||
Top = 1
|
||||
Width = 23
|
||||
Anchors = [akTop, akRight, akBottom]
|
||||
Anchors = [akTop, akLeft, akBottom]
|
||||
AutoSize = True
|
||||
BorderSpacing.Top = 1
|
||||
BorderSpacing.Right = 2
|
||||
BorderSpacing.Bottom = 2
|
||||
BevelOuter = bvNone
|
||||
ClientHeight = 22
|
||||
@ -101,13 +97,12 @@ object BreakpointGroupFrame: TBreakpointGroupFrame
|
||||
TabOrder = 1
|
||||
object BtnDelete: TSpeedButton
|
||||
AnchorSideTop.Control = Panel1
|
||||
AnchorSideBottom.Control = Panel1
|
||||
AnchorSideTop.Side = asrCenter
|
||||
AnchorSideBottom.Side = asrBottom
|
||||
Left = 0
|
||||
Height = 22
|
||||
Top = 0
|
||||
Width = 23
|
||||
Anchors = [akTop, akLeft, akBottom]
|
||||
OnClick = BtnDeleteClick
|
||||
end
|
||||
end
|
||||
|
@ -29,8 +29,8 @@ type
|
||||
TBreakpointGroupFrame = class(TFrame)
|
||||
BtnDelete: TSpeedButton;
|
||||
Panel1: TPanel;
|
||||
StaticText1: TStaticText;
|
||||
StaticText2: TStaticText;
|
||||
StaticText1: TLabel;
|
||||
StaticText2: TLabel;
|
||||
ToolBar1: TToolBar;
|
||||
ToolButtonEnableAll: TToolButton;
|
||||
ToolButtonDisableAll: TToolButton;
|
||||
@ -53,14 +53,15 @@ type
|
||||
FNode: PVirtualNode;
|
||||
FBrkGroup: TIDEBreakPointGroup;
|
||||
procedure DoBrkGroupFreed(Sender: TObject);
|
||||
procedure DoParentResized(Sender: TObject);
|
||||
function GetCount: Integer;
|
||||
function GetName: String;
|
||||
function GetVisible: boolean;
|
||||
procedure SetNodeVisible(AValue: boolean);
|
||||
protected
|
||||
procedure SetVisible(Value: Boolean); reintroduce;
|
||||
procedure VisibleChanged; override;
|
||||
procedure BoundsChanged; override;
|
||||
procedure CreateWnd; override;
|
||||
procedure SetParent(AParent: TWinControl); override;
|
||||
public
|
||||
constructor Create(TheOwner: TBreakPointsDlgBase; ATree: TDbgTreeView; ANode: PVirtualNode;
|
||||
ABrkGroup: TIDEBreakPointGroup;
|
||||
@ -70,7 +71,7 @@ type
|
||||
procedure UpdateButtons;
|
||||
function Compare(AnOther: TBreakpointGroupFrame): integer;
|
||||
|
||||
property Visible: boolean read GetVisible write SetVisible;
|
||||
property NodeVisible: boolean write SetNodeVisible;
|
||||
property GroupKind: TBreakpointGroupFrameKind read FGroupKind;
|
||||
property BrkGroup: TIDEBreakPointGroup read FBrkGroup;
|
||||
property Tree: TDbgTreeView read FTree;
|
||||
@ -186,8 +187,8 @@ begin
|
||||
|
||||
if (Source = FTree) and (FTree.SelectedCount > 0) then begin
|
||||
for VNode in FTree.SelectedNodes(True) do begin
|
||||
if Brk = nil then Continue; // Header row selected
|
||||
Brk := TIDEBreakPoint(FTree.NodeItem[VNode]);
|
||||
if Brk = nil then Continue; // Header row selected
|
||||
Brk.Group := NewGroup;
|
||||
end;
|
||||
end;
|
||||
@ -252,46 +253,57 @@ begin
|
||||
UpdateButtons;
|
||||
end;
|
||||
|
||||
procedure TBreakpointGroupFrame.DoParentResized(Sender: TObject);
|
||||
begin
|
||||
if (Panel1 <> nil) and HandleAllocated and IsVisible and (Parent <> nil) then
|
||||
Panel1.Left := Min(Parent.ClientWidth - Left, ClientWidth) - Panel1.Width - 1;
|
||||
end;
|
||||
|
||||
function TBreakpointGroupFrame.GetName: String;
|
||||
begin
|
||||
Result := StaticText1.Caption;
|
||||
end;
|
||||
|
||||
function TBreakpointGroupFrame.GetVisible: boolean;
|
||||
procedure TBreakpointGroupFrame.SetNodeVisible(AValue: boolean);
|
||||
begin
|
||||
Result := inherited Visible;
|
||||
end;
|
||||
|
||||
procedure TBreakpointGroupFrame.SetVisible(Value: Boolean);
|
||||
begin
|
||||
if (Value = Visible) or
|
||||
(Value and (FGroupKind = bgfAbandoned))
|
||||
then
|
||||
exit;
|
||||
|
||||
if not Value then
|
||||
inherited SetVisible(Value);
|
||||
FTree.IsVisible[FNode] := Value;
|
||||
FTree.IsVisible[FNode] := AValue;
|
||||
end;
|
||||
|
||||
procedure TBreakpointGroupFrame.VisibleChanged;
|
||||
begin
|
||||
inherited VisibleChanged;
|
||||
if HandleAllocated and IsVisible then
|
||||
FTree.NodeHeight[FNode] := Max(15, ToolBar1.Height);
|
||||
if HandleAllocated and IsVisible then begin
|
||||
FTree.NodeControlHeight[FNode] := Max(15, ToolBar1.Height);
|
||||
DoParentResized(nil);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TBreakpointGroupFrame.BoundsChanged;
|
||||
begin
|
||||
inherited BoundsChanged;
|
||||
if HandleAllocated and IsVisible then
|
||||
FTree.NodeHeight[FNode] := Max(15, ToolBar1.Height);
|
||||
if HandleAllocated and IsVisible then begin
|
||||
FTree.NodeControlHeight[FNode] := Max(15, ToolBar1.Height);
|
||||
DoParentResized(nil);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TBreakpointGroupFrame.CreateWnd;
|
||||
begin
|
||||
inherited CreateWnd;
|
||||
FTree.NodeHeight[FNode] := Max(15, ToolBar1.Height);
|
||||
FTree.NodeControlHeight[FNode] := Max(15, ToolBar1.Height);
|
||||
DoParentResized(nil);
|
||||
end;
|
||||
|
||||
procedure TBreakpointGroupFrame.SetParent(AParent: TWinControl);
|
||||
begin
|
||||
if (AParent = nil) and (Parent <> nil) then
|
||||
Parent.RemoveHandlerOnResize(@DoParentResized);
|
||||
inherited SetParent(AParent);
|
||||
if Parent <> nil then begin
|
||||
Parent.AddHandlerOnResize(@DoParentResized);
|
||||
if HandleAllocated and IsVisible then
|
||||
DoParentResized(nil);
|
||||
end;
|
||||
end;
|
||||
|
||||
constructor TBreakpointGroupFrame.Create(TheOwner: TBreakPointsDlgBase;
|
||||
@ -330,6 +342,8 @@ end;
|
||||
|
||||
destructor TBreakpointGroupFrame.Destroy;
|
||||
begin
|
||||
if (Parent <> nil) then
|
||||
Parent.RemoveHandlerOnResize(@DoParentResized);
|
||||
if FBrkGroup <> nil then
|
||||
FBrkGroup.RemoveFreeNotification(@DoBrkGroupFreed);
|
||||
inherited Destroy;
|
||||
|
@ -45,39 +45,39 @@ object BreakpointsDlg: TBreakpointsDlg
|
||||
Action = actDeleteSelected
|
||||
end
|
||||
object ToolSep1: TToolButton
|
||||
Left = 131
|
||||
Left = 134
|
||||
Height = 22
|
||||
Top = 2
|
||||
Style = tbsDivider
|
||||
end
|
||||
object ToolButtonEnableAll: TToolButton
|
||||
Left = 146
|
||||
Left = 139
|
||||
Top = 2
|
||||
Action = actEnableAll
|
||||
end
|
||||
object ToolButtonDisableAll: TToolButton
|
||||
Left = 169
|
||||
Left = 162
|
||||
Top = 2
|
||||
Action = actDisableAll
|
||||
end
|
||||
object ToolButtonTrashAll: TToolButton
|
||||
Left = 108
|
||||
Left = 111
|
||||
Top = 2
|
||||
Action = actDeleteAll
|
||||
end
|
||||
object ToolSep2: TToolButton
|
||||
Left = 192
|
||||
Left = 185
|
||||
Height = 22
|
||||
Top = 2
|
||||
Style = tbsDivider
|
||||
end
|
||||
object ToolButtonProperties: TToolButton
|
||||
Left = 197
|
||||
Left = 190
|
||||
Top = 2
|
||||
Action = actProperties
|
||||
end
|
||||
object tbGroupByBrkGroup: TToolButton
|
||||
Left = 220
|
||||
Left = 213
|
||||
Top = 2
|
||||
Caption = 'Grp'
|
||||
Style = tbsCheck
|
||||
@ -136,7 +136,7 @@ object BreakpointsDlg: TBreakpointsDlg
|
||||
Text = 'Group'
|
||||
Width = 80
|
||||
end>
|
||||
Header.Options = [hoColumnResize, hoDrag, hoShowSortGlyphs, hoVisible]
|
||||
Header.Options = [hoColumnResize, hoShowSortGlyphs, hoVisible]
|
||||
PopupMenu = mnuPopup
|
||||
TabOrder = 1
|
||||
TreeOptions.AutoOptions = [toAutoScroll, toAutoScrollOnExpand, toAutoSort, toAutoTristateTracking, toAutoDeleteMovedNodes, toAutoChangeScale]
|
||||
|
@ -435,12 +435,12 @@ begin
|
||||
|
||||
PVNode := tvBreakPoints.AddChild(nil, nil);
|
||||
FUngroupedHeader := TBreakpointGroupFrame.Create(Self, tvBreakPoints, PVNode, nil);
|
||||
FUngroupedHeader.Visible := tbGroupByBrkGroup.Down;
|
||||
FUngroupedHeader.NodeVisible:= tbGroupByBrkGroup.Down;
|
||||
tvBreakPoints.NodeControl[PVNode] := FUngroupedHeader;
|
||||
|
||||
PVNode := tvBreakPoints.AddChild(nil, nil);
|
||||
FAddGroupedHeader := TBreakpointGroupFrame.Create(Self, tvBreakPoints, PVNode, nil, bgfAddNewGroup);
|
||||
FAddGroupedHeader.Visible := False;
|
||||
FAddGroupedHeader.NodeVisible := False;
|
||||
tvBreakPoints.NodeControl[PVNode] := FAddGroupedHeader;
|
||||
finally
|
||||
EndUpdate;
|
||||
@ -473,7 +473,7 @@ begin
|
||||
try
|
||||
Result := tvBreakPoints.AddChild(nil, nil);
|
||||
GrpHeader := TBreakpointGroupFrame.Create(Self, tvBreakPoints, Result, ABrkGroup);
|
||||
GrpHeader.Visible := tbGroupByBrkGroup.Down;
|
||||
GrpHeader.NodeVisible := tbGroupByBrkGroup.Down;
|
||||
GrpHeader.OnDeleteGroup := @DoGroupDeleteBtnClicked;
|
||||
tvBreakPoints.NodeControl[Result] := GrpHeader;
|
||||
finally
|
||||
@ -1189,7 +1189,7 @@ begin
|
||||
AcceptGroupHeaderDrop(TBreakpointGroupFrame(TToolBar(Source).Owner), TargetNd);
|
||||
end;
|
||||
|
||||
FAddGroupedHeader.Visible := False;
|
||||
FAddGroupedHeader.NodeVisible:= False;
|
||||
FDragSource := False;
|
||||
finally
|
||||
EndUpdate;
|
||||
@ -1206,7 +1206,7 @@ var
|
||||
begin
|
||||
Accept := False;
|
||||
if FDragSource and tbGroupByBrkGroup.Down then
|
||||
FAddGroupedHeader.Visible := True;
|
||||
FAddGroupedHeader.NodeVisible := True;
|
||||
|
||||
TargetNd := tvBreakPoints.GetNodeAt(Pt);
|
||||
if (TargetNd <> nil) and (Source = tvBreakPoints) and (tvBreakPoints.SelectedCount > 0) then begin
|
||||
@ -1251,7 +1251,7 @@ end;
|
||||
procedure TBreakPointsDlg.tvBreakPointsEndDrag(Sender, Target: TObject; X,
|
||||
Y: Integer);
|
||||
begin
|
||||
FAddGroupedHeader.Visible := False;
|
||||
FAddGroupedHeader.NodeVisible := False;
|
||||
FDragSource := False;
|
||||
end;
|
||||
|
||||
@ -1551,7 +1551,7 @@ begin
|
||||
LastAbandoned := nil;
|
||||
end;
|
||||
if GrpHeader.GroupKind in [bgfGroup, bgfUngrouped] then
|
||||
GrpHeader.Visible := tbGroupByBrkGroup.Down;
|
||||
GrpHeader.NodeVisible := tbGroupByBrkGroup.Down;
|
||||
if GrpHeader.GroupKind = bgfAbandoned then
|
||||
LastAbandoned := VNode;
|
||||
end
|
||||
|
@ -28,6 +28,7 @@ type
|
||||
FTreeView: TDbgTreeView;
|
||||
FExpandingWatchAbleResult: TObject;
|
||||
|
||||
procedure TreeViewCollapsed(Sender: TBaseVirtualTree; Node: PVirtualNode);
|
||||
procedure TreeViewExpanded(Sender: TBaseVirtualTree; Node: PVirtualNode);
|
||||
procedure TreeViewInitChildren(Sender: TBaseVirtualTree;
|
||||
Node: PVirtualNode; var ChildCount: Cardinal);
|
||||
@ -82,12 +83,9 @@ begin
|
||||
FTreeView.OnItemRemoved := nil;
|
||||
FTreeView.NodeItem[VNode] := nil;
|
||||
|
||||
if FTreeView.ChildCount[VNode] > 0 then begin
|
||||
VNode := FTreeView.GetFirstVisible(VNode);
|
||||
Nav := FTreeView.NodeControl[VNode];
|
||||
if (Nav <> nil) and (Nav is TArrayNavigationBar) then
|
||||
TArrayNavigationBar(Nav).OwnerData := nil;
|
||||
end;
|
||||
Nav := FTreeView.NodeControl[VNode];
|
||||
if (Nav <> nil) and (Nav is TArrayNavigationBar) then
|
||||
TArrayNavigationBar(Nav).OwnerData := nil;
|
||||
|
||||
FTreeView.OnItemRemoved := @DoItemRemovedFromView;
|
||||
end;
|
||||
@ -154,27 +152,32 @@ begin
|
||||
exit;
|
||||
end;
|
||||
|
||||
ResData := AWatchAbleResult.ResultData;
|
||||
while (ResData <> nil) and (ResData.ValueKind = rdkPointerVal) do
|
||||
ResData := ResData.DerefData;
|
||||
FTreeView.BeginUpdate;
|
||||
try
|
||||
ResData := AWatchAbleResult.ResultData;
|
||||
while (ResData <> nil) and (ResData.ValueKind = rdkPointerVal) do
|
||||
ResData := ResData.DerefData;
|
||||
|
||||
if (ResData <> nil) and
|
||||
(ResData.FieldCount > 0) and
|
||||
(ResData.ValueKind <> rdkConvertRes)
|
||||
then
|
||||
DoUpdateStructSubItems(AWatchAble, AWatchAbleResult, AVNode, ChildCount)
|
||||
else
|
||||
if (ResData <> nil) and
|
||||
//(ResData.ValueKind = rdkArray) and
|
||||
(ResData.ArrayLength > 0)
|
||||
then
|
||||
DoUpdateArraySubItems(AWatchAble, AWatchAbleResult, AVNode, ChildCount)
|
||||
else
|
||||
if (AWatchAbleResult.TypeInfo <> nil) and (AWatchAbleResult.TypeInfo.Fields <> nil) then
|
||||
// Old Interface
|
||||
DoUpdateOldSubItems(AWatchAble, AWatchAbleResult, AVNode, ChildCount);
|
||||
if (ResData <> nil) and
|
||||
(ResData.FieldCount > 0) and
|
||||
(ResData.ValueKind <> rdkConvertRes)
|
||||
then
|
||||
DoUpdateStructSubItems(AWatchAble, AWatchAbleResult, AVNode, ChildCount)
|
||||
else
|
||||
if (ResData <> nil) and
|
||||
//(ResData.ValueKind = rdkArray) and
|
||||
(ResData.ArrayLength > 0)
|
||||
then
|
||||
DoUpdateArraySubItems(AWatchAble, AWatchAbleResult, AVNode, ChildCount)
|
||||
else
|
||||
if (AWatchAbleResult.TypeInfo <> nil) and (AWatchAbleResult.TypeInfo.Fields <> nil) then
|
||||
// Old Interface
|
||||
DoUpdateOldSubItems(AWatchAble, AWatchAbleResult, AVNode, ChildCount);
|
||||
|
||||
FTreeView.ChildCount[AVNode] := ChildCount;
|
||||
FTreeView.ChildCount[AVNode] := ChildCount;
|
||||
finally
|
||||
FTreeView.EndUpdate;
|
||||
end;
|
||||
FTreeView.Invalidate;
|
||||
end;
|
||||
|
||||
@ -204,15 +207,9 @@ begin
|
||||
if (ResData.ValueKind <> rdkArray) or (TotalCount = 0) then
|
||||
TotalCount := ResData.Count;
|
||||
|
||||
ExistingNode := FTreeView.GetFirstChildNoInit(AVNode);
|
||||
if ExistingNode = nil then
|
||||
ExistingNode := FTreeView.AddChild(AVNode, nil)
|
||||
else
|
||||
FTreeView.NodeItem[ExistingNode] := nil;
|
||||
|
||||
Nav := TArrayNavigationBar(FTreeView.NodeControl[ExistingNode]);
|
||||
Nav := TArrayNavigationBar(FTreeView.NodeControl[AVNode]);
|
||||
if Nav = nil then begin
|
||||
Nav := TArrayNavigationBar.Create(nil);
|
||||
Nav := TArrayNavigationBar.Create(nil, FTreeView, AVNode);
|
||||
Nav.ParentColor := False;
|
||||
Nav.ParentBackground := False;
|
||||
Nav.Color := FTreeView.Colors.BackGroundColor;
|
||||
@ -224,9 +221,8 @@ begin
|
||||
Nav.OnIndexChanged := @WatchNavChanged;
|
||||
Nav.OnPageSize := @WatchNavChanged;
|
||||
Nav.HardLimits := not(ResData.ValueKind = rdkArray);
|
||||
FTreeView.NodeControl[ExistingNode] := Nav;
|
||||
FTreeView.NodeText[ExistingNode, 0] := ' ';
|
||||
FTreeView.NodeText[ExistingNode, 1] := ' ';
|
||||
FTreeView.NodeControl[AVNode] := Nav;
|
||||
FTreeView.NodeControlHeight[AVNode] := Nav.PreferredHeight;
|
||||
end
|
||||
else begin
|
||||
ForceIdx := (Nav.LowBound <> ResData.LowBound) or
|
||||
@ -239,10 +235,17 @@ begin
|
||||
Nav.Index := ResData.LowBound;
|
||||
Nav.HardLimits := not(ResData.ValueKind = rdkArray);
|
||||
end;
|
||||
FTreeView.NodeControlVisible[AVNode] := True;
|
||||
Nav.OwnerData := AWatchAble;
|
||||
ChildCount := Nav.LimitedPageSize;
|
||||
|
||||
ExistingNode := FTreeView.GetNextSiblingNoInit(ExistingNode);
|
||||
if ChildCount > 0 then begin
|
||||
ExistingNode := FTreeView.GetFirstChildNoInit(AVNode);
|
||||
if ExistingNode = nil then
|
||||
ExistingNode := FTreeView.AddChild(AVNode, nil)
|
||||
else
|
||||
FTreeView.NodeItem[ExistingNode] := nil;
|
||||
end;
|
||||
|
||||
Offs := Nav.Index;
|
||||
for i := 0 to ChildCount - 1 do begin
|
||||
@ -266,8 +269,6 @@ begin
|
||||
UpdateWatchData(NewWatchAble, nd, nil, True);
|
||||
end;
|
||||
|
||||
inc(ChildCount); // for the nav row
|
||||
|
||||
KeepCnt := Nav.PageSize;
|
||||
KeepBelow := KeepCnt;
|
||||
KeepCnt := max(max(50, KeepCnt+10),
|
||||
@ -298,8 +299,6 @@ begin
|
||||
exit;
|
||||
|
||||
ExistingNode := FTreeView.GetFirstChildNoInit(AVNode);
|
||||
if ExistingNode <> nil then
|
||||
FTreeView.NodeControl[ExistingNode] := nil;
|
||||
|
||||
AnchClass := '';
|
||||
if ResData.StructType <> dstRecord then
|
||||
@ -375,6 +374,9 @@ procedure TDbgTreeViewWatchDataMgr.TreeViewExpanded(Sender: TBaseVirtualTree;
|
||||
var
|
||||
AWatchAble: TObject;
|
||||
begin
|
||||
if TArrayNavigationBar(FTreeView.NodeControl[Node]) <> nil then
|
||||
FTreeView.NodeControlVisible[Node] := True;
|
||||
|
||||
Node := FTreeView.GetFirstChildNoInit(Node);
|
||||
while Node <> nil do begin
|
||||
AWatchAble := FTreeView.NodeItem[Node];
|
||||
@ -384,6 +386,11 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TDbgTreeViewWatchDataMgr.TreeViewCollapsed(Sender: TBaseVirtualTree; Node: PVirtualNode);
|
||||
begin
|
||||
FTreeView.NodeControlVisible[Node] := False;
|
||||
end;
|
||||
|
||||
procedure TDbgTreeViewWatchDataMgr.TreeViewInitChildren(
|
||||
Sender: TBaseVirtualTree; Node: PVirtualNode; var ChildCount: Cardinal);
|
||||
var
|
||||
@ -400,7 +407,9 @@ begin
|
||||
end;
|
||||
|
||||
FExpandingWatchAbleResult := AWatchAble;
|
||||
FTreeView.BeginUpdate;
|
||||
UpdateSubItemsLocked(AWatchAble, AWatchAbleResult, Node, ChildCount);
|
||||
FTreeView.EndUpdate;
|
||||
FExpandingWatchAbleResult := nil;
|
||||
end;
|
||||
|
||||
@ -419,6 +428,7 @@ begin
|
||||
FTreeView := ATreeView;
|
||||
FTreeView.OnItemRemoved := @DoItemRemovedFromView;
|
||||
FTreeView.OnExpanded := @TreeViewExpanded;
|
||||
FTreeView.OnCollapsed := @TreeViewCollapsed;
|
||||
FTreeView.OnInitChildren := @TreeViewInitChildren;
|
||||
end;
|
||||
|
||||
@ -428,22 +438,27 @@ begin
|
||||
if AWatchAble = nil then
|
||||
exit;
|
||||
|
||||
if (AVNode <> nil) then begin
|
||||
FTreeView.NodeItem[AVNode] := AWatchAble;
|
||||
FTreeView.SelectNode(AVNode);
|
||||
(AWatchAble as IFreeNotifyingIntf).AddFreeNotification(@DoWatchAbleFreed);
|
||||
end
|
||||
else begin
|
||||
AVNode := FTreeView.FindNodeForItem(AWatchAble);
|
||||
if AVNode = nil then begin
|
||||
AVNode := FTreeView.AddChild(nil, AWatchAble);
|
||||
FTreeView.BeginUpdate;
|
||||
try
|
||||
if (AVNode <> nil) then begin
|
||||
FTreeView.NodeItem[AVNode] := AWatchAble;
|
||||
FTreeView.SelectNode(AVNode);
|
||||
(AWatchAble as IFreeNotifyingIntf).AddFreeNotification(@DoWatchAbleFreed);
|
||||
end
|
||||
else begin
|
||||
AVNode := FTreeView.FindNodeForItem(AWatchAble);
|
||||
if AVNode = nil then begin
|
||||
AVNode := FTreeView.AddChild(nil, AWatchAble);
|
||||
FTreeView.SelectNode(AVNode);
|
||||
(AWatchAble as IFreeNotifyingIntf).AddFreeNotification(@DoWatchAbleFreed);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
Result := AVNode;
|
||||
Result := AVNode;
|
||||
|
||||
UpdateWatchData(AWatchAble, AVNode, AWatchAbleResult);
|
||||
UpdateWatchData(AWatchAble, AVNode, AWatchAbleResult);
|
||||
finally
|
||||
FTreeView.EndUpdate;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TDbgTreeViewWatchDataMgr.UpdateWatchData(AWatchAble: TObject;
|
||||
@ -461,48 +476,55 @@ begin
|
||||
if AWatchAbleResult = nil then
|
||||
AWatchAbleResult := WatchAbleResultFromObject(AWatchAble);
|
||||
|
||||
UpdateColumnsText(AWatchAble, AWatchAbleResult, AVNode);
|
||||
FTreeView.Invalidate;
|
||||
FTreeView.BeginUpdate;
|
||||
try
|
||||
UpdateColumnsText(AWatchAble, AWatchAbleResult, AVNode);
|
||||
FTreeView.Invalidate;
|
||||
|
||||
if AWatchAbleResult = nil then
|
||||
exit;
|
||||
if AWatchAbleResult = nil then
|
||||
exit;
|
||||
|
||||
// some debuggers may have run Application.ProcessMessages
|
||||
if CancelUpdate then
|
||||
exit;
|
||||
// some debuggers may have run Application.ProcessMessages
|
||||
if CancelUpdate then
|
||||
exit;
|
||||
|
||||
(* If the watch is ddsRequested or ddsEvaluating => keep any expanded tree-nodes. (Avoid flicker)
|
||||
> ddsEvaluating includes "not HasAllValidParents"
|
||||
If the debugger is running => keey any expanded tree-nodes
|
||||
*)
|
||||
(* If the watch is ddsRequested or ddsEvaluating => keep any expanded tree-nodes. (Avoid flicker)
|
||||
> ddsEvaluating includes "not HasAllValidParents"
|
||||
If the debugger is running => keey any expanded tree-nodes
|
||||
*)
|
||||
|
||||
if (not(AWatchAbleResult.Validity in [ddsRequested, ddsEvaluating])) and
|
||||
((DebugBoss = nil) or (DebugBoss.State <> dsRun))
|
||||
then begin
|
||||
TypInfo := AWatchAbleResult.TypeInfo;
|
||||
ResData := AWatchAbleResult.ResultData;
|
||||
while (ResData <> nil) and (ResData.ValueKind = rdkPointerVal) do
|
||||
ResData := ResData.DerefData;
|
||||
HasChildren := ( (TypInfo <> nil) and (TypInfo.Fields <> nil) and (TypInfo.Fields.Count > 0) ) or
|
||||
( (ResData <> nil) and
|
||||
( ( (ResData.FieldCount > 0) and (ResData.ValueKind <> rdkConvertRes) )
|
||||
or
|
||||
//( (ResData.ValueKind = rdkArray) and (ResData.ArrayLength > 0) )
|
||||
(ResData.ArrayLength > 0)
|
||||
) );
|
||||
FTreeView.HasChildren[AVNode] := HasChildren;
|
||||
if (not(AWatchAbleResult.Validity in [ddsRequested, ddsEvaluating])) and
|
||||
((DebugBoss = nil) or (DebugBoss.State <> dsRun))
|
||||
then begin
|
||||
TypInfo := AWatchAbleResult.TypeInfo;
|
||||
ResData := AWatchAbleResult.ResultData;
|
||||
while (ResData <> nil) and (ResData.ValueKind = rdkPointerVal) do
|
||||
ResData := ResData.DerefData;
|
||||
HasChildren := ( (TypInfo <> nil) and (TypInfo.Fields <> nil) and (TypInfo.Fields.Count > 0) ) or
|
||||
( (ResData <> nil) and
|
||||
( ( (ResData.FieldCount > 0) and (ResData.ValueKind <> rdkConvertRes) )
|
||||
or
|
||||
//( (ResData.ValueKind = rdkArray) and (ResData.ArrayLength > 0) )
|
||||
(ResData.ArrayLength > 0)
|
||||
) );
|
||||
FTreeView.HasChildren[AVNode] := HasChildren;
|
||||
|
||||
if HasChildren and FTreeView.Expanded[AVNode] then begin
|
||||
if (AWatchAbleResult.Validity = ddsValid) then begin
|
||||
(* The current "AWatchAbleResult" should be done. Allow UpdateItem for nested entries *)
|
||||
if HasChildren and FTreeView.Expanded[AVNode] then begin
|
||||
if (AWatchAbleResult.Validity = ddsValid) then begin
|
||||
(* The current "AWatchAbleResult" should be done. Allow UpdateItem for nested entries *)
|
||||
|
||||
UpdateSubItems(AWatchAble, AWatchAbleResult, AVNode, c);
|
||||
UpdateSubItems(AWatchAble, AWatchAbleResult, AVNode, c);
|
||||
end;
|
||||
end
|
||||
else
|
||||
if AWatchAble <> FExpandingWatchAbleResult then begin
|
||||
FTreeView.DeleteChildren(AVNode, False);
|
||||
FTreeView.NodeControl[AVNode] := nil
|
||||
end;
|
||||
end
|
||||
else
|
||||
if AWatchAble <> FExpandingWatchAbleResult then
|
||||
FTreeView.DeleteChildren(AVNode, False);
|
||||
end
|
||||
finally
|
||||
FTreeView.EndUpdate;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TDbgTreeViewWatchDataMgr.GetAsText(AScope: TTreeViewDataScope;
|
||||
|
@ -51,7 +51,10 @@ type
|
||||
ShortenResText: string;
|
||||
ColWidth: integer;
|
||||
end;
|
||||
CachedFirstCellLeft: integer;
|
||||
Control: TControl;
|
||||
ControlTop, ControlWidth, ControlHeight: integer; // ControlWidth -1 = full
|
||||
ControlHidden, ControlOutside: Boolean; // below current node, overlaps next
|
||||
PrevControlNode, NextControlNode: PVirtualNode;
|
||||
end;
|
||||
PDbgTreeNodeData = ^TDbgTreeNodeData;
|
||||
@ -63,45 +66,77 @@ type
|
||||
|
||||
TDbgTreeView = class(TLazVirtualStringTree)
|
||||
private
|
||||
FCheckControlsVisibleLock: integer;
|
||||
FCheckControlsVisibleRunning, FCheckControlsVisibleAgain: Boolean;
|
||||
FInToggle: boolean;
|
||||
FFirstControlNode: PVirtualNode; // not ordered
|
||||
FOnDetermineDropMode: TDetermineDropModeEvent;
|
||||
FOnItemRemoved: TItemRemovedEvent;
|
||||
function GetNodeControl(Node: PVirtualNode): TControl;
|
||||
function GetNodeImageIndex(Node: PVirtualNode; AColumn: integer): Integer;
|
||||
function GetNodeItem(Node: PVirtualNode): TObject;
|
||||
function GetNodeText(Node: PVirtualNode; AColumn: integer): String;
|
||||
procedure SetNodeControl(Node: PVirtualNode; AValue: TControl);
|
||||
procedure SetNodeImageIndex(Node: PVirtualNode; AColumn: integer;
|
||||
AValue: Integer);
|
||||
procedure SetNodeItem(Node: PVirtualNode; AValue: TObject);
|
||||
|
||||
// Text/Image
|
||||
function GetNodeImageIndex(Node: PVirtualNode; AColumn: integer): Integer;
|
||||
function GetNodeText(Node: PVirtualNode; AColumn: integer): String;
|
||||
procedure SetNodeImageIndex(Node: PVirtualNode; AColumn: integer; AValue: Integer);
|
||||
procedure SetNodeText(Node: PVirtualNode; AColumn: integer; AValue: String);
|
||||
// Item
|
||||
procedure SetNodeItem(Node: PVirtualNode; AValue: TObject);
|
||||
function GetNodeItem(Node: PVirtualNode): TObject;
|
||||
// Control
|
||||
function GetNodeControl(Node: PVirtualNode): TControl;
|
||||
function GetNodeControlVisible(Node: PVirtualNode): Boolean;
|
||||
function GetNodeControlOutside(Node: PVirtualNode): Boolean;
|
||||
function GetNodeControlWidth(Node: PVirtualNode): Integer;
|
||||
function GetNodeControlHeight(Node: PVirtualNode): Integer;
|
||||
procedure SetNodeControl(Node: PVirtualNode; AValue: TControl);
|
||||
procedure SetNodeControlVisible(Node: PVirtualNode; AValue: Boolean);
|
||||
procedure SetNodeControlOutside(Node: PVirtualNode; AValue: Boolean);
|
||||
procedure SetNodeControlWidth(Node: PVirtualNode; AValue: Integer);
|
||||
procedure SetNodeControlHeight(Node: PVirtualNode; AValue: Integer);
|
||||
procedure ChangeControl(Node: PVirtualNode; NData: PDbgTreeNodeData; AControl: TControl);
|
||||
function GetIsVisible(Node: PVirtualNode): Boolean; reintroduce;
|
||||
procedure SetIsVisible(Node: PVirtualNode; AValue: Boolean); reintroduce;
|
||||
protected
|
||||
procedure CheckControlsVisible(SkipPos: boolean = False);
|
||||
procedure DoAllAutoSize; override;
|
||||
procedure CheckControlsVisible;
|
||||
procedure VisibleChanged; override;
|
||||
|
||||
// Paint / Invalidate
|
||||
procedure EndUpdate; override;
|
||||
function DoSetOffsetXY(Value: TPoint; Options: TScrollUpdateOptions;
|
||||
ClipRect: PRect = nil): Boolean; override;
|
||||
function DoCollapsing(Node: PVirtualNode): Boolean; override;
|
||||
function DoSetOffsetXY(Value: TPoint; Options: TScrollUpdateOptions; ClipRect: PRect = nil): Boolean; override;
|
||||
function DoCollapsing(Node: PVirtualNode): Boolean; override;
|
||||
procedure DoExpanded(Node: PVirtualNode); override;
|
||||
procedure DoStateChange(Enter: TVirtualTreeStates; Leave: TVirtualTreeStates = []); override;
|
||||
procedure ValidateNodeDataSize(var Size: Integer); override;
|
||||
procedure DoFreeNode(Node: PVirtualNode); override;
|
||||
function DetermineLineImageAndSelectLevel(Node: PVirtualNode;
|
||||
var LineImage: TLineImage): Integer; override;
|
||||
function DetermineLineImageAndSelectLevel(Node: PVirtualNode; var LineImage: TLineImage): Integer; override;
|
||||
procedure DoBeforeItemErase(ACanvas: TCanvas; ANode: PVirtualNode; const ItemRect: TRect;
|
||||
var AColor: TColor; var EraseAction: TItemEraseAction); override;
|
||||
procedure PrepareCell(var PaintInfo: TVTPaintInfo; WindowOrgX, MaxWidth: Integer); override; // the background
|
||||
procedure PaintTreeLines(const PaintInfo: TVTPaintInfo; VAlignment, IndentSize: Integer;
|
||||
LineImage: TLineImage); override;
|
||||
procedure PaintNodeButton(ACanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
|
||||
const R: TRect; ButtonX, ButtonY: Integer; ABidiMode: TBiDiMode); override;
|
||||
procedure DoPaintNode(var PaintInfo: TVTPaintInfo); override;
|
||||
|
||||
// Mouse
|
||||
function DetermineDropMode(const P: TPoint; var HitInfo: THitInfo;
|
||||
var NodeRect: TRect): TDropMode; override;
|
||||
procedure HandleMouseDown(var Message: TLMMouse; var HitInfo: THitInfo); override;
|
||||
procedure HandleMouseDblClick(var Message: TLMMouse; const HitInfo: THitInfo); override;
|
||||
|
||||
// Data
|
||||
procedure DoGetText(Node: PVirtualNode; Column: TColumnIndex;
|
||||
TextType: TVSTTextType; var AText: String); override;
|
||||
procedure DoPaintNode(var PaintInfo: TVTPaintInfo); override;
|
||||
function DoGetImageIndex(Node: PVirtualNode; Kind: TVTImageKind;
|
||||
Column: TColumnIndex; var Ghosted: Boolean; var Index: Integer
|
||||
): TCustomImageList; override;
|
||||
function DoGetNodeWidth(ANode: PVirtualNode; AColumn: TColumnIndex; ACanvas: TCanvas =
|
||||
nil): Integer; override;
|
||||
function DoShortenString(ACanvas: TCanvas; ANode: PVirtualNode; AColumn: TColumnIndex;
|
||||
const S: String; AWidth: Integer; AnEllipsisWidth: Integer = 0): String; override;
|
||||
procedure DoNodeMoved(ANode: PVirtualNode); override;
|
||||
|
||||
procedure ValidateNodeDataSize(var Size: Integer); override;
|
||||
procedure DoFreeNode(Node: PVirtualNode); override;
|
||||
public
|
||||
function GetNodeData(Node: PVirtualNode): PDbgTreeNodeData; reintroduce;
|
||||
function GetFocusedNode(OnlySelected: Boolean = True; AnIncludeControlNodes: Boolean = False): PVirtualNode;
|
||||
function FocusedData(OnlySelected: Boolean = True): PDbgTreeNodeData;
|
||||
function FocusedItem(OnlySelected: Boolean = True): TObject;
|
||||
@ -122,10 +157,18 @@ type
|
||||
function SelectedItemNodes(ConsiderChildrenAbove: Boolean = False; IncludeNonItemNodes: Boolean = False): TVTVirtualItemNodeEnumeration;
|
||||
function ControlNodes: TVTVirtualItemNodeEnumeration;
|
||||
|
||||
function GetNodeData(Node: PVirtualNode): PDbgTreeNodeData; reintroduce;
|
||||
property NodeItem[Node: PVirtualNode]: TObject read GetNodeItem write SetNodeItem;
|
||||
property NodeText[Node: PVirtualNode; AColumn: integer]: String read GetNodeText write SetNodeText;
|
||||
property NodeImageIndex[Node: PVirtualNode; AColumn: integer]: Integer read GetNodeImageIndex write SetNodeImageIndex;
|
||||
property IsVisible[Node: PVirtualNode]: Boolean read GetIsVisible write SetIsVisible;
|
||||
// May need reintroduction //property NodeHeight[Node: PVirtualNode]: Cardinal read GetNodeHeight write SetNodeHeight;
|
||||
// Control
|
||||
property NodeControl[Node: PVirtualNode]: TControl read GetNodeControl write SetNodeControl;
|
||||
property NodeControlVisible[Node: PVirtualNode]: Boolean read GetNodeControlVisible write SetNodeControlVisible;
|
||||
property NodeControlWidth[Node: PVirtualNode]: Integer read GetNodeControlWidth write SetNodeControlWidth;
|
||||
property NodeControlHeight[Node: PVirtualNode]: Integer read GetNodeControlHeight write SetNodeControlHeight;
|
||||
property NodeControlOutside[Node: PVirtualNode]: Boolean read GetNodeControlOutside write SetNodeControlOutside;
|
||||
|
||||
property OnItemRemoved: TItemRemovedEvent read FOnItemRemoved write FOnItemRemoved;
|
||||
property OnDetermineDropMode: TDetermineDropModeEvent read FOnDetermineDropMode write FOnDetermineDropMode;
|
||||
@ -204,16 +247,6 @@ end;
|
||||
|
||||
{ TDbgTreeView }
|
||||
|
||||
function TDbgTreeView.GetNodeControl(Node: PVirtualNode): TControl;
|
||||
var
|
||||
Data: PDbgTreeNodeData;
|
||||
begin
|
||||
Result := nil;
|
||||
Data := GetNodeData(Node);
|
||||
if Data <> nil then
|
||||
Result := Data^.Control;
|
||||
end;
|
||||
|
||||
function TDbgTreeView.GetNodeImageIndex(Node: PVirtualNode; AColumn: integer
|
||||
): Integer;
|
||||
var
|
||||
@ -225,16 +258,6 @@ begin
|
||||
Result := Data^.ImageIndex[AColumn] - 1;
|
||||
end;
|
||||
|
||||
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;
|
||||
@ -245,25 +268,6 @@ begin
|
||||
Result := Data^.CachedText[AColumn];
|
||||
end;
|
||||
|
||||
procedure TDbgTreeView.SetNodeControl(Node: PVirtualNode; AValue: TControl);
|
||||
var
|
||||
Data: PDbgTreeNodeData;
|
||||
begin
|
||||
Data := GetNodeData(Node);
|
||||
if Data = nil then
|
||||
exit;
|
||||
if Data^.Control = AValue then
|
||||
exit;
|
||||
|
||||
Data^.Control.Free;
|
||||
ChangeControl(Node, Data, AValue);
|
||||
if AValue <> nil then begin
|
||||
AValue.Visible := False;
|
||||
AValue.Parent := Self;
|
||||
AValue.AutoSize := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TDbgTreeView.SetNodeImageIndex(Node: PVirtualNode; AColumn: integer;
|
||||
AValue: Integer);
|
||||
var
|
||||
@ -277,21 +281,6 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TDbgTreeView.SetNodeItem(Node: PVirtualNode; AValue: TObject);
|
||||
var
|
||||
Data: PDbgTreeNodeData;
|
||||
begin
|
||||
Data := GetNodeData(Node);
|
||||
|
||||
if Data <> nil then begin
|
||||
|
||||
if (FOnItemRemoved <> nil) and (Data^.Item <> nil) and (Data^.Item <> AValue) then
|
||||
FOnItemRemoved(Self, Data^.Item, Node);
|
||||
|
||||
Data^.Item := AValue;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TDbgTreeView.SetNodeText(Node: PVirtualNode; AColumn: integer;
|
||||
AValue: String);
|
||||
var
|
||||
@ -310,6 +299,216 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TDbgTreeView.SetNodeItem(Node: PVirtualNode; AValue: TObject);
|
||||
var
|
||||
Data: PDbgTreeNodeData;
|
||||
begin
|
||||
Data := GetNodeData(Node);
|
||||
|
||||
if Data <> nil then begin
|
||||
|
||||
if (FOnItemRemoved <> nil) and (Data^.Item <> nil) and (Data^.Item <> AValue) then
|
||||
FOnItemRemoved(Self, Data^.Item, Node);
|
||||
|
||||
Data^.Item := AValue;
|
||||
end;
|
||||
end;
|
||||
|
||||
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.GetNodeControl(Node: PVirtualNode): TControl;
|
||||
var
|
||||
Data: PDbgTreeNodeData;
|
||||
begin
|
||||
Result := nil;
|
||||
Data := GetNodeData(Node);
|
||||
if Data <> nil then
|
||||
Result := Data^.Control;
|
||||
end;
|
||||
|
||||
function TDbgTreeView.GetNodeControlVisible(Node: PVirtualNode): Boolean;
|
||||
var
|
||||
Data: PDbgTreeNodeData;
|
||||
begin
|
||||
Result := False;
|
||||
Data := GetNodeData(Node);
|
||||
if Data <> nil then
|
||||
Result := not Data^.ControlHidden;
|
||||
end;
|
||||
|
||||
function TDbgTreeView.GetNodeControlOutside(Node: PVirtualNode): Boolean;
|
||||
var
|
||||
Data: PDbgTreeNodeData;
|
||||
begin
|
||||
Result := False;
|
||||
Data := GetNodeData(Node);
|
||||
if Data <> nil then
|
||||
Result := Data^.ControlOutside;
|
||||
end;
|
||||
|
||||
function TDbgTreeView.GetNodeControlWidth(Node: PVirtualNode): Integer;
|
||||
var
|
||||
Data: PDbgTreeNodeData;
|
||||
begin
|
||||
Result := 0;
|
||||
Data := GetNodeData(Node);
|
||||
if Data <> nil then
|
||||
Result := Data^.ControlWidth;
|
||||
end;
|
||||
|
||||
function TDbgTreeView.GetNodeControlHeight(Node: PVirtualNode): Integer;
|
||||
var
|
||||
Data: PDbgTreeNodeData;
|
||||
begin
|
||||
Result := 0;
|
||||
Data := GetNodeData(Node);
|
||||
if Data <> nil then
|
||||
Result := Data^.ControlHeight;
|
||||
end;
|
||||
|
||||
procedure TDbgTreeView.SetNodeControl(Node: PVirtualNode; AValue: TControl);
|
||||
var
|
||||
Data: PDbgTreeNodeData;
|
||||
h: LongWord;
|
||||
begin
|
||||
Data := GetNodeData(Node);
|
||||
if Data = nil then
|
||||
exit;
|
||||
if Data^.Control = AValue then
|
||||
exit;
|
||||
|
||||
Data^.Control.Free;
|
||||
|
||||
ChangeControl(Node, Data, AValue);
|
||||
if AValue <> nil then begin
|
||||
AValue.Visible := False;
|
||||
AValue.Parent := Self;
|
||||
AValue.AutoSize := False;
|
||||
end;
|
||||
|
||||
if (Data^.Item <> nil) and (Data^.ControlTop = 0) then begin
|
||||
h := NodeHeight[Node];
|
||||
Data^.ControlTop := h;
|
||||
Data^.ControlHeight := DefaultNodeHeight;
|
||||
if (Data^.Control <> nil) and (not Data^.ControlHidden) and not Data^.ControlOutside then
|
||||
NodeHeight[Node] := h + Data^.ControlHeight
|
||||
else
|
||||
NodeHeight[Node] := h;
|
||||
end
|
||||
else
|
||||
if AValue = nil then begin
|
||||
if Data^.ControlTop > 0 then
|
||||
NodeHeight[Node] := Data^.ControlTop;
|
||||
Data^.ControlTop := 0;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TDbgTreeView.SetNodeControlVisible(Node: PVirtualNode; AValue: Boolean);
|
||||
var
|
||||
Data: PDbgTreeNodeData;
|
||||
h: LongWord;
|
||||
begin
|
||||
Data := GetNodeData(Node);
|
||||
if Data = nil then
|
||||
exit;
|
||||
if not Data^.ControlHidden = AValue then
|
||||
exit;
|
||||
|
||||
Data^.ControlHidden := not AValue;
|
||||
|
||||
if (Data^.ControlTop = 0) then begin
|
||||
h := NodeHeight[Node];
|
||||
if Data^.Item <> nil then
|
||||
Data^.ControlTop := h;
|
||||
end
|
||||
else
|
||||
h := Data^.ControlTop;
|
||||
|
||||
if (Data^.Control <> nil) and Data^.ControlHidden then
|
||||
Data^.Control.Visible := False;
|
||||
|
||||
if (Data^.Item <> nil) then begin
|
||||
if (Data^.Control <> nil) and (not Data^.ControlHidden) and not Data^.ControlOutside then
|
||||
NodeHeight[Node] := h + Data^.ControlHeight
|
||||
else
|
||||
NodeHeight[Node] := h;
|
||||
end;
|
||||
InvalidateToBottom(Node);
|
||||
end;
|
||||
|
||||
procedure TDbgTreeView.SetNodeControlOutside(Node: PVirtualNode; AValue: Boolean);
|
||||
var
|
||||
Data: PDbgTreeNodeData;
|
||||
h: LongWord;
|
||||
begin
|
||||
Data := GetNodeData(Node);
|
||||
if Data = nil then
|
||||
exit;
|
||||
if Data^.ControlOutside = AValue then
|
||||
exit;
|
||||
|
||||
Data^.ControlOutside := AValue;
|
||||
|
||||
if (Data^.ControlTop = 0) then begin
|
||||
h := NodeHeight[Node];
|
||||
if Data^.Item <> nil then
|
||||
Data^.ControlTop := h;
|
||||
end
|
||||
else
|
||||
h := Data^.ControlTop;
|
||||
|
||||
if (Data^.Item <> nil) then begin
|
||||
if (Data^.Control <> nil) and (not Data^.ControlHidden) and not Data^.ControlOutside then
|
||||
NodeHeight[Node] := h + Data^.ControlHeight
|
||||
else
|
||||
NodeHeight[Node] := h;
|
||||
end;
|
||||
InvalidateToBottom(Node);
|
||||
end;
|
||||
|
||||
procedure TDbgTreeView.SetNodeControlWidth(Node: PVirtualNode; AValue: Integer);
|
||||
var
|
||||
Data: PDbgTreeNodeData;
|
||||
begin
|
||||
Data := GetNodeData(Node);
|
||||
if Data = nil then
|
||||
exit;
|
||||
if Data^.ControlWidth = AValue then
|
||||
exit;
|
||||
|
||||
Data^.ControlWidth := AValue;
|
||||
InvalidateToBottom(Node);
|
||||
end;
|
||||
|
||||
procedure TDbgTreeView.SetNodeControlHeight(Node: PVirtualNode; AValue: Integer);
|
||||
var
|
||||
Data: PDbgTreeNodeData;
|
||||
begin
|
||||
Data := GetNodeData(Node);
|
||||
if Data = nil then
|
||||
exit;
|
||||
if AValue < 0 then AValue := 0;
|
||||
if Data^.ControlHeight = AValue then
|
||||
exit;
|
||||
|
||||
if (Data^.Item = nil) then // control takes full node
|
||||
NodeHeight[Node] := AValue
|
||||
else
|
||||
if (Data^.Control <> nil) and (not Data^.ControlHidden) and not Data^.ControlOutside then
|
||||
NodeHeight[Node] := NodeHeight[Node] + AValue - Data^.ControlHeight;
|
||||
|
||||
Data^.ControlHeight := AValue;
|
||||
InvalidateToBottom(Node);
|
||||
end;
|
||||
|
||||
procedure TDbgTreeView.ChangeControl(Node: PVirtualNode;
|
||||
NData: PDbgTreeNodeData; AControl: TControl);
|
||||
var
|
||||
@ -354,63 +553,140 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TDbgTreeView.CheckControlsVisible(SkipPos: boolean);
|
||||
function TDbgTreeView.GetIsVisible(Node: PVirtualNode): Boolean;
|
||||
begin
|
||||
Result := inherited IsVisible[Node];
|
||||
end;
|
||||
|
||||
procedure TDbgTreeView.SetIsVisible(Node: PVirtualNode; AValue: Boolean);
|
||||
var
|
||||
Data: PDbgTreeNodeData;
|
||||
begin
|
||||
inherited IsVisible[Node] := AValue;
|
||||
|
||||
Data := GetNodeData(Node);
|
||||
if (Data <> nil) and (Data^.Control <> nil) and (not AValue) then
|
||||
Data^.Control.Visible := False;
|
||||
end;
|
||||
|
||||
procedure TDbgTreeView.DoAllAutoSize;
|
||||
begin
|
||||
FCheckControlsVisibleRunning := True;
|
||||
inherited DoAllAutoSize;
|
||||
FCheckControlsVisibleRunning := False;
|
||||
if FCheckControlsVisibleAgain then
|
||||
CheckControlsVisible;
|
||||
end;
|
||||
|
||||
procedure TDbgTreeView.CheckControlsVisible;
|
||||
var
|
||||
VNode: PVirtualNode;
|
||||
Y, H, T, B: Integer;
|
||||
NData: PDbgTreeNodeData;
|
||||
Y, Y2, H, H2, T, B, offs, Limit: Integer;
|
||||
Ctrl: TControl;
|
||||
Chg: Boolean;
|
||||
r2: TRect;
|
||||
begin
|
||||
if (FFirstControlNode = nil) or (UpdateCount > 0) then
|
||||
FCheckControlsVisibleAgain := FCheckControlsVisibleRunning;
|
||||
if (FCheckControlsVisibleLock > 0) or FCheckControlsVisibleRunning or
|
||||
(FFirstControlNode = nil) or (UpdateCount > 0) or
|
||||
(not TControl(self).IsVisible) or (not HandleAllocated)
|
||||
then
|
||||
exit;
|
||||
|
||||
T := Header.Height;
|
||||
B := ClientHeight - 1 + T; // subtracted by laz.VirtualTree
|
||||
Y := OffsetY + T;
|
||||
Chg := False;
|
||||
for VNode in VisibleNoInitNodes do begin
|
||||
Ctrl := NodeControl[VNode];
|
||||
H := NodeHeight[VNode];
|
||||
if (Ctrl <> nil) then begin
|
||||
if (Y < T) or (Y >= B) then begin
|
||||
Chg := Chg or Ctrl.Visible;
|
||||
Ctrl.Visible := False;
|
||||
end
|
||||
else begin
|
||||
Chg := Chg or
|
||||
(Ctrl.Top <> Y) or
|
||||
(Ctrl.Height <> H) or
|
||||
(Ctrl.Visible <> True);
|
||||
DisableAutoSizing;
|
||||
FCheckControlsVisibleRunning := True;
|
||||
try
|
||||
Limit := 5 + ClientHeight div (DefaultNodeHeight * 2);
|
||||
repeat
|
||||
dec(Limit);
|
||||
T := Header.Height;
|
||||
B := ClientHeight - 1 + T; // subtracted by laz.VirtualTree
|
||||
Y := OffsetY + T;
|
||||
Chg := False;
|
||||
for VNode in VisibleNoInitNodes do begin
|
||||
NData := GetNodeData(VNode);
|
||||
offs := 0;
|
||||
H := NodeHeight[VNode];
|
||||
if NData <> nil then begin
|
||||
Ctrl := NData^.Control;
|
||||
if NData^.ControlHidden then begin
|
||||
if (Ctrl <> nil) then
|
||||
Ctrl.Visible := False;
|
||||
end
|
||||
else
|
||||
if (Ctrl <> nil) then begin
|
||||
offs := NData^.ControlTop;
|
||||
Y2 := Y + offs;
|
||||
if NData^.ControlOutside then
|
||||
H2 := NData^.ControlHeight
|
||||
else
|
||||
H2 := H - offs;
|
||||
if (Y2 < T) or (Y2 >= B) then begin
|
||||
Chg := Chg or Ctrl.Visible;
|
||||
Ctrl.Visible := False;
|
||||
end
|
||||
else begin
|
||||
Chg := Chg or
|
||||
(Ctrl.Top <> Y2) or
|
||||
(Ctrl.Height <> H2) or
|
||||
(Ctrl.Visible <> True);
|
||||
|
||||
if (not Ctrl.Visible) or (not SkipPos) then begin
|
||||
Ctrl.Top := Y;
|
||||
Ctrl.Height := Min(H, b - 1 - Y);
|
||||
|
||||
if NData^.ControlOutside then begin
|
||||
Ctrl.SetBounds(OffsetX, Y2, Ctrl.Width, H2);
|
||||
end
|
||||
else begin
|
||||
if (NData^.CachedFirstCellLeft <= 0) then begin
|
||||
r2 := GetDisplayRect(vNode, 0, True, False);
|
||||
NData^.CachedFirstCellLeft := r2.Left;
|
||||
end;
|
||||
Ctrl.SetBounds(NData^.CachedFirstCellLeft + OffsetX, Y2, Ctrl.Width, H2);
|
||||
end;
|
||||
ctrl.Visible := True;
|
||||
H2 := NodeHeight[VNode];
|
||||
if H <> H2 then
|
||||
Ctrl.Height := H2 - offs;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
Ctrl.Visible := True;
|
||||
Y := Y + NodeHeight[VNode];
|
||||
end;
|
||||
end;
|
||||
Y := Y + H;
|
||||
end;
|
||||
until (not FCheckControlsVisibleAgain) or (Limit <= 0);
|
||||
|
||||
if Chg then
|
||||
Invalidate;
|
||||
finally
|
||||
FCheckControlsVisibleAgain := False;
|
||||
FCheckControlsVisibleRunning := False;
|
||||
// EnableAutoSizing: Some controls may change their node's height
|
||||
EnableAutoSizing;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TDbgTreeView.VisibleChanged;
|
||||
begin
|
||||
inc(FCheckControlsVisibleLock);
|
||||
inherited VisibleChanged;
|
||||
dec(FCheckControlsVisibleLock);
|
||||
CheckControlsVisible;
|
||||
end;
|
||||
|
||||
procedure TDbgTreeView.EndUpdate;
|
||||
begin
|
||||
inc(FCheckControlsVisibleLock);
|
||||
inherited EndUpdate;
|
||||
dec(FCheckControlsVisibleLock);
|
||||
CheckControlsVisible;
|
||||
end;
|
||||
|
||||
function TDbgTreeView.DoSetOffsetXY(Value: TPoint;
|
||||
Options: TScrollUpdateOptions; ClipRect: PRect): Boolean;
|
||||
begin
|
||||
inc(FCheckControlsVisibleLock);
|
||||
DisableAutoSizing;
|
||||
Result := inherited DoSetOffsetXY(Value, Options, ClipRect);
|
||||
{$if defined(LCLGtk) or defined(LCLGtk2)}
|
||||
dec(FCheckControlsVisibleLock);
|
||||
CheckControlsVisible;
|
||||
{$else}
|
||||
CheckControlsVisible(True);
|
||||
{$endif}
|
||||
EnableAutoSizing;
|
||||
end;
|
||||
|
||||
function TDbgTreeView.DoCollapsing(Node: PVirtualNode): Boolean;
|
||||
@ -419,11 +695,11 @@ function TDbgTreeView.DoCollapsing(Node: PVirtualNode): Boolean;
|
||||
N2: PVirtualNode;
|
||||
NData: PDbgTreeNodeData;
|
||||
begin
|
||||
NData := GetNodeData(N);
|
||||
if NData^.Control <> nil then
|
||||
NData^.Control.Visible := False;
|
||||
|
||||
while N <> nil do begin
|
||||
NData := GetNodeData(N);
|
||||
if NData^.Control <> nil then
|
||||
NData^.Control.Visible := False;
|
||||
|
||||
N2 := GetFirstChildNoInit(N);
|
||||
if N2 <> nil then
|
||||
RecursivelyHideControls(N2);
|
||||
@ -442,42 +718,36 @@ end;
|
||||
|
||||
procedure TDbgTreeView.DoExpanded(Node: PVirtualNode);
|
||||
begin
|
||||
inc(FCheckControlsVisibleLock);
|
||||
inherited DoExpanded(Node);
|
||||
dec(FCheckControlsVisibleLock);
|
||||
CheckControlsVisible;
|
||||
end;
|
||||
|
||||
procedure TDbgTreeView.DoStateChange(Enter: TVirtualTreeStates;
|
||||
Leave: TVirtualTreeStates);
|
||||
begin
|
||||
inherited DoStateChange(Enter, Leave);
|
||||
if tsToggling in Leave then
|
||||
CheckControlsVisible;
|
||||
end;
|
||||
|
||||
procedure TDbgTreeView.ValidateNodeDataSize(var Size: Integer);
|
||||
begin
|
||||
Size := SizeOf(TDbgTreeNodeData);
|
||||
end;
|
||||
|
||||
procedure TDbgTreeView.DoFreeNode(Node: PVirtualNode);
|
||||
var
|
||||
NData: PDbgTreeNodeData;
|
||||
begin
|
||||
NData := GetNodeData(Node);
|
||||
if NData <> nil then begin
|
||||
if (FOnItemRemoved <> nil) and (NData^.Item <> nil) then
|
||||
FOnItemRemoved(Self, NData^.Item, Node);
|
||||
|
||||
NData^.Control.Free;
|
||||
ChangeControl(Node, NData, nil);
|
||||
NData^ := Default(TDbgTreeNodeData);
|
||||
if tsToggling in Enter then begin
|
||||
if not FInToggle then
|
||||
inc(FCheckControlsVisibleLock);
|
||||
FInToggle := True;
|
||||
end;
|
||||
inherited DoStateChange(Enter, Leave);
|
||||
if tsToggling in Leave then begin
|
||||
if FInToggle then
|
||||
dec(FCheckControlsVisibleLock);
|
||||
FInToggle := False;
|
||||
CheckControlsVisible;
|
||||
if not AutoSizeDelayed then // e.g. called by mouseclick / update before syncronizing with dbg-results
|
||||
Update;
|
||||
end;
|
||||
|
||||
inherited DoFreeNode(Node);
|
||||
end;
|
||||
|
||||
function TDbgTreeView.DetermineLineImageAndSelectLevel(Node: PVirtualNode;
|
||||
var LineImage: TLineImage): Integer;
|
||||
var
|
||||
NData: PDbgTreeNodeData;
|
||||
i: Integer;
|
||||
begin
|
||||
Result := inherited DetermineLineImageAndSelectLevel(Node, LineImage);
|
||||
if Length(LineImage) > 1 then
|
||||
@ -485,6 +755,145 @@ begin
|
||||
else
|
||||
if (Length(LineImage) > 0) and (LineImage[0] <> ltNone) then
|
||||
LineImage[0] := ltRight;
|
||||
|
||||
NData := GetNodeData(Node);
|
||||
if (NData^.Control <> nil) and (NData^.Item <> nil) then
|
||||
for i := 1 to Length(LineImage) - 1 do
|
||||
if LineImage[i] = ltNone then
|
||||
LineImage[i] := ltTopDown;
|
||||
|
||||
end;
|
||||
|
||||
procedure TDbgTreeView.DoPaintNode(var PaintInfo: TVTPaintInfo);
|
||||
var
|
||||
NData: PDbgTreeNodeData;
|
||||
r: TRect;
|
||||
b: LongInt;
|
||||
begin
|
||||
NData := GetNodeData(PaintInfo.Node);
|
||||
b := PaintInfo.ContentRect.Bottom;
|
||||
if NData^.Item = nil then
|
||||
exit;
|
||||
if (NData^.Control <> nil) and (not NData^.ControlHidden) and (not NData^.ControlOutside) then
|
||||
PaintInfo.ContentRect.Bottom := NData^.ControlTop;
|
||||
|
||||
inherited DoPaintNode(PaintInfo);
|
||||
PaintInfo.ContentRect.Bottom := b;
|
||||
end;
|
||||
|
||||
procedure TDbgTreeView.PaintNodeButton(ACanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
|
||||
const R: TRect; ButtonX, ButtonY: Integer; ABidiMode: TBiDiMode);
|
||||
var
|
||||
NData: PDbgTreeNodeData;
|
||||
offs: Integer;
|
||||
begin
|
||||
NData := GetNodeData(Node);
|
||||
offs := NData^.ControlTop;
|
||||
|
||||
if offs > 0 then
|
||||
ButtonY := ButtonY - (r.Bottom - offs) div 2;
|
||||
inherited PaintNodeButton(ACanvas, Node, Column, R, ButtonX, ButtonY, ABidiMode);
|
||||
end;
|
||||
|
||||
procedure TDbgTreeView.PaintTreeLines(const PaintInfo: TVTPaintInfo; VAlignment,
|
||||
IndentSize: Integer; LineImage: TLineImage);
|
||||
var
|
||||
NData: PDbgTreeNodeData;
|
||||
offs: Integer;
|
||||
PaintI2: TVTPaintInfo;
|
||||
VAlignment2: LongInt;
|
||||
begin
|
||||
|
||||
NData := GetNodeData(PaintInfo.Node);
|
||||
offs := NData^.ControlTop;
|
||||
PaintI2 := PaintInfo;
|
||||
if offs > 0 then begin
|
||||
PaintI2.CellRect.Top := min(PaintInfo.CellRect.Top + offs, PaintInfo.CellRect.Bottom);
|
||||
VAlignment2 := (PaintI2.CellRect.Bottom - PaintI2.CellRect.Top) div 2 - 1;
|
||||
inherited PaintTreeLines(PaintI2, VAlignment2, IndentSize, LineImage);
|
||||
end;
|
||||
|
||||
inherited PaintTreeLines(PaintInfo, VAlignment, IndentSize -1, LineImage);
|
||||
end;
|
||||
|
||||
procedure TDbgTreeView.PrepareCell(var PaintInfo: TVTPaintInfo; WindowOrgX, MaxWidth: Integer);
|
||||
var
|
||||
NData: PDbgTreeNodeData;
|
||||
offs: Integer;
|
||||
b, b2: LongInt;
|
||||
begin
|
||||
NData := GetNodeData(PaintInfo.Node);
|
||||
offs := NData^.ControlTop;
|
||||
if offs = 0 then begin
|
||||
inherited PrepareCell(PaintInfo, WindowOrgX, MaxWidth);
|
||||
exit;
|
||||
end;
|
||||
|
||||
b := PaintInfo.CellRect.Bottom;
|
||||
b2 := PaintInfo.ContentRect.Bottom;
|
||||
PaintInfo.CellRect.Bottom := PaintInfo.CellRect.Top + offs;
|
||||
PaintInfo.ContentRect.Bottom := PaintInfo.ContentRect.Top + offs;
|
||||
|
||||
inherited PrepareCell(PaintInfo, WindowOrgX, MaxWidth);
|
||||
PaintInfo.CellRect.Bottom := b;
|
||||
PaintInfo.ContentRect.Bottom := b2;
|
||||
end;
|
||||
|
||||
procedure TDbgTreeView.DoBeforeItemErase(ACanvas: TCanvas; ANode: PVirtualNode;
|
||||
const ItemRect: TRect; var AColor: TColor; var EraseAction: TItemEraseAction);
|
||||
var
|
||||
NData: PDbgTreeNodeData;
|
||||
offs: Integer;
|
||||
r, r2: TRect;
|
||||
Temp: PVirtualNode;
|
||||
begin
|
||||
inherited DoBeforeItemErase(ACanvas, ANode, ItemRect, AColor, EraseAction);
|
||||
EraseAction := eaColor;
|
||||
|
||||
NData := GetNodeData(ANode);
|
||||
if NData^.Control <> nil then begin
|
||||
if not NData^.ControlHidden then begin
|
||||
r := ItemRect;
|
||||
|
||||
if NData^.CachedFirstCellLeft <= 0 then begin
|
||||
r2 := GetDisplayRect(ANode, 0, True, False);
|
||||
NData^.CachedFirstCellLeft := r2.Left;
|
||||
r.Top := r2.Top;
|
||||
end
|
||||
else begin
|
||||
r.Top := OffsetY;
|
||||
Temp := ANode;
|
||||
repeat
|
||||
Temp := GetPreviousVisibleNoInit(Temp, True);
|
||||
if Temp = nil then
|
||||
Break;
|
||||
Inc(r.Top, NodeHeight[Temp]);
|
||||
until False;
|
||||
if hoVisible in Header.Options then
|
||||
inc(r.Top, Header.Height);
|
||||
end;
|
||||
|
||||
offs := NData^.ControlTop;
|
||||
r.Bottom := r.Top + ItemRect.Bottom - ItemRect.Top;
|
||||
r.Top := r.Top + offs;
|
||||
if r.Top >= Header.Height then begin
|
||||
if NData^.ControlOutside then begin
|
||||
NData^.Control.SetBounds(OffsetX, r.Top, NData^.ControlWidth, NData^.ControlHeight);
|
||||
end
|
||||
else begin
|
||||
r.Left := NData^.CachedFirstCellLeft + OffsetX;
|
||||
if NData^.ControlWidth <= 0 then
|
||||
r.Right := RangeX
|
||||
else
|
||||
r.Right := r.Left+NData^.ControlWidth;
|
||||
NData^.Control.BoundsRect := r;
|
||||
end;
|
||||
NData^.Control.Visible := True;
|
||||
end;
|
||||
end
|
||||
else
|
||||
NData^.Control.Visible := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TDbgTreeView.DetermineDropMode(const P: TPoint; var HitInfo: THitInfo;
|
||||
@ -534,29 +943,13 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TDbgTreeView.DoPaintNode(var PaintInfo: TVTPaintInfo);
|
||||
var
|
||||
NData: PDbgTreeNodeData;
|
||||
r: TRect;
|
||||
function TDbgTreeView.DoGetImageIndex(Node: PVirtualNode; Kind: TVTImageKind;
|
||||
Column: TColumnIndex; var Ghosted: Boolean; var Index: Integer
|
||||
): TCustomImageList;
|
||||
begin
|
||||
NData := GetNodeData(PaintInfo.Node);
|
||||
if NData^.Control <> nil then begin
|
||||
if PaintInfo.Column = 0 then begin
|
||||
r := GetDisplayRect(PaintInfo.Node, 0, True, False);
|
||||
if r.Top >= Header.Height then begin
|
||||
r.Right := ClientWidth - 1;
|
||||
NData^.Control.BoundsRect := r;
|
||||
NData^.Control.Visible := True;
|
||||
if (r.Top < (r.Bottom - r.Height) * 2 + 5) or
|
||||
(r.Bottom > ClientHeight - (r.Bottom - r.Height) * 2 - 5)
|
||||
then
|
||||
NData^.Control.Invalidate;
|
||||
end;
|
||||
end;
|
||||
exit;
|
||||
end;
|
||||
|
||||
inherited DoPaintNode(PaintInfo);
|
||||
Result := nil;
|
||||
Ghosted := False;
|
||||
Index := GetNodeImageIndex(Node, Column);
|
||||
end;
|
||||
|
||||
function TDbgTreeView.DoGetNodeWidth(ANode: PVirtualNode; AColumn: TColumnIndex; ACanvas: TCanvas
|
||||
@ -614,6 +1007,7 @@ begin
|
||||
NData^.CachedColumnData[i].ShortenResText := '';
|
||||
NData^.CachedColumnData[i].ShortenWidth1 := -1;
|
||||
NData^.CachedColumnData[i].ColWidth := -1;
|
||||
NData^.CachedFirstCellLeft := -1;
|
||||
end;
|
||||
|
||||
N := GetFirstChildNoInit(ANode);
|
||||
@ -622,6 +1016,27 @@ begin
|
||||
if N <> nil then DoNodeMoved(N);
|
||||
end;
|
||||
|
||||
procedure TDbgTreeView.ValidateNodeDataSize(var Size: Integer);
|
||||
begin
|
||||
Size := SizeOf(TDbgTreeNodeData);
|
||||
end;
|
||||
|
||||
procedure TDbgTreeView.DoFreeNode(Node: PVirtualNode);
|
||||
var
|
||||
NData: PDbgTreeNodeData;
|
||||
begin
|
||||
NData := GetNodeData(Node);
|
||||
if NData <> nil then begin
|
||||
if (FOnItemRemoved <> nil) and (NData^.Item <> nil) then
|
||||
FOnItemRemoved(Self, NData^.Item, Node);
|
||||
|
||||
NData^.Control.Free;
|
||||
ChangeControl(Node, NData, nil);
|
||||
NData^ := Default(TDbgTreeNodeData);
|
||||
end;
|
||||
|
||||
inherited DoFreeNode(Node);
|
||||
end;
|
||||
|
||||
function TDbgTreeView.GetNodeData(Node: PVirtualNode): PDbgTreeNodeData;
|
||||
begin
|
||||
@ -632,7 +1047,9 @@ function TDbgTreeView.GetFocusedNode(OnlySelected: Boolean;
|
||||
AnIncludeControlNodes: Boolean): PVirtualNode;
|
||||
begin
|
||||
Result := FocusedNode;
|
||||
if (not AnIncludeControlNodes) and (Result <> nil) and (NodeControl[Result] <> nil) then
|
||||
if (not AnIncludeControlNodes) and (Result <> nil) and
|
||||
(NodeControl[Result] <> nil) and (NodeItem[Result] = nil)
|
||||
then
|
||||
Result := nil;
|
||||
if (Result = nil) or (OnlySelected and not Selected[Result]) then
|
||||
Result := nil;
|
||||
|
Loading…
Reference in New Issue
Block a user