mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-31 02:53:42 +02:00
Debugger, IDE: Add basic child watch support for structured values
This commit is contained in:
parent
d58b6ab507
commit
601246dc25
@ -40,6 +40,7 @@ object WatchesDlg: TWatchesDlg
|
|||||||
OnDragOver = tvWatchesDragOver
|
OnDragOver = tvWatchesDragOver
|
||||||
OnDragDrop = tvWatchesDragDrop
|
OnDragDrop = tvWatchesDragDrop
|
||||||
OnFocusChanged = tvWatchesFocusChanged
|
OnFocusChanged = tvWatchesFocusChanged
|
||||||
|
OnInitChildren = tvWatchesInitChildren
|
||||||
OnNodeDblClick = tvWatchesNodeDblClick
|
OnNodeDblClick = tvWatchesNodeDblClick
|
||||||
end
|
end
|
||||||
object ToolBar1: TToolBar
|
object ToolBar1: TToolBar
|
||||||
|
@ -51,7 +51,8 @@ type
|
|||||||
TWatchesDlgStateFlags = set of (
|
TWatchesDlgStateFlags = set of (
|
||||||
wdsfUpdating,
|
wdsfUpdating,
|
||||||
wdsfNeedDeleteAll,
|
wdsfNeedDeleteAll,
|
||||||
wdsfNeedDeleteCurrent
|
wdsfNeedDeleteCurrent,
|
||||||
|
wdsDeleting
|
||||||
);
|
);
|
||||||
|
|
||||||
{ TWatchesDlg }
|
{ TWatchesDlg }
|
||||||
@ -132,6 +133,8 @@ type
|
|||||||
var Effect: LongWord; var Accept: Boolean);
|
var Effect: LongWord; var Accept: Boolean);
|
||||||
procedure tvWatchesFocusChanged(Sender: TBaseVirtualTree;
|
procedure tvWatchesFocusChanged(Sender: TBaseVirtualTree;
|
||||||
Node: PVirtualNode; Column: TColumnIndex);
|
Node: PVirtualNode; Column: TColumnIndex);
|
||||||
|
procedure tvWatchesInitChildren(Sender: TBaseVirtualTree;
|
||||||
|
Node: PVirtualNode; var ChildCount: Cardinal);
|
||||||
procedure tvWatchesNodeDblClick(Sender: TBaseVirtualTree;
|
procedure tvWatchesNodeDblClick(Sender: TBaseVirtualTree;
|
||||||
const HitInfo: THitInfo);
|
const HitInfo: THitInfo);
|
||||||
procedure popAddClick(Sender: TObject);
|
procedure popAddClick(Sender: TObject);
|
||||||
@ -142,14 +145,16 @@ type
|
|||||||
procedure popEnableAllClick(Sender: TObject);
|
procedure popEnableAllClick(Sender: TObject);
|
||||||
procedure popDeleteAllClick(Sender: TObject);
|
procedure popDeleteAllClick(Sender: TObject);
|
||||||
private
|
private
|
||||||
|
FQueuedUnLockCommandProcessing: Boolean;
|
||||||
|
procedure DoUnLockCommandProcessing(Data: PtrInt);
|
||||||
function GetWatches: TIdeWatches;
|
function GetWatches: TIdeWatches;
|
||||||
procedure ContextChanged(Sender: TObject);
|
procedure ContextChanged(Sender: TObject);
|
||||||
procedure SnapshotChanged(Sender: TObject);
|
procedure SnapshotChanged(Sender: TObject);
|
||||||
private
|
private
|
||||||
FWatchesInView: TIdeWatches;
|
FWatchesInView: TIdeWatches;
|
||||||
FPowerImgIdx, FPowerImgIdxGrey: Integer;
|
FPowerImgIdx, FPowerImgIdxGrey: Integer;
|
||||||
FUpdateAllNeeded, FUpdatingAll: Boolean;
|
FUpdateAllNeeded, FInEndUpdate: Boolean;
|
||||||
FWatchInUpDateItem: TIdeWatch;
|
FWatchInUpDateItem, FCurrentWatchInUpDateItem: TIdeWatch;
|
||||||
FStateFlags: TWatchesDlgStateFlags;
|
FStateFlags: TWatchesDlgStateFlags;
|
||||||
function GetSelected: TIdeWatch; // The focused Selected Node
|
function GetSelected: TIdeWatch; // The focused Selected Node
|
||||||
function GetThreadId: Integer;
|
function GetThreadId: Integer;
|
||||||
@ -161,6 +166,8 @@ type
|
|||||||
|
|
||||||
procedure UpdateInspectPane;
|
procedure UpdateInspectPane;
|
||||||
procedure UpdateItem(const VNode: PVirtualNode; const AWatch: TIdeWatch);
|
procedure UpdateItem(const VNode: PVirtualNode; const AWatch: TIdeWatch);
|
||||||
|
procedure UpdateSubItems(const VNode: PVirtualNode;
|
||||||
|
const AWatchValue: TIdeWatchValue; out ChildCount: LongWord);
|
||||||
procedure UpdateAll;
|
procedure UpdateAll;
|
||||||
procedure DisableAllActions;
|
procedure DisableAllActions;
|
||||||
function GetSelectedSnapshot: TSnapshot;
|
function GetSelectedSnapshot: TSnapshot;
|
||||||
@ -173,6 +180,7 @@ type
|
|||||||
procedure ColSizeSetter(AColId: Integer; ASize: Integer);
|
procedure ColSizeSetter(AColId: Integer; ASize: Integer);
|
||||||
public
|
public
|
||||||
constructor Create(AOwner: TComponent); override;
|
constructor Create(AOwner: TComponent); override;
|
||||||
|
destructor Destroy; override;
|
||||||
property WatchesMonitor;
|
property WatchesMonitor;
|
||||||
property ThreadsMonitor;
|
property ThreadsMonitor;
|
||||||
property CallStackMonitor;
|
property CallStackMonitor;
|
||||||
@ -284,6 +292,16 @@ begin
|
|||||||
tvWatches.Header.Columns[1].Width := COL_WIDTHS[COL_WATCH_VALUE];
|
tvWatches.Header.Columns[1].Width := COL_WIDTHS[COL_WATCH_VALUE];
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
destructor TWatchesDlg.Destroy;
|
||||||
|
begin
|
||||||
|
Application.RemoveAsyncCalls(Self);
|
||||||
|
if FQueuedUnLockCommandProcessing then
|
||||||
|
DebugBoss.UnLockCommandProcessing;
|
||||||
|
FQueuedUnLockCommandProcessing := False;
|
||||||
|
|
||||||
|
inherited Destroy;
|
||||||
|
end;
|
||||||
|
|
||||||
function TWatchesDlg.GetSelected: TIdeWatch;
|
function TWatchesDlg.GetSelected: TIdeWatch;
|
||||||
begin
|
begin
|
||||||
Result := TIdeWatch(tvWatches.FocusedItem(True));
|
Result := TIdeWatch(tvWatches.FocusedItem(True));
|
||||||
@ -343,10 +361,9 @@ var
|
|||||||
ItemSelected: Boolean;
|
ItemSelected: Boolean;
|
||||||
Watch, VNdWatch: TIdeWatch;
|
Watch, VNdWatch: TIdeWatch;
|
||||||
SelCanEnable, SelCanDisable: Boolean;
|
SelCanEnable, SelCanDisable: Boolean;
|
||||||
AllCanEnable, AllCanDisable: Boolean;
|
AllCanEnable, AllCanDisable, HasTopWatchSelected: Boolean;
|
||||||
VNode: PVirtualNode;
|
VNode: PVirtualNode;
|
||||||
begin
|
begin
|
||||||
if FUpdatingAll then exit;
|
|
||||||
if IsUpdating then exit;
|
if IsUpdating then exit;
|
||||||
if GetSelectedSnapshot <> nil then begin
|
if GetSelectedSnapshot <> nil then begin
|
||||||
actToggleCurrentEnable.Enabled := False;
|
actToggleCurrentEnable.Enabled := False;
|
||||||
@ -373,6 +390,7 @@ begin
|
|||||||
SelCanDisable := False;
|
SelCanDisable := False;
|
||||||
AllCanEnable := False;
|
AllCanEnable := False;
|
||||||
AllCanDisable := False;
|
AllCanDisable := False;
|
||||||
|
HasTopWatchSelected := False;
|
||||||
|
|
||||||
for VNode in tvWatches.NoInitNodes do begin
|
for VNode in tvWatches.NoInitNodes do begin
|
||||||
VNdWatch := TIdeWatch(tvWatches.NodeItem[VNode]);
|
VNdWatch := TIdeWatch(tvWatches.NodeItem[VNode]);
|
||||||
@ -380,6 +398,7 @@ begin
|
|||||||
if tvWatches.Selected[VNode] then begin
|
if tvWatches.Selected[VNode] then begin
|
||||||
SelCanEnable := SelCanEnable or not VNdWatch.Enabled;
|
SelCanEnable := SelCanEnable or not VNdWatch.Enabled;
|
||||||
SelCanDisable := SelCanDisable or VNdWatch.Enabled;
|
SelCanDisable := SelCanDisable or VNdWatch.Enabled;
|
||||||
|
HasTopWatchSelected := HasTopWatchSelected or (VNdWatch = VNdWatch.TopParentWatch);
|
||||||
end;
|
end;
|
||||||
AllCanEnable := AllCanEnable or not VNdWatch.Enabled;
|
AllCanEnable := AllCanEnable or not VNdWatch.Enabled;
|
||||||
AllCanDisable := AllCanDisable or VNdWatch.Enabled;
|
AllCanDisable := AllCanDisable or VNdWatch.Enabled;
|
||||||
@ -391,7 +410,7 @@ begin
|
|||||||
|
|
||||||
actEnableSelected.Enabled := SelCanEnable;
|
actEnableSelected.Enabled := SelCanEnable;
|
||||||
actDisableSelected.Enabled := SelCanDisable;
|
actDisableSelected.Enabled := SelCanDisable;
|
||||||
actDeleteSelected.Enabled := tvWatches.SelectedCount > 0;
|
actDeleteSelected.Enabled := (tvWatches.SelectedCount > 0) and HasTopWatchSelected;
|
||||||
|
|
||||||
actAddWatchPoint.Enabled := ItemSelected;
|
actAddWatchPoint.Enabled := ItemSelected;
|
||||||
actEvaluate.Enabled := ItemSelected;
|
actEvaluate.Enabled := ItemSelected;
|
||||||
@ -404,7 +423,7 @@ begin
|
|||||||
actCopyName.Enabled := ItemSelected;
|
actCopyName.Enabled := ItemSelected;
|
||||||
actCopyValue.Enabled := ItemSelected;
|
actCopyValue.Enabled := ItemSelected;
|
||||||
|
|
||||||
actProperties.Enabled := ItemSelected;
|
actProperties.Enabled := ItemSelected and (Watch.TopParentWatch = Watch);
|
||||||
actAddWatch.Enabled := True;
|
actAddWatch.Enabled := True;
|
||||||
actPower.Enabled := True;
|
actPower.Enabled := True;
|
||||||
|
|
||||||
@ -641,14 +660,18 @@ begin
|
|||||||
Exclude(FStateFlags, wdsfNeedDeleteAll);
|
Exclude(FStateFlags, wdsfNeedDeleteAll);
|
||||||
DisableAllActions;
|
DisableAllActions;
|
||||||
BeginUpdate;
|
BeginUpdate;
|
||||||
|
DebugBoss.Watches.CurrentWatches.BeginUpdate;
|
||||||
try
|
try
|
||||||
DisableAllActions;
|
include(FStateFlags, wdsDeleting);
|
||||||
VNode := tvWatches.GetFirst;
|
VNode := tvWatches.GetFirst;
|
||||||
while VNode <> nil do begin
|
while VNode <> nil do begin
|
||||||
tvWatches.NodeItem[VNode].Free;
|
tvWatches.NodeItem[VNode].Free;
|
||||||
VNode := tvWatches.GetFirst;
|
VNode := tvWatches.GetFirst;
|
||||||
end;
|
end;
|
||||||
|
tvWatches.Clear;
|
||||||
finally
|
finally
|
||||||
|
exclude(FStateFlags, wdsDeleting);
|
||||||
|
DebugBoss.Watches.CurrentWatches.EndUpdate;
|
||||||
EndUpdate;
|
EndUpdate;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -660,7 +683,6 @@ begin
|
|||||||
DebugLn(DBG_DATA_MONITORS, ['DebugDataWindow: TWatchesDlg.SnapshotChanged ', DbgSName(Sender), ' Upd:', IsUpdating]);
|
DebugLn(DBG_DATA_MONITORS, ['DebugDataWindow: TWatchesDlg.SnapshotChanged ', DbgSName(Sender), ' Upd:', IsUpdating]);
|
||||||
BeginUpdate;
|
BeginUpdate;
|
||||||
// prevent lvWatchesSelectItem when deleting the itews. Snapsot may have been deleted
|
// prevent lvWatchesSelectItem when deleting the itews. Snapsot may have been deleted
|
||||||
FUpdatingAll := True; // will be reset by UpdateAll
|
|
||||||
try
|
try
|
||||||
NewWatches := Watches;
|
NewWatches := Watches;
|
||||||
if FWatchesInView <> NewWatches
|
if FWatchesInView <> NewWatches
|
||||||
@ -668,7 +690,6 @@ begin
|
|||||||
FWatchesInView := NewWatches;
|
FWatchesInView := NewWatches;
|
||||||
UpdateAll;
|
UpdateAll;
|
||||||
finally
|
finally
|
||||||
FUpdatingAll := False; // wan reset by UpdateAll anyway
|
|
||||||
EndUpdate;
|
EndUpdate;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -687,6 +708,12 @@ begin
|
|||||||
else Result := WatchesMonitor.CurrentWatches;
|
else Result := WatchesMonitor.CurrentWatches;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TWatchesDlg.DoUnLockCommandProcessing(Data: PtrInt);
|
||||||
|
begin
|
||||||
|
FQueuedUnLockCommandProcessing := False;
|
||||||
|
DebugBoss.UnLockCommandProcessing;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TWatchesDlg.DoBeginUpdate;
|
procedure TWatchesDlg.DoBeginUpdate;
|
||||||
begin
|
begin
|
||||||
inherited DoBeginUpdate;
|
inherited DoBeginUpdate;
|
||||||
@ -695,15 +722,30 @@ end;
|
|||||||
|
|
||||||
procedure TWatchesDlg.DoEndUpdate;
|
procedure TWatchesDlg.DoEndUpdate;
|
||||||
begin
|
begin
|
||||||
|
if FInEndUpdate then begin
|
||||||
|
tvWatches.EndUpdate;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
inherited DoEndUpdate;
|
inherited DoEndUpdate;
|
||||||
if FUpdateAllNeeded then begin
|
if FUpdateAllNeeded then begin
|
||||||
FUpdateAllNeeded := False;
|
FInEndUpdate := True;
|
||||||
UpdateAll;
|
try
|
||||||
|
FUpdateAllNeeded := False;
|
||||||
|
UpdateAll;
|
||||||
|
if FUpdateAllNeeded then begin
|
||||||
|
FUpdateAllNeeded := False;
|
||||||
|
UpdateAll;
|
||||||
|
DebugLn(FUpdateAllNeeded, ['TWatchesDlg failed to UpdateAll']);
|
||||||
|
end;
|
||||||
|
finally
|
||||||
|
FUpdateAllNeeded := False;
|
||||||
|
FInEndUpdate := False;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
tvWatches.EndUpdate;
|
tvWatches.EndUpdate;
|
||||||
if not FUpdatingAll then
|
tvWatchesChange(nil, nil);
|
||||||
tvWatchesChange(nil, nil);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TWatchesDlg.DoWatchesChanged;
|
procedure TWatchesDlg.DoWatchesChanged;
|
||||||
@ -737,20 +779,30 @@ end;
|
|||||||
|
|
||||||
procedure TWatchesDlg.popDeleteClick(Sender: TObject);
|
procedure TWatchesDlg.popDeleteClick(Sender: TObject);
|
||||||
var
|
var
|
||||||
VNode: PVirtualNode;
|
VNode, NNode: PVirtualNode;
|
||||||
|
w: TIdeWatch;
|
||||||
begin
|
begin
|
||||||
Include(FStateFlags, wdsfNeedDeleteCurrent);
|
|
||||||
if (wdsfUpdating in FStateFlags) then exit;
|
|
||||||
Exclude(FStateFlags, wdsfNeedDeleteCurrent);
|
|
||||||
DisableAllActions;
|
DisableAllActions;
|
||||||
BeginUpdate;
|
BeginUpdate;
|
||||||
|
DebugBoss.Watches.CurrentWatches.BeginUpdate;
|
||||||
|
// Subwatches are not included in this BeginUpdate.....
|
||||||
try
|
try
|
||||||
|
include(FStateFlags, wdsDeleting);
|
||||||
VNode := tvWatches.GetFirstSelected;
|
VNode := tvWatches.GetFirstSelected;
|
||||||
while VNode <> nil do begin
|
while VNode <> nil do begin
|
||||||
tvWatches.DeleteNodeEx(VNode, True);
|
NNode := tvWatches.GetNextSelected(VNode);
|
||||||
VNode := tvWatches.GetFirstSelected;
|
w := TIdeWatch(tvWatches.NodeItem[VNode]);
|
||||||
|
if w = w.TopParentWatch then begin
|
||||||
|
if tvWatches.NodeItem[VNode] = FWatchInUpDateItem then
|
||||||
|
Include(FStateFlags, wdsfNeedDeleteCurrent)
|
||||||
|
else
|
||||||
|
tvWatches.DeleteNodeEx(VNode, True);
|
||||||
|
end;
|
||||||
|
VNode := NNode;
|
||||||
end;
|
end;
|
||||||
finally
|
finally
|
||||||
|
exclude(FStateFlags, wdsDeleting);
|
||||||
|
DebugBoss.Watches.CurrentWatches.EndUpdate;
|
||||||
EndUpdate;
|
EndUpdate;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -808,11 +860,15 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TWatchesDlg.popPropertiesClick(Sender: TObject);
|
procedure TWatchesDlg.popPropertiesClick(Sender: TObject);
|
||||||
|
var
|
||||||
|
Watch: TCurrentWatch;
|
||||||
begin
|
begin
|
||||||
if GetSelectedSnapshot <> nil then exit;
|
if GetSelectedSnapshot <> nil then exit;
|
||||||
try
|
try
|
||||||
DisableAllActions;
|
DisableAllActions;
|
||||||
DebugBoss.ShowWatchProperties(TCurrentWatch(GetSelected));
|
Watch := TCurrentWatch(GetSelected);
|
||||||
|
if (Watch.TopParentWatch = Watch) then
|
||||||
|
DebugBoss.ShowWatchProperties(Watch);
|
||||||
finally
|
finally
|
||||||
tvWatchesChange(nil, nil);
|
tvWatchesChange(nil, nil);
|
||||||
end;
|
end;
|
||||||
@ -917,16 +973,33 @@ procedure TWatchesDlg.UpdateItem(const VNode: PVirtualNode;
|
|||||||
SetLength(Result,ow);
|
SetLength(Result,ow);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
function DoDelayedDelete: Boolean;
|
||||||
|
begin
|
||||||
|
// In case the debugger did ProcessMessages, and a "delete" action was triggered
|
||||||
|
Result := FStateFlags * [wdsfNeedDeleteCurrent, wdsfNeedDeleteAll] <> [];
|
||||||
|
if Result then
|
||||||
|
exclude(FStateFlags, wdsfUpdating);
|
||||||
|
if wdsfNeedDeleteAll in FStateFlags then
|
||||||
|
popDeleteAllClick(nil)
|
||||||
|
else
|
||||||
|
if wdsfNeedDeleteCurrent in FStateFlags then begin
|
||||||
|
Exclude(FStateFlags, wdsfNeedDeleteCurrent);
|
||||||
|
tvWatches.DeleteNodeEx(VNode, True);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
var
|
var
|
||||||
WatchValue: TIdeWatchValue;
|
WatchValue: TIdeWatchValue;
|
||||||
WatchValueStr: string;
|
WatchValueStr: string;
|
||||||
|
TypInfo: TDBGType;
|
||||||
|
HasChildren, IsOuterUpdate: Boolean;
|
||||||
|
c: LongWord;
|
||||||
begin
|
begin
|
||||||
if (not ToolButtonPower.Down) or (not Visible) then exit;
|
if (not ToolButtonPower.Down) or (not Visible) then exit;
|
||||||
if (ThreadsMonitor = nil) or (CallStackMonitor = nil) then exit;
|
if (ThreadsMonitor = nil) or (CallStackMonitor = nil) then exit;
|
||||||
if GetStackframe < 0 then exit; // TODO need dedicated validity property
|
if GetStackframe < 0 then exit; // TODO need dedicated validity property
|
||||||
|
|
||||||
if wdsfUpdating in FStateFlags then begin
|
if wdsfUpdating in FStateFlags then begin
|
||||||
if FWatchInUpDateItem <> AWatch then // The watch got data while we requested it, that is fine
|
if FCurrentWatchInUpDateItem <> AWatch then // The watch got data while we requested it, that is fine
|
||||||
FUpdateAllNeeded := True;
|
FUpdateAllNeeded := True;
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
@ -934,36 +1007,130 @@ begin
|
|||||||
BeginUpdate;
|
BeginUpdate;
|
||||||
include(FStateFlags, wdsfUpdating);
|
include(FStateFlags, wdsfUpdating);
|
||||||
DebugBoss.LockCommandProcessing;
|
DebugBoss.LockCommandProcessing;
|
||||||
FWatchInUpDateItem := AWatch;
|
IsOuterUpdate := FWatchInUpDateItem = nil;
|
||||||
|
if IsOuterUpdate then
|
||||||
|
FWatchInUpDateItem := AWatch.TopParentWatch;
|
||||||
|
FCurrentWatchInUpDateItem := AWatch;
|
||||||
try
|
try
|
||||||
tvWatches.NodeText[VNode, COL_WATCH_EXPR-1]:= AWatch.Expression;
|
tvWatches.NodeText[VNode, COL_WATCH_EXPR-1]:= AWatch.Expression;
|
||||||
WatchValue := AWatch.Values[GetThreadId, GetStackframe];
|
if AWatch.HasAllValidParents(GetThreadId, GetStackframe) then begin
|
||||||
if (WatchValue <> nil) and
|
WatchValue := AWatch.Values[GetThreadId, GetStackframe];
|
||||||
( (GetSelectedSnapshot = nil) or not(WatchValue.Validity in [ddsUnknown, ddsEvaluating, ddsRequested]) )
|
if (WatchValue <> nil) and
|
||||||
then begin
|
( (GetSelectedSnapshot = nil) or not(WatchValue.Validity in [ddsUnknown, ddsEvaluating, ddsRequested]) )
|
||||||
WatchValueStr := ClearMultiline(DebugBoss.FormatValue(WatchValue.TypeInfo, WatchValue.Value));
|
then begin
|
||||||
if (WatchValue.TypeInfo <> nil) and
|
WatchValueStr := ClearMultiline(DebugBoss.FormatValue(WatchValue.TypeInfo, WatchValue.Value));
|
||||||
(WatchValue.TypeInfo.Attributes * [saArray, saDynArray] <> []) and
|
if (WatchValue.TypeInfo <> nil) and
|
||||||
(WatchValue.TypeInfo.Len >= 0)
|
(WatchValue.TypeInfo.Attributes * [saArray, saDynArray] <> []) and
|
||||||
then tvWatches.NodeText[VNode, COL_WATCH_VALUE-1] := Format(drsLen, [WatchValue.TypeInfo.Len]) + WatchValueStr
|
(WatchValue.TypeInfo.Len >= 0)
|
||||||
else tvWatches.NodeText[VNode, COL_WATCH_VALUE-1] := WatchValueStr;
|
then tvWatches.NodeText[VNode, COL_WATCH_VALUE-1] := Format(drsLen, [WatchValue.TypeInfo.Len]) + WatchValueStr
|
||||||
|
else tvWatches.NodeText[VNode, COL_WATCH_VALUE-1] := WatchValueStr;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
tvWatches.NodeText[VNode, COL_WATCH_VALUE-1]:= '<not evaluated>';
|
||||||
|
|
||||||
|
if (DebugBoss.Debugger <> nil) and (DebugBoss.Debugger.State <> dsRun) and
|
||||||
|
(WatchValue <> nil) and (WatchValue.Validity <> ddsRequested)
|
||||||
|
then begin
|
||||||
|
TypInfo := WatchValue.TypeInfo;
|
||||||
|
if DoDelayedDelete then
|
||||||
|
exit;
|
||||||
|
|
||||||
|
HasChildren := (TypInfo <> nil) and (TypInfo.Fields <> nil) and (TypInfo.Fields.Count > 0);
|
||||||
|
tvWatches.HasChildren[VNode] := HasChildren;
|
||||||
|
if HasChildren and (WatchValue.Validity = ddsValid) and tvWatches.Expanded[VNode] then begin
|
||||||
|
(* The current "AWatch" should be done. Allow UpdateItem for nested entries *)
|
||||||
|
exclude(FStateFlags, wdsfUpdating);
|
||||||
|
FCurrentWatchInUpDateItem := nil;
|
||||||
|
|
||||||
|
//AWatch.BeginChildUpdate;
|
||||||
|
UpdateSubItems(VNode, WatchValue, c);
|
||||||
|
//AWatch.EndChildUpdate; // This would currently trigger "UpdateAll" even when nothing changed, causing an endless loop
|
||||||
|
end;
|
||||||
|
end;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
tvWatches.NodeText[VNode, COL_WATCH_VALUE-1]:= '<not evaluated>';
|
tvWatches.NodeText[VNode, COL_WATCH_VALUE-1]:= '<not evaluated>';
|
||||||
finally
|
|
||||||
FWatchInUpDateItem := nil;
|
|
||||||
exclude(FStateFlags, wdsfUpdating);
|
|
||||||
if wdsfNeedDeleteCurrent in FStateFlags then
|
|
||||||
popDeleteClick(nil);
|
|
||||||
if wdsfNeedDeleteAll in FStateFlags then
|
|
||||||
popDeleteAllClick(nil);
|
|
||||||
|
|
||||||
|
finally
|
||||||
|
if IsOuterUpdate then
|
||||||
|
FWatchInUpDateItem := nil;
|
||||||
|
FCurrentWatchInUpDateItem := nil;
|
||||||
|
exclude(FStateFlags, wdsfUpdating);
|
||||||
|
DoDelayedDelete;
|
||||||
EndUpdate;
|
EndUpdate;
|
||||||
DebugBoss.UnLockCommandProcessing;
|
DebugBoss.UnLockCommandProcessing;
|
||||||
tvWatches.Invalidate;
|
tvWatches.Invalidate;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TWatchesDlg.UpdateSubItems(const VNode: PVirtualNode;
|
||||||
|
const AWatchValue: TIdeWatchValue; out ChildCount: LongWord);
|
||||||
|
var
|
||||||
|
NewWatch, AWatch: TIdeWatch;
|
||||||
|
TypInfo: TDBGType;
|
||||||
|
i: Integer;
|
||||||
|
ExistingNode, nd: PVirtualNode;
|
||||||
|
begin
|
||||||
|
ChildCount := 0;
|
||||||
|
TypInfo := AWatchValue.TypeInfo;
|
||||||
|
AWatch := AWatchValue.Watch;
|
||||||
|
|
||||||
|
if (TypInfo <> nil) and (TypInfo.Fields <> nil) then begin
|
||||||
|
ChildCount := TypInfo.Fields.Count;
|
||||||
|
ExistingNode := tvWatches.GetFirstChildNoInit(VNode);
|
||||||
|
|
||||||
|
for i := 0 to TypInfo.Fields.Count-1 do begin
|
||||||
|
NewWatch := AWatch.ChildrenByName[TypInfo.Fields[i].Name];
|
||||||
|
if NewWatch = nil then begin
|
||||||
|
dec(ChildCount);
|
||||||
|
continue;
|
||||||
|
end;
|
||||||
|
if AWatch is TCurrentWatch then begin
|
||||||
|
NewWatch.DisplayFormat := wdfDefault;
|
||||||
|
NewWatch.Enabled := AWatch.Enabled;
|
||||||
|
if EnvironmentOptions.DebuggerAutoSetInstanceFromClass then
|
||||||
|
NewWatch.EvaluateFlags := [defClassAutoCast];
|
||||||
|
end;
|
||||||
|
|
||||||
|
if ExistingNode <> nil then begin
|
||||||
|
tvWatches.NodeItem[ExistingNode] := NewWatch;
|
||||||
|
nd := ExistingNode;
|
||||||
|
ExistingNode := tvWatches.GetNextSiblingNoInit(ExistingNode);
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
nd := tvWatches.AddChild(VNode, NewWatch);
|
||||||
|
end;
|
||||||
|
UpdateItem(nd, NewWatch);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
tvWatches.ChildCount[VNode] := ChildCount;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TWatchesDlg.tvWatchesInitChildren(Sender: TBaseVirtualTree;
|
||||||
|
Node: PVirtualNode; var ChildCount: Cardinal);
|
||||||
|
var
|
||||||
|
VNdWatch, NewWatch: TIdeWatch;
|
||||||
|
WatchValue: TIdeWatchValue;
|
||||||
|
begin
|
||||||
|
ChildCount := 0;
|
||||||
|
VNdWatch := TIdeWatch(tvWatches.NodeItem[Node]);
|
||||||
|
|
||||||
|
DebugBoss.LockCommandProcessing;
|
||||||
|
DebugBoss.Watches.CurrentWatches.BeginUpdate;
|
||||||
|
VNdWatch.BeginChildUpdate;
|
||||||
|
try
|
||||||
|
WatchValue := VNdWatch.Values[GetThreadId, GetStackframe];
|
||||||
|
UpdateSubItems(Node, WatchValue, ChildCount);
|
||||||
|
finally
|
||||||
|
VNdWatch.EndChildUpdate;
|
||||||
|
DebugBoss.Watches.CurrentWatches.EndUpdate;
|
||||||
|
if not FQueuedUnLockCommandProcessing then
|
||||||
|
Application.QueueAsyncCall(@DoUnLockCommandProcessing, 0);
|
||||||
|
FQueuedUnLockCommandProcessing := True;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TWatchesDlg.UpdateAll;
|
procedure TWatchesDlg.UpdateAll;
|
||||||
var
|
var
|
||||||
i, l: Integer;
|
i, l: Integer;
|
||||||
@ -982,9 +1149,8 @@ begin
|
|||||||
then Caption:= liswlWatchList + ' (' + Snap.LocationAsText + ')'
|
then Caption:= liswlWatchList + ' (' + Snap.LocationAsText + ')'
|
||||||
else Caption:= liswlWatchList;
|
else Caption:= liswlWatchList;
|
||||||
|
|
||||||
FUpdatingAll := True;
|
|
||||||
DebugBoss.LockCommandProcessing;
|
DebugBoss.LockCommandProcessing;
|
||||||
tvWatches.BeginUpdate;
|
BeginUpdate;
|
||||||
try
|
try
|
||||||
l := Watches.Count;
|
l := Watches.Count;
|
||||||
i := 0;
|
i := 0;
|
||||||
@ -997,8 +1163,7 @@ begin
|
|||||||
inc(i);
|
inc(i);
|
||||||
end;
|
end;
|
||||||
finally
|
finally
|
||||||
FUpdatingAll := False;
|
EndUpdate;
|
||||||
tvWatches.EndUpdate;
|
|
||||||
DebugBoss.UnLockCommandProcessing;
|
DebugBoss.UnLockCommandProcessing;
|
||||||
tvWatchesChange(nil, nil);
|
tvWatchesChange(nil, nil);
|
||||||
end;
|
end;
|
||||||
@ -1024,6 +1189,9 @@ procedure TWatchesDlg.WatchAdd(const ASender: TIdeWatches; const AWatch: TIdeWat
|
|||||||
var
|
var
|
||||||
VNode: PVirtualNode;
|
VNode: PVirtualNode;
|
||||||
begin
|
begin
|
||||||
|
if AWatch.Collection <> FWatchesInView then
|
||||||
|
exit;
|
||||||
|
|
||||||
BeginUpdate;
|
BeginUpdate;
|
||||||
try
|
try
|
||||||
VNode := tvWatches.FindNodeForItem(AWatch);
|
VNode := tvWatches.FindNodeForItem(AWatch);
|
||||||
@ -1044,12 +1212,15 @@ var
|
|||||||
VNode: PVirtualNode;
|
VNode: PVirtualNode;
|
||||||
begin
|
begin
|
||||||
if AWatch = nil then Exit; // TODO: update all
|
if AWatch = nil then Exit; // TODO: update all
|
||||||
if AWatch.Collection <> FWatchesInView then exit;
|
if AWatch.TopParentWatch.Collection <> FWatchesInView then exit;
|
||||||
try DebugLnEnter(DBG_DATA_MONITORS, ['DebugDataWindow: TWatchesDlg.WatchUpdate Upd:', IsUpdating, ' Watch=',AWatch.Expression]);
|
try DebugLnEnter(DBG_DATA_MONITORS, ['DebugDataWindow: TWatchesDlg.WatchUpdate Upd:', IsUpdating, ' Watch=',AWatch.Expression]);
|
||||||
|
|
||||||
|
VNode := tvWatches.FindNodeForItem(AWatch);
|
||||||
|
if (VNode = nil) and (AWatch <> AWatch.TopParentWatch) then
|
||||||
|
exit;
|
||||||
|
|
||||||
BeginUpdate;
|
BeginUpdate;
|
||||||
try
|
try
|
||||||
VNode := tvWatches.FindNodeForItem(AWatch);
|
|
||||||
if VNode = nil
|
if VNode = nil
|
||||||
then WatchAdd(ASender, AWatch)
|
then WatchAdd(ASender, AWatch)
|
||||||
else UpdateItem(VNode, AWatch);
|
else UpdateItem(VNode, AWatch);
|
||||||
@ -1064,6 +1235,8 @@ end;
|
|||||||
|
|
||||||
procedure TWatchesDlg.WatchRemove(const ASender: TIdeWatches; const AWatch: TIdeWatch);
|
procedure TWatchesDlg.WatchRemove(const ASender: TIdeWatches; const AWatch: TIdeWatch);
|
||||||
begin
|
begin
|
||||||
|
if wdsDeleting in FStateFlags then
|
||||||
|
exit;
|
||||||
tvWatches.DeleteNode(tvWatches.FindNodeForItem(AWatch));
|
tvWatches.DeleteNode(tvWatches.FindNodeForItem(AWatch));
|
||||||
tvWatchesChange(nil, nil);
|
tvWatchesChange(nil, nil);
|
||||||
end;
|
end;
|
||||||
|
Loading…
Reference in New Issue
Block a user