IdeDebugger: Breakpoint dialog, drag/drop breakpoints-groups to reorder

This commit is contained in:
Martin 2023-07-24 22:43:06 +02:00
parent 72907f810a
commit 4bf617c018
4 changed files with 107 additions and 16 deletions

View File

@ -54,7 +54,7 @@ type
{ TBreakPointsDlg } { TBreakPointsDlg }
TBreakPointsDlg = class(TDebuggerDlg, IFPObserver) TBreakPointsDlg = class(TBreakPointsDlgBase, IFPObserver)
actAddSourceBP: TAction; actAddSourceBP: TAction;
actAddAddressBP: TAction; actAddAddressBP: TAction;
actAddWatchPoint: TAction; actAddWatchPoint: TAction;
@ -155,7 +155,7 @@ type
FUngroupedHeader, FAddGroupedHeader: TBreakpointGroupFrame; FUngroupedHeader, FAddGroupedHeader: TBreakpointGroupFrame;
FLastTargetHeader: TBreakpointGroupFrame; FLastTargetHeader: TBreakpointGroupFrame;
function GetDropTargetGroup(ANode: PVirtualNode): TBreakpointGroupFrame; function GetDropTargetGroup(ANode: PVirtualNode): TBreakpointGroupFrame;
procedure DoDetermineDropMode(const P: TPoint; var HitInfo: THitInfo; procedure DoDetermineDropMode(const P: TPoint; var HitInfo: THitInfo;
var NodeRect: TRect; var DropMode: TDropMode); var NodeRect: TRect; var DropMode: TDropMode);
procedure Notification(AComponent: TComponent; Operation: TOperation); override; procedure Notification(AComponent: TComponent; Operation: TOperation); override;
@ -188,6 +188,7 @@ type
procedure JumpToCurrentBreakPoint; procedure JumpToCurrentBreakPoint;
procedure ShowProperties; procedure ShowProperties;
protected protected
procedure AcceptGroupHeaderDrop(ADroppedGroupFrame: TBreakpointGroupFrame; ATargetNode: PVirtualNode); override;
procedure DoBreakPointsChanged; override; procedure DoBreakPointsChanged; override;
procedure DoBeginUpdate; override; procedure DoBeginUpdate; override;
procedure DoEndUpdate; override; procedure DoEndUpdate; override;
@ -1097,6 +1098,32 @@ begin
Result := b1.Index - b2.Index; Result := b1.Index - b2.Index;
end; end;
procedure TBreakPointsDlg.AcceptGroupHeaderDrop(
ADroppedGroupFrame: TBreakpointGroupFrame; ATargetNode: PVirtualNode);
var
TargetGroupFrame: TBreakpointGroupFrame;
idx: Integer;
begin
TargetGroupFrame := GetDropTargetGroup(ATargetNode);
if (TargetGroupFrame = nil) or (TargetGroupFrame = ADroppedGroupFrame) then
exit;
if TargetGroupFrame.GroupKind <> bgfGroup then begin
ADroppedGroupFrame.BrkGroup.Index := 0;
end
else begin
if TargetGroupFrame.BrkGroup = nil then
exit;
idx := TargetGroupFrame.BrkGroup.Index;
if ADroppedGroupFrame.BrkGroup.Index > idx then
ADroppedGroupFrame.BrkGroup.Index := idx + 1
else
ADroppedGroupFrame.BrkGroup.Index := idx;
end;
end;
procedure TBreakPointsDlg.tvBreakPointsDragDrop(Sender: TBaseVirtualTree; procedure TBreakPointsDlg.tvBreakPointsDragDrop(Sender: TBaseVirtualTree;
Source: TObject; DataObject: IDataObject; Formats: TFormatArray; Source: TObject; DataObject: IDataObject; Formats: TFormatArray;
Shift: TShiftState; const Pt: TPoint; var Effect: LongWord; Mode: TDropMode); Shift: TShiftState; const Pt: TPoint; var Effect: LongWord; Mode: TDropMode);
@ -1106,10 +1133,10 @@ var
Brk: TIDEBreakPoint; Brk: TIDEBreakPoint;
idx: Integer; idx: Integer;
begin begin
TargetNd := tvBreakPoints.GetNodeAt(Pt); BeginUpdate;
if (TargetNd <> nil) and (Source = tvBreakPoints) and (tvBreakPoints.SelectedCount > 0) then begin try
BeginUpdate; TargetNd := tvBreakPoints.GetNodeAt(Pt);
try if (TargetNd <> nil) and (Source = tvBreakPoints) and (tvBreakPoints.SelectedCount > 0) then begin
TargetHeader := GetDropTargetGroup(TargetNd); TargetHeader := GetDropTargetGroup(TargetNd);
Brk := TIDEBreakPoint(tvBreakPoints.NodeItem[TargetNd]); Brk := TIDEBreakPoint(tvBreakPoints.NodeItem[TargetNd]);
if (tvBreakPoints.Header.SortColumn < 0) and (Brk <> nil) then begin if (tvBreakPoints.Header.SortColumn < 0) and (Brk <> nil) then begin
@ -1133,9 +1160,15 @@ begin
if TargetHeader <> nil then if TargetHeader <> nil then
TargetHeader.FrameDragDrop(Sender, Source, Pt.X, Pt.Y); TargetHeader.FrameDragDrop(Sender, Source, Pt.X, Pt.Y);
finally
EndUpdate;
end; end;
if (Source is TToolBar) and (TToolBar(Source).Owner is TBreakpointGroupFrame) then begin
AcceptGroupHeaderDrop(TBreakpointGroupFrame(TToolBar(Source).Owner), TargetNd);
end;
FAddGroupedHeader.Visible := False;
finally
EndUpdate;
end; end;
end; end;
@ -1175,12 +1208,18 @@ begin
FLastTargetHeader := nil; FLastTargetHeader := nil;
end; end;
if (Source is TToolBar) and (TToolBar(Source).Owner is TBreakpointGroupFrame) then begin
TargetHeader := GetDropTargetGroup(TargetNd);
Accept := (TToolBar(Source).Owner <> TargetHeader) and
(TargetHeader.GroupKind in [bgfGroup, bgfUngrouped]);
end;
end; end;
procedure TBreakPointsDlg.tvBreakPointsStartDrag(Sender: TObject; procedure TBreakPointsDlg.tvBreakPointsStartDrag(Sender: TObject;
var DragObject: TDragObject); var DragObject: TDragObject);
begin begin
FAddGroupedHeader.Visible := True; FAddGroupedHeader.Visible := True;
FDraggingGroupHeader := False;
end; end;
procedure TBreakPointsDlg.tvBreakPointsEndDrag(Sender, Target: TObject; X, procedure TBreakPointsDlg.tvBreakPointsEndDrag(Sender, Target: TObject; X,
@ -1192,18 +1231,20 @@ end;
function TBreakPointsDlg.GetDropTargetGroup(ANode: PVirtualNode function TBreakPointsDlg.GetDropTargetGroup(ANode: PVirtualNode
): TBreakpointGroupFrame; ): TBreakpointGroupFrame;
begin begin
Result := TBreakpointGroupFrame(tvBreakPoints.NodeControl[ANode]); Result := GetGroupFrame(ANode);
if Result = nil then begin if Result = nil then begin
ANode := tvBreakPoints.NodeParent[ANode]; ANode := tvBreakPoints.NodeParent[ANode];
if ANode <> nil then if ANode <> nil then
Result := TBreakpointGroupFrame(tvBreakPoints.NodeControl[ANode]); Result := GetGroupFrame(ANode);
end; end;
end; end;
procedure TBreakPointsDlg.DoDetermineDropMode(const P: TPoint; procedure TBreakPointsDlg.DoDetermineDropMode(const P: TPoint;
var HitInfo: THitInfo; var NodeRect: TRect; var DropMode: TDropMode); var HitInfo: THitInfo; var NodeRect: TRect; var DropMode: TDropMode);
begin begin
if tvBreakPoints.Header.SortColumn >= 0 then if (tvBreakPoints.Header.SortColumn >= 0) or
(FDraggingGroupHeader)
then
DropMode := dmNowhere; DropMode := dmNowhere;
end; end;

View File

@ -23,6 +23,8 @@ object BreakpointGroupFrame: TBreakpointGroupFrame
TabOrder = 0 TabOrder = 0
OnDragDrop = FrameDragDrop OnDragDrop = FrameDragDrop
OnDragOver = FrameDragOver OnDragOver = FrameDragOver
OnEndDrag = ToolBar1EndDrag
OnStartDrag = ToolBar1StartDrag
object StaticText1: TStaticText object StaticText1: TStaticText
Left = 1 Left = 1
Height = 16 Height = 16
@ -34,6 +36,7 @@ object BreakpointGroupFrame: TBreakpointGroupFrame
Caption = 'StaticText1' Caption = 'StaticText1'
OnDragDrop = FrameDragDrop OnDragDrop = FrameDragDrop
OnDragOver = FrameDragOver OnDragOver = FrameDragOver
OnMouseDown = StaticText1MouseDown
TabOrder = 0 TabOrder = 0
end end
object StaticText2: TStaticText object StaticText2: TStaticText
@ -47,6 +50,7 @@ object BreakpointGroupFrame: TBreakpointGroupFrame
Caption = 'StaticText2' Caption = 'StaticText2'
OnDragDrop = FrameDragDrop OnDragDrop = FrameDragDrop
OnDragOver = FrameDragOver OnDragOver = FrameDragOver
OnMouseDown = StaticText1MouseDown
TabOrder = 1 TabOrder = 1
end end
end end

View File

@ -7,12 +7,19 @@ interface
uses uses
Classes, SysUtils, Math, Forms, Controls, ComCtrls, StdCtrls, ExtCtrls, Classes, SysUtils, Math, Forms, Controls, ComCtrls, StdCtrls, ExtCtrls,
LCLType, Buttons, Graphics, Dialogs, laz.VirtualTrees, IDEImagesIntf, LCLType, Buttons, Graphics, Dialogs, laz.VirtualTrees, IDEImagesIntf,
DebuggerTreeView, Debugger, IdeDebuggerStringConstants, BaseDebugManager; DebuggerTreeView, Debugger, IdeDebuggerStringConstants, BaseDebugManager,
DebuggerDlg;
type type
TBreakpointGroupFrame = class; TBreakpointGroupFrame = class;
TBreakPointsDlgBase = class(TDebuggerDlg)
protected
FDraggingGroupHeader: Boolean;
procedure AcceptGroupHeaderDrop(ADroppedGroupFrame: TBreakpointGroupFrame; ATargetNode: PVirtualNode); virtual; abstract;
end;
TOnDeleteGroup = procedure(Sender: TBreakpointGroupFrame; BrkGroup: TIDEBreakPointGroup) of object; TOnDeleteGroup = procedure(Sender: TBreakpointGroupFrame; BrkGroup: TIDEBreakPointGroup) of object;
TBreakpointGroupFrameKind = (bgfUngrouped, bgfGroup, bgfAddNewGroup, bgfAbandoned); TBreakpointGroupFrameKind = (bgfUngrouped, bgfGroup, bgfAddNewGroup, bgfAbandoned);
@ -29,9 +36,14 @@ type
procedure FrameDragDrop(Sender, Source: TObject; X, Y: Integer); procedure FrameDragDrop(Sender, Source: TObject; X, Y: Integer);
procedure FrameDragOver(Sender, Source: TObject; X, Y: Integer; procedure FrameDragOver(Sender, Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean); State: TDragState; var Accept: Boolean);
procedure StaticText1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure ToolBar1EndDrag(Sender, Target: TObject; X, Y: Integer);
procedure ToolBar1StartDrag(Sender: TObject; var DragObject: TDragObject);
private private
FGroupKind: TBreakpointGroupFrameKind; FGroupKind: TBreakpointGroupFrameKind;
FOnDeleteGroup: TOnDeleteGroup; FOnDeleteGroup: TOnDeleteGroup;
FOwner: TBreakPointsDlgBase;
FTree: TDbgTreeView; FTree: TDbgTreeView;
FNode: PVirtualNode; FNode: PVirtualNode;
FBrkGroup: TIDEBreakPointGroup; FBrkGroup: TIDEBreakPointGroup;
@ -43,7 +55,7 @@ type
procedure SetVisible(Value: Boolean); reintroduce; procedure SetVisible(Value: Boolean); reintroduce;
procedure VisibleChanged; override; procedure VisibleChanged; override;
public public
constructor Create(TheOwner: TComponent; ATree: TDbgTreeView; ANode: PVirtualNode; constructor Create(TheOwner: TBreakPointsDlgBase; ATree: TDbgTreeView; ANode: PVirtualNode;
ABrkGroup: TIDEBreakPointGroup; ABrkGroup: TIDEBreakPointGroup;
AGroupKind: TBreakpointGroupFrameKind = bgfGroup); reintroduce; AGroupKind: TBreakpointGroupFrameKind = bgfGroup); reintroduce;
destructor Destroy; override; destructor Destroy; override;
@ -66,6 +78,25 @@ implementation
{ TBreakpointGroupFrame } { TBreakpointGroupFrame }
procedure TBreakpointGroupFrame.StaticText1MouseDown(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
if ToolBar1.DragMode = dmAutomatic then
ToolBar1.BeginDrag(DragManager.DragImmediate, DragManager.DragThreshold);
end;
procedure TBreakpointGroupFrame.ToolBar1EndDrag(Sender, Target: TObject; X,
Y: Integer);
begin
FOwner.FDraggingGroupHeader := False;
end;
procedure TBreakpointGroupFrame.ToolBar1StartDrag(Sender: TObject;
var DragObject: TDragObject);
begin
FOwner.FDraggingGroupHeader := True;
end;
procedure TBreakpointGroupFrame.BtnDeleteClick(Sender: TObject); procedure TBreakpointGroupFrame.BtnDeleteClick(Sender: TObject);
begin begin
if assigned(FOnDeleteGroup) then if assigned(FOnDeleteGroup) then
@ -123,6 +154,11 @@ begin
Brk.Group := NewGroup; Brk.Group := NewGroup;
end; end;
end; end;
if (Source is TToolBar) and (TToolBar(Source).Owner is TBreakpointGroupFrame) then begin
FOwner.AcceptGroupHeaderDrop(TBreakpointGroupFrame(TToolBar(Source).Owner), FNode);
end;
finally finally
if FGroupKind = bgfAddNewGroup then if FGroupKind = bgfAddNewGroup then
Visible := False; Visible := False;
@ -158,6 +194,11 @@ begin
ToolBar1.Color := clBtnFace; ToolBar1.Color := clBtnFace;
ToolBar1.Font.Color := clDefault; ToolBar1.Font.Color := clDefault;
end; end;
if (Source is TToolBar) and (TToolBar(Source).Owner is TBreakpointGroupFrame) then begin
Accept := (TToolBar(Source).Owner <> Self) and
(GroupKind in [bgfGroup, bgfUngrouped]);
end;
end; end;
function TBreakpointGroupFrame.GetCount: Integer; function TBreakpointGroupFrame.GetCount: Integer;
@ -201,11 +242,12 @@ begin
FTree.NodeHeight[FNode] := min(40, Max(15, ToolBar1.Height)); FTree.NodeHeight[FNode] := min(40, Max(15, ToolBar1.Height));
end; end;
constructor TBreakpointGroupFrame.Create(TheOwner: TComponent; constructor TBreakpointGroupFrame.Create(TheOwner: TBreakPointsDlgBase;
ATree: TDbgTreeView; ANode: PVirtualNode; ABrkGroup: TIDEBreakPointGroup; ATree: TDbgTreeView; ANode: PVirtualNode; ABrkGroup: TIDEBreakPointGroup;
AGroupKind: TBreakpointGroupFrameKind); AGroupKind: TBreakpointGroupFrameKind);
begin begin
inherited Create(nil); inherited Create(nil);
FOwner := TheOwner;
FTree := ATree; FTree := ATree;
FNode := ANode; FNode := ANode;
FBrkGroup := ABrkGroup; FBrkGroup := ABrkGroup;
@ -241,11 +283,16 @@ begin
if FBrkGroup <> nil then if FBrkGroup <> nil then
StaticText1.Caption := FBrkGroup.Name; StaticText1.Caption := FBrkGroup.Name;
StaticText2.Caption := Format(' (%d)', [Count]); StaticText2.Caption := Format(' (%d)', [Count]);
if (Count > 0) then
ToolBar1.DragMode := dmAutomatic
else
ToolBar1.DragMode := dmManual;
end; end;
bgfAddNewGroup: begin bgfAddNewGroup: begin
StaticText1.Caption := BreakViewHeaderAddGroup; StaticText1.Caption := BreakViewHeaderAddGroup;
StaticText2.Caption := ''; StaticText2.Caption := '';
StaticText1.Font.Style := [fsItalic]; ToolBar1.Font.Style := [fsItalic];
end; end;
bgfAbandoned: ; bgfAbandoned: ;
end; end;

View File

@ -94,7 +94,6 @@ type
): TCustomImageList; override; ): TCustomImageList; override;
public public
function GetNodeData(Node: PVirtualNode): PDbgTreeNodeData; reintroduce; function GetNodeData(Node: PVirtualNode): PDbgTreeNodeData; reintroduce;
function GetFocusedNode(OnlySelected: Boolean = True; AnIncludeControlNodes: Boolean = False): PVirtualNode; function GetFocusedNode(OnlySelected: Boolean = True; AnIncludeControlNodes: Boolean = False): PVirtualNode;
function FocusedData(OnlySelected: Boolean = True): PDbgTreeNodeData; function FocusedData(OnlySelected: Boolean = True): PDbgTreeNodeData;
function FocusedItem(OnlySelected: Boolean = True): TObject; function FocusedItem(OnlySelected: Boolean = True): TObject;