IdeDebugger: allow editing properties of multiple watches simultaneously

This commit is contained in:
Martin 2024-09-11 16:53:41 +02:00
parent 9f0c74432d
commit 0a25d6933a
28 changed files with 511 additions and 177 deletions

View File

@ -417,6 +417,18 @@ type
property HighlightModifiedTabs: boolean read FHighlightModifiedTabs write SetHighlightModifiedTabs;
end;
const
MULTIOPT_INT_MIX = low(integer);
MULTIOPT_INT_UNK = low(integer)+1;
procedure UpdateIntSetting(var CurVal: Integer; NewVal: integer);
procedure SetSpinEditToInherit(ASpin: TSpinEdit);
procedure IntToSpinEdit(ASpin: TSpinEdit; aVal: integer);
function BoolsetToCBState(bs: TBoolSet; ARevert: Boolean = True): TCheckBoxState;
procedure BoolFromCBState(cs: TCheckBoxState; var b: boolean; ARevert: Boolean = True);
procedure BoolFromCB(cb: TCheckBox; var b: boolean; ARevert: Boolean = True);
implementation
{$R *.lfm}
@ -435,14 +447,12 @@ const
RBA_AddrNum: TValueDisplayFormatArray = (vdfBaseHex, vdfBaseDecimal, vdfBaseOct, vdfBaseBin);
RBA_ArrayCombine: TValueDisplayFormatArrayTypeArray = (vdfatNone, vdfatAll, vdfatStat, vdfatDyn);
INT_MIX = low(integer);
INT_UNK = low(integer)+1;
procedure UpdateIntSetting(var CurVal: Integer; NewVal: integer);
begin
if (CurVal = INT_UNK) or (CurVal = NewVal)
if (CurVal = MULTIOPT_INT_UNK) or (CurVal = NewVal)
then CurVal := NewVal
else CurVal := INT_MIX;
else CurVal := MULTIOPT_INT_MIX;
end;
procedure SetSpinEditToInherit(ASpin: TSpinEdit);
@ -454,10 +464,11 @@ end;
procedure IntToSpinEdit(ASpin: TSpinEdit; aVal: integer);
begin
if (aVal = INT_MIX) or (aVal = INT_UNK) then begin
if (aVal = MULTIOPT_INT_MIX) or (aVal = MULTIOPT_INT_UNK) then begin
ASpin.Tag := 2;
ASpin.Value := 0;
ASpin.Text := '';
ASpin.Tag := 2;
end
else begin
ASpin.Tag := 0;
@ -1328,7 +1339,7 @@ begin
else SpinDigits.MaxValue := 16;
if SpinDigits.Tag = 0 then begin
FormatNumDigits := INT_UNK;
FormatNumDigits := MULTIOPT_INT_UNK;
for i := 0 to FDisplayFormatCount - 1 do
UpdateIntSetting(FormatNumDigits, FDisplayFormat[i].Num.MinDigits[FDisplayFormat[i].Num.BaseFormat]);
@ -1368,7 +1379,7 @@ begin
else Spin2Digits.MaxValue := 16;
if Spin2Digits.Tag = 0 then begin
FormatNumDigits := INT_UNK;
FormatNumDigits := MULTIOPT_INT_UNK;
for i := 0 to FDisplayFormatCount - 1 do
UpdateIntSetting(FormatNumDigits, FDisplayFormat[i].Num2.MinDigits[FDisplayFormat[i].Num2.BaseFormat]);
@ -1812,7 +1823,7 @@ begin
FormatENumValSign := [];
FormatFloat := [];
FormatFloatPrec := INT_UNK;
FormatFloatPrec := MULTIOPT_INT_UNK;
FormatStruct := [];
FormatStructPointer := [];
@ -1828,25 +1839,25 @@ begin
FormatArrayShowLen := [];
FormatArrayShowLenEmbedded := [];
FormatArrayLenMaxNest := INT_UNK;
FormatArrayLenMaxNest := MULTIOPT_INT_UNK;
FormatArrayLenCombine := [];
FormatHideLen := [];
FormatHideLenReverseDepth := INT_UNK;
FormatHideLenThresholdCnt := INT_UNK;
FormatHideLenThresholdEach := INT_UNK;
FormatHideLenThresholdFullLen := INT_UNK;
FormatHideLenReverseDepth := MULTIOPT_INT_UNK;
FormatHideLenThresholdCnt := MULTIOPT_INT_UNK;
FormatHideLenThresholdEach := MULTIOPT_INT_UNK;
FormatHideLenThresholdFullLen := MULTIOPT_INT_UNK;
FormatArrayNavAutoHide := [];
FormatArrayNavForceBounds := [];
FormatPageSize:= INT_UNK;
FormatPageSize:= MULTIOPT_INT_UNK;
FormatIndentMaxWrap := INT_UNK;
FormatIndentMaxWrap := MULTIOPT_INT_UNK;
FormatForceSingleLine := [];
FormatForceSingleLineThresholdStructFld := INT_UNK;
FormatForceSingleLineThresholdArrayLen := INT_UNK;
FormatForceSingleLineReverseDepth := INT_UNK;
FormatForceSingleLineThresholdEach := INT_UNK;
FormatForceSingleLineThresholdLen := INT_UNK;
FormatForceSingleLineThresholdStructFld := MULTIOPT_INT_UNK;
FormatForceSingleLineThresholdArrayLen := MULTIOPT_INT_UNK;
FormatForceSingleLineReverseDepth := MULTIOPT_INT_UNK;
FormatForceSingleLineThresholdEach := MULTIOPT_INT_UNK;
FormatForceSingleLineThresholdLen := MULTIOPT_INT_UNK;
FormatIsMemDump := [];

View File

@ -104,6 +104,7 @@ resourcestring
dlgBackendConvOptDefault = '- Default -';
dlgBackendConvOptDisabled = '- Disabled -';
drsRunAllThreadsWhileEvaluat = 'Run all threads while evaluating';
dlgWatchPropertyUnknown = '>> Mixed/Keep <<';
// Debugger Dialogs
lisDbgWinPower = 'On/Off';

View File

@ -650,6 +650,10 @@ msgstr ""
msgid "Delete all watches?"
msgstr ""
#: idedebuggerstringconstants.dlgwatchpropertyunknown
msgid ">> Mixed/Keep <<"
msgstr ""
#: idedebuggerstringconstants.drsaddwatch
msgctxt "idedebuggerstringconstants.drsaddwatch"
msgid "Add watch"

View File

@ -653,6 +653,10 @@ msgstr ""
msgid "Delete all watches?"
msgstr ""
#: idedebuggerstringconstants.dlgwatchpropertyunknown
msgid ">> Mixed/Keep <<"
msgstr ""
#: idedebuggerstringconstants.drsaddwatch
msgctxt "idedebuggerstringconstants.drsaddwatch"
msgid "Add watch"

View File

@ -660,6 +660,10 @@ msgstr ""
msgid "Delete all watches?"
msgstr ""
#: idedebuggerstringconstants.dlgwatchpropertyunknown
msgid ">> Mixed/Keep <<"
msgstr ""
#: idedebuggerstringconstants.drsaddwatch
msgctxt "idedebuggerstringconstants.drsaddwatch"
msgid "Add watch"

View File

@ -666,6 +666,10 @@ msgstr ""
msgid "Delete all watches?"
msgstr ""
#: idedebuggerstringconstants.dlgwatchpropertyunknown
msgid ">> Mixed/Keep <<"
msgstr ""
#: idedebuggerstringconstants.drsaddwatch
msgctxt "idedebuggerstringconstants.drsaddwatch"
msgid "Add watch"

View File

@ -665,6 +665,10 @@ msgstr ""
msgid "Delete all watches?"
msgstr ""
#: idedebuggerstringconstants.dlgwatchpropertyunknown
msgid ">> Mixed/Keep <<"
msgstr ""
#: idedebuggerstringconstants.drsaddwatch
msgctxt "idedebuggerstringconstants.drsaddwatch"
msgid "Add watch"

View File

@ -668,6 +668,10 @@ msgstr ""
msgid "Delete all watches?"
msgstr ""
#: idedebuggerstringconstants.dlgwatchpropertyunknown
msgid ">> Mixed/Keep <<"
msgstr ""
#: idedebuggerstringconstants.drsaddwatch
msgctxt "idedebuggerstringconstants.drsaddwatch"
msgid "Add watch"

View File

@ -664,6 +664,10 @@ msgstr ""
msgid "Delete all watches?"
msgstr ""
#: idedebuggerstringconstants.dlgwatchpropertyunknown
msgid ">> Mixed/Keep <<"
msgstr ""
#: idedebuggerstringconstants.drsaddwatch
msgctxt "idedebuggerstringconstants.drsaddwatch"
msgid "Add watch"

View File

@ -666,6 +666,10 @@ msgstr ""
msgid "Delete all watches?"
msgstr ""
#: idedebuggerstringconstants.dlgwatchpropertyunknown
msgid ">> Mixed/Keep <<"
msgstr ""
#: idedebuggerstringconstants.drsaddwatch
#, fuzzy
msgctxt "idedebuggerstringconstants.drsaddwatch"

View File

@ -665,6 +665,10 @@ msgstr ""
msgid "Delete all watches?"
msgstr ""
#: idedebuggerstringconstants.dlgwatchpropertyunknown
msgid ">> Mixed/Keep <<"
msgstr ""
#: idedebuggerstringconstants.drsaddwatch
msgctxt "idedebuggerstringconstants.drsaddwatch"
msgid "Add watch"

View File

@ -666,6 +666,10 @@ msgstr ""
msgid "Delete all watches?"
msgstr ""
#: idedebuggerstringconstants.dlgwatchpropertyunknown
msgid ">> Mixed/Keep <<"
msgstr ""
#: idedebuggerstringconstants.drsaddwatch
msgctxt "idedebuggerstringconstants.drsaddwatch"
msgid "Add watch"

View File

@ -660,6 +660,10 @@ msgstr ""
msgid "Delete all watches?"
msgstr ""
#: idedebuggerstringconstants.dlgwatchpropertyunknown
msgid ">> Mixed/Keep <<"
msgstr ""
#: idedebuggerstringconstants.drsaddwatch
msgctxt "idedebuggerstringconstants.drsaddwatch"
msgid "Add watch"

View File

@ -667,6 +667,10 @@ msgstr ""
msgid "Delete all watches?"
msgstr ""
#: idedebuggerstringconstants.dlgwatchpropertyunknown
msgid ">> Mixed/Keep <<"
msgstr ""
#: idedebuggerstringconstants.drsaddwatch
msgctxt "idedebuggerstringconstants.drsaddwatch"
msgid "Add watch"

View File

@ -665,6 +665,10 @@ msgstr ""
msgid "Delete all watches?"
msgstr ""
#: idedebuggerstringconstants.dlgwatchpropertyunknown
msgid ">> Mixed/Keep <<"
msgstr ""
#: idedebuggerstringconstants.drsaddwatch
msgctxt "idedebuggerstringconstants.drsaddwatch"
msgid "Add watch"

View File

@ -665,6 +665,10 @@ msgstr ""
msgid "Delete all watches?"
msgstr ""
#: idedebuggerstringconstants.dlgwatchpropertyunknown
msgid ">> Mixed/Keep <<"
msgstr ""
#: idedebuggerstringconstants.drsaddwatch
msgctxt "idedebuggerstringconstants.drsaddwatch"
msgid "Add watch"

View File

@ -660,6 +660,10 @@ msgstr ""
msgid "Delete all watches?"
msgstr ""
#: idedebuggerstringconstants.dlgwatchpropertyunknown
msgid ">> Mixed/Keep <<"
msgstr ""
#: idedebuggerstringconstants.drsaddwatch
msgctxt "idedebuggerstringconstants.drsaddwatch"
msgid "Add watch"

View File

@ -665,6 +665,10 @@ msgstr ""
msgid "Delete all watches?"
msgstr ""
#: idedebuggerstringconstants.dlgwatchpropertyunknown
msgid ">> Mixed/Keep <<"
msgstr ""
#: idedebuggerstringconstants.drsaddwatch
msgctxt "idedebuggerstringconstants.drsaddwatch"
msgid "Add watch"

View File

@ -654,6 +654,10 @@ msgstr ""
msgid "Delete all watches?"
msgstr ""
#: idedebuggerstringconstants.dlgwatchpropertyunknown
msgid ">> Mixed/Keep <<"
msgstr ""
#: idedebuggerstringconstants.drsaddwatch
msgctxt "idedebuggerstringconstants.drsaddwatch"
msgid "Add watch"

View File

@ -686,6 +686,10 @@ msgstr ""
msgid "Delete all watches?"
msgstr ""
#: idedebuggerstringconstants.dlgwatchpropertyunknown
msgid ">> Mixed/Keep <<"
msgstr ""
#: idedebuggerstringconstants.drsaddwatch
msgctxt "idedebuggerstringconstants.drsaddwatch"
msgid "Add watch"

View File

@ -666,6 +666,10 @@ msgstr "Форматирование значений"
msgid "Delete all watches?"
msgstr "Удалить все наблюдения?"
#: idedebuggerstringconstants.dlgwatchpropertyunknown
msgid ">> Mixed/Keep <<"
msgstr ""
#: idedebuggerstringconstants.drsaddwatch
msgctxt "idedebuggerstringconstants.drsaddwatch"
msgid "Add watch"

View File

@ -671,6 +671,10 @@ msgstr ""
msgid "Delete all watches?"
msgstr ""
#: idedebuggerstringconstants.dlgwatchpropertyunknown
msgid ">> Mixed/Keep <<"
msgstr ""
#: idedebuggerstringconstants.drsaddwatch
#, fuzzy
msgctxt "idedebuggerstringconstants.drsaddwatch"

View File

@ -669,6 +669,10 @@ msgstr ""
msgid "Delete all watches?"
msgstr ""
#: idedebuggerstringconstants.dlgwatchpropertyunknown
msgid ">> Mixed/Keep <<"
msgstr ""
#: idedebuggerstringconstants.drsaddwatch
msgctxt "idedebuggerstringconstants.drsaddwatch"
msgid "Add watch"

View File

@ -674,6 +674,10 @@ msgstr ""
msgid "Delete all watches?"
msgstr ""
#: idedebuggerstringconstants.dlgwatchpropertyunknown
msgid ">> Mixed/Keep <<"
msgstr ""
#: idedebuggerstringconstants.drsaddwatch
msgctxt "idedebuggerstringconstants.drsaddwatch"
msgid "Add watch"

View File

@ -671,6 +671,10 @@ msgstr ""
msgid "Delete all watches?"
msgstr ""
#: idedebuggerstringconstants.dlgwatchpropertyunknown
msgid ">> Mixed/Keep <<"
msgstr ""
#: idedebuggerstringconstants.drsaddwatch
msgctxt "idedebuggerstringconstants.drsaddwatch"
msgid "Add watch"

View File

@ -57,7 +57,7 @@ uses
Debugger, DebuggerTreeView, IdeDebuggerBase, DebuggerDlg, BaseDebugManager,
IdeDebuggerWatchResult, IdeDebuggerWatchResPrinter, IdeDebuggerUtils,
IdeDebuggerStringConstants, DbgTreeViewWatchData, EnvDebuggerOptions,
IdeDebuggerDisplayFormats, IdeDebuggerOpts, ProjectDebugLink;
IdeDebuggerDisplayFormats, IdeDebuggerOpts, ProjectDebugLink, WatchPropertyDlg;
type
@ -462,6 +462,25 @@ var
SelCanEnable, SelCanDisable: Boolean;
AllCanEnable, AllCanDisable, HasTopWatchSelected: Boolean;
VNode: PVirtualNode;
function CanProperty: boolean;
var
VPropNode: PVirtualNode;
PropWatch: TIdeWatch;
begin
if tvWatches.SelectedCount > 1 then begin
Result := False;
for VPropNode in tvWatches.SelectedItemNodes do begin
PropWatch := TCurrentWatch(tvWatches.NodeItem[VPropNode]);
if (PropWatch.TopParentWatch <> PropWatch) then
exit;
end;
Result := True;
end
else
Result := ItemSelected and (Watch.TopParentWatch = Watch)
end;
begin
if IsUpdating then exit;
if GetSelectedSnapshot <> nil then begin
@ -1169,19 +1188,41 @@ end;
procedure TWatchesDlg.popPropertiesClick(Sender: TObject);
var
Watch: TCurrentWatch;
SelWatches: array of TIdeWatch;
d: TIdeWatchValue;
dk: TWatchResultDataKind;
VNode: PVirtualNode;
i: Integer;
begin
if GetSelectedSnapshot <> nil then exit;
try
DisableAllActions;
Watch := TCurrentWatch(GetSelected);
if (Watch.TopParentWatch = Watch) then begin
d := Watch.Values[GetThreadId, GetStackframe];
dk := rdkUnknown;
if (d <> nil) and (d.Validity = ddsValid) and (d.ResultData <> nil) then
dk := d.ResultData.ValueKind;
DebugBoss.ShowWatchProperties(Watch, '', dk);
if tvWatches.SelectedCount > 1 then begin
SetLength(SelWatches, tvWatches.SelectedCount);
i := 0;
for VNode in tvWatches.SelectedItemNodes do begin
Watch := TCurrentWatch(tvWatches.NodeItem[VNode]);
if (Watch.TopParentWatch <> Watch) then
exit;
if Length(SelWatches) >= i then
SetLength(SelWatches, i + 10);
SelWatches[i] := Watch;
inc(i);
end;
SetLength(SelWatches, i);
if i > 0 then
TWatchPropertyDlg.Create(Self, SelWatches).ShowModal;
end
else begin
Watch := TCurrentWatch(GetSelected);
if (Watch.TopParentWatch = Watch) then begin
d := Watch.Values[GetThreadId, GetStackframe];
dk := rdkUnknown;
if (d <> nil) and (d.Validity = ddsValid) and (d.ResultData <> nil) then
dk := d.ResultData.ValueKind;
DebugBoss.ShowWatchProperties(Watch, '', dk);
end;
end;
finally
tvWatchesChange(nil, nil);

View File

@ -198,23 +198,6 @@ object WatchPropertyDlg: TWatchPropertyDlg
Layout = tlCenter
ParentColor = False
end
object txtRepCount: TEdit
AnchorSideLeft.Control = lblRepCount
AnchorSideLeft.Side = asrBottom
AnchorSideTop.Control = lblRepCount
AnchorSideTop.Side = asrCenter
AnchorSideRight.Control = Panel2
AnchorSideRight.Side = asrBottom
Left = 85
Height = 23
Top = 5
Width = 196
Alignment = taRightJustify
Anchors = [akTop, akLeft, akRight]
BorderSpacing.Left = 5
TabOrder = 0
Text = '0'
end
object lblFpDbgConv: TLabel
AnchorSideTop.Side = asrCenter
Left = 0
@ -231,17 +214,18 @@ object WatchPropertyDlg: TWatchPropertyDlg
AnchorSideLeft.Side = asrBottom
AnchorSideTop.Control = lblFpDbgConv
AnchorSideTop.Side = asrCenter
AnchorSideRight.Control = Panel2
AnchorSideRight.Side = asrBottom
Left = 85
Height = 23
Top = 33
Width = 227
Width = 196
Anchors = [akTop, akLeft, akRight]
BorderSpacing.Left = 5
Constraints.MinWidth = 150
ItemHeight = 15
Style = csDropDownList
TabOrder = 1
TabOrder = 0
end
object lblValFormatter: TLabel
AnchorSideTop.Side = asrCenter
@ -270,7 +254,25 @@ object WatchPropertyDlg: TWatchPropertyDlg
Constraints.MinWidth = 150
ItemHeight = 15
Style = csDropDownList
TabOrder = 1
end
object txtRepCount: TSpinEdit
AnchorSideLeft.Control = lblRepCount
AnchorSideLeft.Side = asrBottom
AnchorSideTop.Control = lblRepCount
AnchorSideTop.Side = asrCenter
AnchorSideRight.Control = Panel2
AnchorSideRight.Side = asrBottom
Left = 85
Height = 23
Top = 5
Width = 196
Alignment = taRightJustify
Anchors = [akTop, akLeft, akRight]
BorderSpacing.Left = 5
MaxValue = 9999
TabOrder = 2
OnChange = txtRepCountChange
end
end
end

View File

@ -41,7 +41,7 @@ interface
uses
Classes, SysUtils,
// LCL
Forms, StdCtrls, Extctrls, ButtonPanel,
Forms, StdCtrls, Extctrls, ButtonPanel, Spin,
// IdeIntf
IDEHelpIntf, IdeIntfStrConsts, IdeDebuggerWatchValueIntf,
// IdeConfig
@ -78,20 +78,31 @@ type
PanelTop: TPanel;
Spacer2: TLabel;
txtExpression: TEdit;
txtRepCount: TEdit;
txtRepCount: TSpinEdit;
procedure btnHelpClick(Sender: TObject);
procedure btnOKClick(Sender: TObject);
procedure chkAllowFuncChange(Sender: TObject);
procedure txtExpressionChange(Sender: TObject);
procedure txtRepCountChange(Sender: TObject);
private
FMode: (wpmWatch, wpmDispFormat);
FMode: (wpmWatch, wpmMultiWatch, wpmDispFormat);
FWatch: TIdeWatch;
FWatches: array of TIdeWatch;
FDisplayFormat: TWatchDisplayFormat;
procedure InitCaptions(AnIncludeUnknown: Boolean);
procedure InitBtnCaptions;
function ValBackConvIndex(const AWatch: TIdeWatch; AnIncludeUnknown: Boolean): integer;
function ValFormatterIndex(const AWatch: TIdeWatch; AnIncludeUnknown: Boolean): integer;
procedure ValBackConvToWatch(AWatch: TIdeWatch; AnIncludeUnknown: Boolean);
procedure ValFormatterToWach(AWatch: TIdeWatch; AnIncludeUnknown: Boolean);
protected
procedure SetVisible(Value: Boolean); override;
public
constructor Create(AOWner: TComponent; const AWatch: TIdeWatch; const AWatchExpression: String = ''; AResDataType: TWatchResultDataKind = rdkUnknown); overload;
constructor Create(AOWner: TComponent; const ADisplayFormat: TWatchDisplayFormat; AResDataType: TWatchResultDataKind; AShowMemDump: boolean = False; AShowArrayNav: boolean = False); overload;
constructor Create(AnOWner: TComponent; const AWatch: TIdeWatch; const AWatchExpression: String = ''; AResDataType: TWatchResultDataKind = rdkUnknown); overload;
constructor Create(AnOWner: TComponent; const AWatches: array of TIdeWatch); overload;
constructor Create(AnOWner: TComponent; const ADisplayFormat: TWatchDisplayFormat; AResDataType: TWatchResultDataKind; AShowMemDump: boolean = False; AShowArrayNav: boolean = False); overload;
property DisplayFormat: TWatchDisplayFormat read FDisplayFormat;
destructor Destroy; override;
end;
implementation
@ -102,69 +113,84 @@ implementation
procedure TWatchPropertyDlg.btnOKClick(Sender: TObject);
var
Conv: TIdeDbgValueConvertSelector;
VFormatter: TIdeDbgValueFormatterSelector;
Idx: Integer;
begin
if FMode = wpmDispFormat then begin
FDisplayFormat := DisplayFormatFrame1.DisplayFormat;
exit;
case FMode of
wpmWatch: begin
if txtExpression.Text = '' then
exit;
DebugBoss.Watches.CurrentWatches.BeginUpdate;
try
if FWatch = nil
then begin
FWatch := DebugBoss.Watches.CurrentWatches.Add(txtExpression.Text);
end
else begin
FWatch.Expression := txtExpression.Text;
end;
FWatch.DisplayFormat := DisplayFormatFrame1.DisplayFormat;
FWatch.EvaluateFlags := [];
if chkUseInstanceClass.Checked
then FWatch.EvaluateFlags := FWatch.EvaluateFlags + [defClassAutoCast];
if chkAllowFunc.Checked
then FWatch.EvaluateFlags := FWatch.EvaluateFlags + [defAllowFunctionCall];
if chkAllowFuncThreads.Checked
then FWatch.EvaluateFlags := FWatch.EvaluateFlags + [defFunctionCallRunAllThreads];
FWatch.RepeatCount := StrToIntDef(txtRepCount.Text, 0);
ValBackConvToWatch(FWatch, False);
ValFormatterToWach(FWatch, False);
FWatch.Enabled := chkEnabled.Checked;
finally
DebugBoss.Watches.CurrentWatches.EndUpdate;
end;
end;
wpmMultiWatch: begin
DebugBoss.Watches.CurrentWatches.BeginUpdate;
try
for Idx := 0 to Length(FWatches) - 1 do begin
FWatches[Idx].DisplayFormat := DisplayFormatFrame1.DisplayFormats[Idx];
case chkUseInstanceClass.State of
cbUnchecked: FWatches[Idx].EvaluateFlags := FWatches[Idx].EvaluateFlags - [defClassAutoCast];
cbChecked: FWatches[Idx].EvaluateFlags := FWatches[Idx].EvaluateFlags + [defClassAutoCast];
end;
case chkAllowFunc.State of
cbUnchecked: FWatches[Idx].EvaluateFlags := FWatches[Idx].EvaluateFlags - [defAllowFunctionCall];
cbChecked: FWatches[Idx].EvaluateFlags := FWatches[Idx].EvaluateFlags + [defAllowFunctionCall];
end;
case chkAllowFuncThreads.State of
cbUnchecked: FWatches[Idx].EvaluateFlags := FWatches[Idx].EvaluateFlags - [defFunctionCallRunAllThreads];
cbChecked: FWatches[Idx].EvaluateFlags := FWatches[Idx].EvaluateFlags + [defFunctionCallRunAllThreads];
end;
if txtRepCount.Tag = 0 then
FWatches[Idx].RepeatCount := txtRepCount.Value;
ValBackConvToWatch(FWatches[Idx], False);
ValFormatterToWach(FWatches[Idx], False);
case chkEnabled.State of
cbUnchecked: FWatches[Idx].Enabled := False;
cbChecked: FWatches[Idx].Enabled := True;
end;
end;
finally
DebugBoss.Watches.CurrentWatches.EndUpdate;
end;
end;
wpmDispFormat: begin
FDisplayFormat := DisplayFormatFrame1.DisplayFormat;
exit;
end;
end;
if txtExpression.Text = '' then
exit;
DebugBoss.Watches.CurrentWatches.BeginUpdate;
try
if FWatch = nil
then begin
FWatch := DebugBoss.Watches.CurrentWatches.Add(txtExpression.Text);
end
else begin
FWatch.Expression := txtExpression.Text;
end;
FWatch.DisplayFormat := DisplayFormatFrame1.DisplayFormat;
FWatch.EvaluateFlags := [];
if chkUseInstanceClass.Checked
then FWatch.EvaluateFlags := FWatch.EvaluateFlags + [defClassAutoCast];
if chkAllowFunc.Checked
then FWatch.EvaluateFlags := FWatch.EvaluateFlags + [defAllowFunctionCall];
if chkAllowFuncThreads.Checked
then FWatch.EvaluateFlags := FWatch.EvaluateFlags + [defFunctionCallRunAllThreads];
FWatch.RepeatCount := StrToIntDef(txtRepCount.Text, 0);
if dropFpDbgConv.ItemIndex = 0 then
FWatch.DbgBackendConverter := nil
else
if dropFpDbgConv.ItemIndex = 1 then
FWatch.EvaluateFlags := FWatch.EvaluateFlags + [defSkipValConv]
else begin
Conv := TIdeDbgValueConvertSelector(dropFpDbgConv.Items.Objects[dropFpDbgConv.ItemIndex]);
if (DebuggerOptions.BackendConverterConfig.IndexOf(Conv) < 0) and
(DbgProjectLink.BackendConverterConfig.IndexOf(Conv) < 0)
then
Conv := nil;
FWatch.DbgBackendConverter := Conv;
end;
if dropValFormatter.ItemIndex = 0 then
FWatch.DbgValueFormatter := nil
else
if dropValFormatter.ItemIndex = 1 then
FWatch.EvaluateFlags := FWatch.EvaluateFlags + [defSkipValueFormatter]
else begin
VFormatter := TIdeDbgValueFormatterSelector(dropValFormatter.Items.Objects[dropValFormatter.ItemIndex]);
if (DebuggerOptions.ValueFormatterConfig.IndexOf(VFormatter) < 0) and
(DbgProjectLink.ValueFormatterConfig.IndexOf(VFormatter) < 0)
then
VFormatter := nil;
FWatch.DbgValueFormatter := VFormatter;
end;
FWatch.Enabled := chkEnabled.Checked;
finally
DebugBoss.Watches.CurrentWatches.EndUpdate;
end;
end;
procedure TWatchPropertyDlg.chkAllowFuncChange(Sender: TObject);
@ -179,24 +205,184 @@ begin
ButtonPanel.OKButton.Enabled := txtExpression.Text <> '';
end;
procedure TWatchPropertyDlg.txtRepCountChange(Sender: TObject);
begin
txtRepCount.Tag := 0;
end;
procedure TWatchPropertyDlg.InitCaptions(AnIncludeUnknown: Boolean);
var
i: Integer;
begin
Caption:= lisWatchPropert;
lblExpression.Caption:= lisExpression;
lblRepCount.Caption:= lisRepeatCount;
chkEnabled.Caption:= lisEnabled;
chkAllowFunc.Caption:= lisAllowFunctio;
chkAllowFuncThreads.Caption := drsRunAllThreadsWhileEvaluat;
chkUseInstanceClass.Caption := drsUseInstanceClassType;
lblFpDbgConv.Caption := dlgBackendConvOptDebugConverter;
if AnIncludeUnknown then
dropFpDbgConv.AddItem(dlgWatchPropertyUnknown, nil);
dropFpDbgConv.AddItem(dlgBackendConvOptDefault, nil);
dropFpDbgConv.AddItem(dlgBackendConvOptDisabled, nil);
for i := 0 to DebuggerOptions.BackendConverterConfig.Count - 1 do
dropFpDbgConv.AddItem(DebuggerOptions.BackendConverterConfig.Items[i].Name, DebuggerOptions.BackendConverterConfig.Items[i]);
for i := 0 to DbgProjectLink.BackendConverterConfig.Count - 1 do
dropFpDbgConv.AddItem(DbgProjectLink.BackendConverterConfig.Items[i].Name, DbgProjectLink.BackendConverterConfig.Items[i]);
lblValFormatter.Caption := dlgVarFormatterDebugOptions;
if AnIncludeUnknown then
dropValFormatter.AddItem(dlgWatchPropertyUnknown, nil);
dropValFormatter.AddItem(dlgBackendConvOptDefault, nil);
dropValFormatter.AddItem(dlgBackendConvOptDisabled, nil);
for i := 0 to DebuggerOptions.ValueFormatterConfig.Count - 1 do
dropValFormatter.AddItem(DebuggerOptions.ValueFormatterConfig.Items[i].Name, DebuggerOptions.ValueFormatterConfig.Items[i]);
for i := 0 to DbgProjectLink.ValueFormatterConfig.Count - 1 do
dropValFormatter.AddItem(DbgProjectLink.ValueFormatterConfig.Items[i].Name, DbgProjectLink.ValueFormatterConfig.Items[i]);
dropValFormatter.ItemIndex := 0;
InitBtnCaptions;
end;
procedure TWatchPropertyDlg.InitBtnCaptions;
begin
ButtonPanel.OKButton.Caption:=lisBtnOk;
ButtonPanel.HelpButton.Caption:=lisMenuHelp;
ButtonPanel.CancelButton.Caption:=lisCancel;
end;
function TWatchPropertyDlg.ValBackConvIndex(const AWatch: TIdeWatch; AnIncludeUnknown: Boolean
): integer;
var
i: Integer;
begin
Result := 0;
if AnIncludeUnknown then
Result := 1;
if AWatch <> nil then begin
if defSkipValConv in AWatch.EvaluateFlags then begin
Result := Result + 1;
end
else
if AWatch.DbgBackendConverter <> nil then begin
i := dropFpDbgConv.Items.IndexOfObject(AWatch.DbgBackendConverter);
assert(i > 0, 'TWatchPropertyDlg.Create: i > 0');
if i > 0 then
Result := i;
end;
end;
end;
function TWatchPropertyDlg.ValFormatterIndex(const AWatch: TIdeWatch; AnIncludeUnknown: Boolean
): integer;
var
i: Integer;
begin
Result := 0;
if AnIncludeUnknown then
Result := 1;
if AWatch <> nil then begin
if defSkipValueFormatter in AWatch.EvaluateFlags then begin
Result := Result + 1;
end
else
if AWatch.DbgValueFormatter <> nil then begin
i := dropValFormatter.Items.IndexOfObject(AWatch.DbgValueFormatter);
assert(i > 0, 'TWatchPropertyDlg.Create: i > 0');
if i > 0 then
Result := i;
end;
end;
end;
procedure TWatchPropertyDlg.ValBackConvToWatch(AWatch: TIdeWatch; AnIncludeUnknown: Boolean);
var
Offs: Integer;
Conv: TIdeDbgValueConvertSelector;
begin
Offs := 0;
if AnIncludeUnknown then begin
if dropFpDbgConv.ItemIndex = 0 then
exit;
Offs := 1;
end;
if dropFpDbgConv.ItemIndex = Offs then
AWatch.DbgBackendConverter := nil
else
if dropFpDbgConv.ItemIndex = Offs+1 then
AWatch.EvaluateFlags := AWatch.EvaluateFlags + [defSkipValConv]
else begin
Conv := TIdeDbgValueConvertSelector(dropFpDbgConv.Items.Objects[dropFpDbgConv.ItemIndex]);
if (DebuggerOptions.BackendConverterConfig.IndexOf(Conv) < 0) and
(DbgProjectLink.BackendConverterConfig.IndexOf(Conv) < 0)
then
Conv := nil;
AWatch.DbgBackendConverter := Conv;
end;
end;
procedure TWatchPropertyDlg.ValFormatterToWach(AWatch: TIdeWatch; AnIncludeUnknown: Boolean);
var
Offs: Integer;
VFormatter: TIdeDbgValueFormatterSelector;
begin
Offs := 0;
if AnIncludeUnknown then begin
if dropFpDbgConv.ItemIndex = 0 then
exit;
Offs := 1;
end;
if dropValFormatter.ItemIndex = Offs then
AWatch.DbgValueFormatter := nil
else
if dropValFormatter.ItemIndex = Offs+1 then
AWatch.EvaluateFlags := AWatch.EvaluateFlags + [defSkipValueFormatter]
else begin
VFormatter := TIdeDbgValueFormatterSelector(dropValFormatter.Items.Objects[dropValFormatter.ItemIndex]);
if (DebuggerOptions.ValueFormatterConfig.IndexOf(VFormatter) < 0) and
(DbgProjectLink.ValueFormatterConfig.IndexOf(VFormatter) < 0)
then
VFormatter := nil;
AWatch.DbgValueFormatter := VFormatter;
end;
end;
procedure TWatchPropertyDlg.SetVisible(Value: Boolean);
begin
inherited SetVisible(Value);
// Issue #40875
if HandleAllocated then
if txtRepCount.Tag = 2 then begin
txtRepCount.Handle;
txtRepCount.Text := '';
txtRepCount.Tag := 2;
end;
end;
procedure TWatchPropertyDlg.btnHelpClick(Sender: TObject);
begin
LazarusHelp.ShowHelpForIDEControl(Self);
end;
constructor TWatchPropertyDlg.Create(AOWner: TComponent; const AWatch: TIdeWatch;
constructor TWatchPropertyDlg.Create(AnOWner: TComponent; const AWatch: TIdeWatch;
const AWatchExpression: String; AResDataType: TWatchResultDataKind);
var
i: Integer;
begin
FMode := wpmWatch;
FWatch := AWatch;
inherited Create(AOwner);
inherited Create(AnOwner);
PanelTop.Visible := True;
ButtonPanel.HelpButton.Visible := True;
DisplayFormatFrame1.Setup;
DisplayFormatFrame1.BeginUdpate;
DisplayFormatFrame1.ShowArrayNavBarOpts := True;
DisplayFormatFrame1.ShowMemDump := True;
try
if FWatch = nil
then begin
@ -228,74 +414,80 @@ begin
(dfEvalFunctionCalls in DebugBoss.DebuggerClass.SupportedFeatures) and
(chkAllowFunc.Checked);
Caption:= lisWatchPropert;
lblExpression.Caption:= lisExpression;
lblRepCount.Caption:= lisRepeatCount;
chkEnabled.Caption:= lisEnabled;
chkAllowFunc.Caption:= lisAllowFunctio;
chkAllowFuncThreads.Caption := drsRunAllThreadsWhileEvaluat;
chkUseInstanceClass.Caption := drsUseInstanceClassType;
InitCaptions(False);
lblFpDbgConv.Caption := dlgBackendConvOptDebugConverter;
dropFpDbgConv.AddItem(dlgBackendConvOptDefault, nil);
dropFpDbgConv.AddItem(dlgBackendConvOptDisabled, nil);
for i := 0 to DebuggerOptions.BackendConverterConfig.Count - 1 do
dropFpDbgConv.AddItem(DebuggerOptions.BackendConverterConfig.Items[i].Name, DebuggerOptions.BackendConverterConfig.Items[i]);
for i := 0 to DbgProjectLink.BackendConverterConfig.Count - 1 do
dropFpDbgConv.AddItem(DbgProjectLink.BackendConverterConfig.Items[i].Name, DbgProjectLink.BackendConverterConfig.Items[i]);
dropFpDbgConv.ItemIndex := 0;
if AWatch <> nil then begin
if defSkipValConv in AWatch.EvaluateFlags then begin
dropFpDbgConv.ItemIndex := 1;
end
else
if AWatch.DbgBackendConverter <> nil then begin
i := dropFpDbgConv.Items.IndexOfObject(AWatch.DbgBackendConverter);
assert(i > 0, 'TWatchPropertyDlg.Create: i > 0');
if i > 0 then
dropFpDbgConv.ItemIndex := i;
end;
end;
lblValFormatter.Caption := dlgVarFormatterDebugOptions;
dropValFormatter.AddItem(dlgBackendConvOptDefault, nil);
dropValFormatter.AddItem(dlgBackendConvOptDisabled, nil);
for i := 0 to DebuggerOptions.ValueFormatterConfig.Count - 1 do
dropValFormatter.AddItem(DebuggerOptions.ValueFormatterConfig.Items[i].Name, DebuggerOptions.ValueFormatterConfig.Items[i]);
for i := 0 to DbgProjectLink.ValueFormatterConfig.Count - 1 do
dropValFormatter.AddItem(DbgProjectLink.ValueFormatterConfig.Items[i].Name, DbgProjectLink.ValueFormatterConfig.Items[i]);
dropValFormatter.ItemIndex := 0;
if AWatch <> nil then begin
if defSkipValueFormatter in AWatch.EvaluateFlags then begin
dropValFormatter.ItemIndex := 1;
end
else
if AWatch.DbgValueFormatter <> nil then begin
i := dropValFormatter.Items.IndexOfObject(AWatch.DbgValueFormatter);
assert(i > 0, 'TWatchPropertyDlg.Create: i > 0');
if i > 0 then
dropValFormatter.ItemIndex := i;
end;
end;
ButtonPanel.OKButton.Caption:=lisBtnOk;
ButtonPanel.HelpButton.Caption:=lisMenuHelp;
ButtonPanel.CancelButton.Caption:=lisCancel;
dropFpDbgConv.ItemIndex := ValBackConvIndex(AWatch, False);
dropValFormatter.ItemIndex := ValFormatterIndex(AWatch, False);
end;
constructor TWatchPropertyDlg.Create(AOWner: TComponent;
constructor TWatchPropertyDlg.Create(AnOWner: TComponent; const AWatches: array of TIdeWatch);
var
Idx: Integer;
OptEnabled, OptUseInstanceClass, OptAllowFunc, OptFuncThreads: TBoolSet;
OptRepeat, OptBackend, OptValFormatter: integer;
begin
FMode := wpmMultiWatch;
inherited Create(AnOWner);
PanelTop.Visible := True;
txtExpression.Text := '';
txtExpression.Enabled := False;
InitCaptions(True);
DisplayFormatFrame1.Setup;
DisplayFormatFrame1.ShowArrayNavBarOpts := True;
DisplayFormatFrame1.ShowMemDump := True;
DisplayFormatFrame1.BeginUdpate;
try
OptEnabled := [];
OptUseInstanceClass := [];
OptAllowFunc := [];
OptFuncThreads := [];
OptRepeat := MULTIOPT_INT_UNK;
OptBackend := MULTIOPT_INT_UNK;
OptValFormatter := MULTIOPT_INT_UNK;
DisplayFormatFrame1.DisplayFormatCount := Length(AWatches);
SetLength(FWatches, Length(AWatches));
for Idx := 0 to Length(AWatches) - 1 do begin
DisplayFormatFrame1.DisplayFormats[Idx] := AWatches[Idx].DisplayFormat;
FWatches[Idx] := AWatches[Idx];
include(OptEnabled, AWatches[Idx].Enabled);
include(OptUseInstanceClass, defClassAutoCast in AWatches[Idx].EvaluateFlags);
include(OptAllowFunc, defAllowFunctionCall in AWatches[Idx].EvaluateFlags);
include(OptFuncThreads, defFunctionCallRunAllThreads in AWatches[Idx].EvaluateFlags);
UpdateIntSetting(OptRepeat, AWatches[Idx].RepeatCount);
UpdateIntSetting(OptBackend, ValBackConvIndex(AWatches[Idx], True));
UpdateIntSetting(OptValFormatter, ValFormatterIndex(AWatches[Idx], True));
end;
chkEnabled.State := BoolsetToCBState(OptEnabled, False);
chkUseInstanceClass.State := BoolsetToCBState(OptUseInstanceClass, False);
chkAllowFunc.State := BoolsetToCBState(OptAllowFunc, False);
chkAllowFuncThreads.State := BoolsetToCBState(OptFuncThreads, False);
IntToSpinEdit(txtRepCount, OptRepeat);
if OptBackend < 0 then OptBackend := 0;
if OptValFormatter < 0 then OptValFormatter := 0;
dropFpDbgConv.ItemIndex := OptBackend;
dropValFormatter.ItemIndex := OptValFormatter;
DisplayFormatFrame1.CurrentResDataType := rdkUnknown;
DisplayFormatFrame1.SelectDefaultButton;
finally
DisplayFormatFrame1.EndUdpate;
end;
end;
constructor TWatchPropertyDlg.Create(AnOWner: TComponent;
const ADisplayFormat: TWatchDisplayFormat; AResDataType: TWatchResultDataKind;
AShowMemDump: boolean; AShowArrayNav: boolean);
begin
FMode := wpmDispFormat;
inherited Create(AOWner);
inherited Create(AnOWner);
PanelTop.Visible := False;
ButtonPanel.HelpButton.Visible := False;
FDisplayFormat := ADisplayFormat;
Caption:= dlgDisplayFormatDebugOptions;
InitBtnCaptions;
DisplayFormatFrame1.Setup;
DisplayFormatFrame1.ShowArrayNavBarOpts := AShowArrayNav;
DisplayFormatFrame1.ShowMemDump := AShowMemDump;
@ -306,10 +498,5 @@ begin
DisplayFormatFrame1.EndUdpate;
end;
destructor TWatchPropertyDlg.Destroy;
begin
inherited;
end;
end.