diff --git a/debugger/evaluatedlg.pp b/debugger/evaluatedlg.pp index 66992fc0eb..bb517a2485 100644 --- a/debugger/evaluatedlg.pp +++ b/debugger/evaluatedlg.pp @@ -49,7 +49,7 @@ uses LazarusIDEStrConsts, BaseDebugManager, InputHistory, IDEProcs, Debugger, IdeDebuggerWatchResPrinter, IdeDebuggerWatchResult, IdeDebuggerOpts, IdeDebuggerFpDbgValueConv, WatchInspectToolbar, DebuggerDlg, DebuggerStrConst, - IdeDebuggerStringConstants, EnvironmentOpts; + IdeDebuggerStringConstants, IdeDebuggerBase, EnvironmentOpts; type @@ -87,7 +87,7 @@ type public constructor Create(TheOwner: TComponent); override; destructor Destroy; override; - procedure Execute(const AExpression: String); + procedure Execute(const AExpression: String; AWatch: TWatch = nil); property EvalExpression: string read GetEvalExpression write SetEvalExpression; end; @@ -161,9 +161,12 @@ begin inherited Destroy; end; -procedure TEvaluateDlg.Execute(const AExpression: String); +procedure TEvaluateDlg.Execute(const AExpression: String; AWatch: TWatch); begin - SetEvalExpression(AExpression); + if AWatch <> nil then + WatchInspectNav1.ReadFromWatch(AWatch, AExpression) + else + SetEvalExpression(AExpression); end; procedure TEvaluateDlg.DoAddWatch(Sender: TObject); @@ -288,8 +291,13 @@ begin end; procedure TEvaluateDlg.DoAddInspect(Sender: TObject); +var + w: TIdeWatch; begin - DebugBoss.Inspect(WatchInspectNav1.Expression); + w := nil; + if WatchInspectNav1.CurrentWatchValue <> nil then + w := WatchInspectNav1.CurrentWatchValue.Watch; + DebugBoss.Inspect(WatchInspectNav1.Expression, w); end; procedure TEvaluateDlg.SetEvalExpression(const NewExpression: string); diff --git a/debugger/inspectdlg.pas b/debugger/inspectdlg.pas index 74dc926462..3ce4c102d2 100644 --- a/debugger/inspectdlg.pas +++ b/debugger/inspectdlg.pas @@ -127,7 +127,7 @@ type public constructor Create(AOwner: TComponent); override; destructor Destroy; override; - procedure Execute(const AExpression: ansistring); + procedure Execute(const AExpression: ansistring; AWatch: TWatch = nil); end; implementation @@ -1164,9 +1164,12 @@ begin end; -procedure TIDEInspectDlg.Execute(const AExpression: ansistring); +procedure TIDEInspectDlg.Execute(const AExpression: ansistring; AWatch: TWatch); begin - WatchInspectNav1.Execute(AExpression); + if AWatch <> nil then + WatchInspectNav1.ReadFromWatch(AWatch, AExpression) + else + WatchInspectNav1.Execute(AExpression); end; procedure TIDEInspectDlg.DoWatchUpdated(const ASender: TIdeWatches; @@ -1318,8 +1321,13 @@ begin end; procedure TIDEInspectDlg.DoAddEval(Sender: TObject); +var + w: TIdeWatch; begin - DebugBoss.EvaluateModify(WatchInspectNav1.Expression); + w := nil; + if WatchInspectNav1.CurrentWatchValue <> nil then + w := WatchInspectNav1.CurrentWatchValue.Watch; + DebugBoss.EvaluateModify(WatchInspectNav1.Expression, w); end; procedure TIDEInspectDlg.DoAddWatch(Sender: TObject); diff --git a/debugger/watchesdlg.pp b/debugger/watchesdlg.pp index af9a84abca..15a4cead8c 100644 --- a/debugger/watchesdlg.pp +++ b/debugger/watchesdlg.pp @@ -750,7 +750,7 @@ var begin CurWatch := GetSelected; if CurWatch <> nil then - DebugBoss.EvaluateModify(CurWatch.Expression); + DebugBoss.EvaluateModify(CurWatch.Expression, CurWatch); end; procedure TWatchesDlg.actInspectExecute(Sender: TObject); @@ -759,7 +759,7 @@ var begin CurWatch := GetSelected; if CurWatch <> nil then - DebugBoss.Inspect(CurWatch.Expression); + DebugBoss.Inspect(CurWatch.Expression, CurWatch); end; procedure TWatchesDlg.actDisableSelectedExecute(Sender: TObject); diff --git a/ide/basedebugmanager.pas b/ide/basedebugmanager.pas index 1594c662d6..3474641c9e 100644 --- a/ide/basedebugmanager.pas +++ b/ide/basedebugmanager.pas @@ -52,7 +52,8 @@ uses LazDebuggerIntf, IdeDebuggerOpts, // IDE - Debugger, SourceMarks, Project, ProjectDefs, LazarusIDEStrConsts; + Debugger, IdeDebuggerBase, SourceMarks, Project, ProjectDefs, + LazarusIDEStrConsts; type TDebugDialogType = ( @@ -188,8 +189,8 @@ type out Filename: string; AskUserIfNotFound: Boolean): Boolean; virtual; abstract; function GetFullFilename(var Filename: string; AskUserIfNotFound: Boolean): Boolean; virtual; abstract; - procedure EvaluateModify(const AExpression: String); virtual; abstract; - procedure Inspect(const AExpression: String); virtual; abstract; + procedure EvaluateModify(const AExpression: String; AWatch: TWatch = nil); virtual; abstract; + procedure Inspect(const AExpression: String; AWatch: TWatch = nil); virtual; abstract; function DoCreateBreakPoint(const AFilename: string; ALine: integer; WarnIfNoDebugger: boolean): TModalResult; virtual; abstract; @@ -213,8 +214,11 @@ type procedure CreateDebugDialog(Sender: TObject; aFormName: string; var AForm: TCustomForm; DoDisableAutoSizing: boolean); virtual; abstract; procedure ViewDebugDialog(const ADialogType: TDebugDialogType; - BringToFront: Boolean = True; Show: Boolean = true; - DoDisableAutoSizing: boolean = false); virtual; abstract; + BringToFront: Boolean = true; + Show: Boolean = true; + DoDisableAutoSizing: boolean = false; + InitFromSourceEdit: boolean = True + ); virtual; abstract; procedure ViewDisassembler(AnAddr: TDBGPtr; BringToFront: Boolean = True; Show: Boolean = true; DoDisableAutoSizing: boolean = false); virtual; abstract; diff --git a/ide/debugmanager.pas b/ide/debugmanager.pas index bf6fb892b7..65b1f57031 100644 --- a/ide/debugmanager.pas +++ b/ide/debugmanager.pas @@ -58,9 +58,9 @@ uses BreakPointsdlg, BreakPropertyDlg, LocalsDlg, WatchPropertyDlg, CallStackDlg, EvaluateDlg, RegistersDlg, AssemblerDlg, DebugOutputForm, ExceptionDlg, InspectDlg, DebugEventsForm, PseudoTerminalDlg, FeedbackDlg, ThreadDlg, - HistoryDlg, ProcessDebugger, DbgIntfBaseTypes, DbgIntfDebuggerBase, - DbgIntfMiscClasses, DbgIntfPseudoTerminal, LazDebuggerIntf, - LazDebuggerIntfBaseTypes, BaseDebugManager; + HistoryDlg, ProcessDebugger, IdeDebuggerBase, DbgIntfBaseTypes, + DbgIntfDebuggerBase, DbgIntfMiscClasses, DbgIntfPseudoTerminal, + LazDebuggerIntf, LazDebuggerIntfBaseTypes, BaseDebugManager; type @@ -253,8 +253,8 @@ type EvalFlags: TWatcheEvaluateFlags = []): Boolean; override; function Modify(const AExpression, ANewValue: String): Boolean; override; - procedure EvaluateModify(const AExpression: String); override; - procedure Inspect(const AExpression: String); override; + procedure EvaluateModify(const AExpression: String; AWatch: TWatch = nil); override; + procedure Inspect(const AExpression: String; AWatch: TWatch = nil); override; function GetFullFilename(const AUnitinfo: TDebuggerUnitInfo; out Filename: string; AskUserIfNotFound: Boolean): Boolean; override; @@ -282,7 +282,12 @@ type // Dialog routines procedure CreateDebugDialog(Sender: TObject; aFormName: string; var AForm: TCustomForm; DoDisableAutoSizing: boolean); override; - procedure ViewDebugDialog(const ADialogType: TDebugDialogType; BringToFront: Boolean = true; Show: Boolean = true; DoDisableAutoSizing: boolean = false); override; + procedure ViewDebugDialog(const ADialogType: TDebugDialogType; + BringToFront: Boolean = true; + Show: Boolean = true; + DoDisableAutoSizing: boolean = false; + InitFromSourceEdit: boolean = True + ); override; procedure ViewDisassembler(AnAddr: TDBGPtr; BringToFront: Boolean = True; Show: Boolean = true; DoDisableAutoSizing: boolean = false); override; @@ -1658,7 +1663,8 @@ begin end; procedure TDebugManager.ViewDebugDialog(const ADialogType: TDebugDialogType; - BringToFront: Boolean; Show: Boolean; DoDisableAutoSizing: boolean); + BringToFront: Boolean; Show: Boolean; DoDisableAutoSizing: boolean; + InitFromSourceEdit: boolean); const DEBUGDIALOGCLASS: array[TDebugDialogType] of TDebuggerDlgClass = ( TDbgOutputForm, TDbgEventsForm, TBreakPointsDlg, TWatchesDlg, TLocalsDlg, @@ -1711,19 +1717,21 @@ begin then begin TAssemblerDlg(CurDialog).SetLocation(FDebugger, FCurrentLocation.Address); end; - if (CurDialog is TIDEInspectDlg) and (SourceEditorManager.GetActiveSE <> nil) - then begin - if SourceEditorManager.GetActiveSE.SelectionAvailable then - TIDEInspectDlg(CurDialog).Execute(SourceEditorManager.GetActiveSE.Selection) - else - TIDEInspectDlg(CurDialog).Execute(SourceEditorManager.GetActiveSE.GetOperandAtCurrentCaret); - end; - if (CurDialog is TEvaluateDlg) and (SourceEditorManager.GetActiveSE <> nil) - then begin - if SourceEditorManager.GetActiveSE.SelectionAvailable then - TEvaluateDlg(CurDialog).Execute(SourceEditorManager.GetActiveSE.Selection) - else - TEvaluateDlg(CurDialog).Execute(SourceEditorManager.GetActiveSE.GetOperandAtCurrentCaret); + if InitFromSourceEdit then begin + if (CurDialog is TIDEInspectDlg) and (SourceEditorManager.GetActiveSE <> nil) + then begin + if SourceEditorManager.GetActiveSE.SelectionAvailable then + TIDEInspectDlg(CurDialog).Execute(SourceEditorManager.GetActiveSE.Selection) + else + TIDEInspectDlg(CurDialog).Execute(SourceEditorManager.GetActiveSE.GetOperandAtCurrentCaret); + end; + if (CurDialog is TEvaluateDlg) and (SourceEditorManager.GetActiveSE <> nil) + then begin + if SourceEditorManager.GetActiveSE.SelectionAvailable then + TEvaluateDlg(CurDialog).Execute(SourceEditorManager.GetActiveSE.Selection) + else + TEvaluateDlg(CurDialog).Execute(SourceEditorManager.GetActiveSE.GetOperandAtCurrentCaret); + end; end; end; if not DoDisableAutoSizing then @@ -3011,21 +3019,22 @@ begin and FDebugger.Modify(AExpression, ANewValue); end; -procedure TDebugManager.EvaluateModify(const AExpression: String); +procedure TDebugManager.EvaluateModify(const AExpression: String; AWatch: TWatch + ); begin if Destroying then Exit; - ViewDebugDialog(ddtEvaluate); + ViewDebugDialog(ddtEvaluate, True, True, False, False); if FDialogs[ddtEvaluate] <> nil then - TEvaluateDlg(FDialogs[ddtEvaluate]).EvalExpression := AExpression; + TEvaluateDlg(FDialogs[ddtEvaluate]).Execute(AExpression, AWatch); end; -procedure TDebugManager.Inspect(const AExpression: String); +procedure TDebugManager.Inspect(const AExpression: String; AWatch: TWatch); begin if Destroying then Exit; - ViewDebugDialog(ddtInspect); // TODO: If not yet open, this will get Expression from SourceEdit, and trigger uneeded eval. + ViewDebugDialog(ddtInspect, True, True, False, False); if FDialogs[ddtInspect] <> nil then begin - TIDEInspectDlg(FDialogs[ddtInspect]).Execute(AExpression); + TIDEInspectDlg(FDialogs[ddtInspect]).Execute(AExpression, AWatch); end; end; diff --git a/ide/packages/idedebugger/frames/watchinspecttoolbar.pas b/ide/packages/idedebugger/frames/watchinspecttoolbar.pas index e6cfb8f46c..34f2e2e072 100644 --- a/ide/packages/idedebugger/frames/watchinspecttoolbar.pas +++ b/ide/packages/idedebugger/frames/watchinspecttoolbar.pas @@ -8,7 +8,7 @@ uses Classes, SysUtils, Forms, Controls, ComCtrls, Buttons, StdCtrls, ExtCtrls, Menus, LCLType, SpinEx, IDEImagesIntf, LazUTF8, LazClasses, LazDebuggerIntf, IdeDebuggerStringConstants, ArrayNavigationFrame, IdeDebuggerOpts, Debugger, - IdeDebuggerFpDbgValueConv; + IdeDebuggerFpDbgValueConv, IdeDebuggerBase; type @@ -92,6 +92,8 @@ type FThreadsMonitor: TIdeThreadsMonitor; FCallStackMonitor: TIdeCallStackMonitor; FInspectWatches: TCurrentWatches; + FUpdateCount: Integer; + FExecAfterUpdate: Boolean; procedure ArrayNavSizeChanged(Sender: TObject); procedure DoDbpConvMenuClicked(Sender: TObject); @@ -124,7 +126,12 @@ type ADefaultEvalOpts: TWatcheEvaluateFlags ); + procedure BeginUpdate; + procedure EndUpdate; + procedure InitWatch(AWatch: TIdeWatch); + procedure ReadFromWatch(AWatch: TWatch; AlternateExpression: String = ''); + procedure Execute(const AnExpression: ansistring; ASkipHistory: Boolean = False); procedure UpdateData(AForceClear: Boolean = False);// context changed instead procedure DoContextChanged; @@ -616,6 +623,21 @@ begin FDefaultEvalOpts := ADefaultEvalOpts; end; +procedure TWatchInspectNav.BeginUpdate; +begin + if FUpdateCount = 0 then + FExecAfterUpdate := False; + inc(FUpdateCount); +end; + +procedure TWatchInspectNav.EndUpdate; +begin + if FUpdateCount > 0 then + dec(FUpdateCount); + if (FUpdateCount = 0) and FExecAfterUpdate then + UpdateData(True); +end; + procedure TWatchInspectNav.InitWatch(AWatch: TIdeWatch); var Opts: TWatcheEvaluateFlags; @@ -640,6 +662,46 @@ begin AWatch.FpDbgConverter := Conv; end; +procedure TWatchInspectNav.ReadFromWatch(AWatch: TWatch; + AlternateExpression: String); +var + i: Integer; +begin + BeginUpdate; + try + + btnUseInstance.Down := defClassAutoCast in AWatch.EvaluateFlags; + btnFunctionEval.Down := defAllowFunctionCall in AWatch.EvaluateFlags; + + if defSkipValConv in AWatch.EvaluateFlags then begin + if popConverter.Items.Count > 1 then + popConverter.Items[1].Click; + end + else if AWatch.FpDbgConverter = nil then begin + if popConverter.Items.Count > 0 then + popConverter.Items[0].Click; + end + else begin + i := DebuggerOptions.FpDbgConverterConfig.Count - 1; + while i >= 0 do begin + if DebuggerOptions.FpDbgConverterConfig.IdeItems[i] = AWatch.FpDbgConverter then begin + if popConverter.Items.Count > i+2 then + popConverter.Items[i+2].Click; + break; + end; + dec(i); + end; + end; + + if AlternateExpression <> '' then + Execute(AlternateExpression) + else + Execute(AWatch.Expression); + finally + EndUpdate; + end; +end; + procedure TWatchInspectNav.Execute(const AnExpression: ansistring; ASkipHistory: Boolean); begin @@ -709,6 +771,12 @@ var expr: String; Conv: TIdeFpDbgConverterConfig; begin + if FUpdateCount > 0 then begin + FExecAfterUpdate := True; + exit; + end; + FExecAfterUpdate := False; + if AForceClear then FInspectWatches.Clear;