Skip to content

Commit 9a14457

Browse files
committed
Add support for custom labels on breakpoints
This commit introduces the ability for users to set custom labels on breakpoints, making it easier to identify and differentiate them. Additionally, breakpoints with custom labels are visually highlighted, improving workflow and debugging efficiency.
1 parent 9bbb5b0 commit 9a14457

File tree

10 files changed

+230
-6
lines changed

10 files changed

+230
-6
lines changed

debug/org.eclipse.debug.core/core/org/eclipse/debug/core/model/Breakpoint.java

+28-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2000, 2016 IBM Corporation and others.
2+
* Copyright (c) 2000, 2025 IBM Corporation and others.
33
*
44
* This program and the accompanying materials
55
* are made available under the terms of the Eclipse Public License 2.0
@@ -45,7 +45,6 @@
4545

4646
public abstract class Breakpoint extends PlatformObject implements IBreakpoint, ITriggerPoint {
4747

48-
4948
/**
5049
* Creates a breakpoint.
5150
*
@@ -61,6 +60,13 @@ public Breakpoint() {
6160
*/
6261
private volatile IMarker fMarker;
6362

63+
/**
64+
* Attribute for custom labeling in breakpoints
65+
*
66+
* @since 3.23
67+
*/
68+
private final String LABEL = "breakpointLabel"; //$NON-NLS-1$
69+
6470
/**
6571
* @see IBreakpoint#setMarker(IMarker)
6672
*/
@@ -384,4 +390,24 @@ public String toString() {
384390
return builder.toString();
385391
}
386392

393+
/**
394+
* Returns the label associated with this breakpoint, or <code>null</code>
395+
* if no specific label was defined.
396+
*
397+
* @since 3.23
398+
*/
399+
public String getBreakpointLabel() {
400+
return getMarker().getAttribute(LABEL, null);
401+
}
402+
403+
/**
404+
* Sets a new label for the breakpoint.
405+
*
406+
* @param labelValue provide by the user
407+
* @since 3.23
408+
*/
409+
public void setBreakpointLabel(String labelValue) throws CoreException {
410+
setAttribute(LABEL, labelValue);
411+
}
412+
387413
}
Loading
Loading

debug/org.eclipse.debug.ui/plugin.properties

+2
Original file line numberDiff line numberDiff line change
@@ -418,3 +418,5 @@ debug.core.component.label = Platform Debug Core
418418
GroupLaunch.description=Launch several other configurations sequentially
419419

420420
prototype.decorator.label = Prototype Decorator
421+
breakpointLabel.label=Label
422+
breakpointLabel.tooltip=Provide a custom label to quickly identify breakpoint

debug/org.eclipse.debug.ui/plugin.xml

+9
Original file line numberDiff line numberDiff line change
@@ -1482,6 +1482,15 @@
14821482
enablesFor="+"
14831483
id="org.eclipse.debug.ui.breakpointsView.toolbar.remove">
14841484
</action>
1485+
<action
1486+
label="%breakpointLabel.label"
1487+
icon="$nl$/icons/full/elcl16/bp_label.png"
1488+
tooltip="%breakpointLabel.tooltip"
1489+
class="org.eclipse.debug.internal.ui.actions.breakpoints.BreakpointLabelAction"
1490+
menubarPath="breakpointGroup"
1491+
enablesFor="1"
1492+
id="org.eclipse.debug.ui.breakpointsView.breakpointLabel">
1493+
</action>
14851494
<action
14861495
label="%DisableAllBreakpointsAction.label"
14871496
icon="$nl$/icons/full/elcl16/disabled_co.svg"

debug/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/ActionMessages.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2000, 2020 IBM Corporation and others.
2+
* Copyright (c) 2000, 2025 IBM Corporation and others.
33
*
44
* This program and the accompanying materials
55
* are made available under the terms of the Eclipse Public License 2.0
@@ -252,4 +252,6 @@ public class ActionMessages extends NLS {
252252
public static String EnableAllBreakpointsAction_0;
253253
public static String EnableAllBreakpointsAction_1;
254254
public static String EnableAllBreakpointsAction_3;
255+
public static String BreakpointLabelDialog;
256+
255257
}

debug/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/ActionMessages.properties

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
###############################################################################
2-
# Copyright (c) 2000, 2020 IBM Corporation and others.
2+
# Copyright (c) 2000, 2025 IBM Corporation and others.
33
#
44
# This program and the accompanying materials
55
# are made available under the terms of the Eclipse Public License 2.0
@@ -235,4 +235,5 @@ VirtualFindAction_0=Error
235235
VirtualFindAction_1=Unable to locate {0} in viewer
236236

237237
ToggleBreakpointsTargetManager_defaultToggleTarget_name = Default
238-
ToggleBreakpointsTargetManager_defaultToggleTarget_description = Default
238+
ToggleBreakpointsTargetManager_defaultToggleTarget_description = Default
239+
BreakpointLabelDialog=Provide a custom label, or blank for the default label
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2025 IBM Corporation
3+
*
4+
* This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License 2.0
6+
* which accompanies this distribution, and is available at
7+
* https://www.eclipse.org/legal/epl-2.0/
8+
*
9+
* SPDX-License-Identifier: EPL-2.0
10+
*
11+
* Contributors:
12+
* IBM Corporation - initial API and implementation
13+
*******************************************************************************/
14+
package org.eclipse.debug.internal.ui.actions.breakpoints;
15+
16+
import org.eclipse.core.runtime.CoreException;
17+
import org.eclipse.debug.core.model.Breakpoint;
18+
import org.eclipse.debug.internal.ui.DebugUIPlugin;
19+
import org.eclipse.debug.internal.ui.actions.ActionMessages;
20+
import org.eclipse.debug.internal.ui.viewers.model.provisional.TreeModelViewer;
21+
import org.eclipse.debug.internal.ui.views.breakpoints.BreakpointsView;
22+
import org.eclipse.debug.ui.IDebugUIConstants;
23+
import org.eclipse.jface.action.IAction;
24+
import org.eclipse.jface.viewers.ISelection;
25+
import org.eclipse.jface.viewers.IStructuredSelection;
26+
import org.eclipse.jface.viewers.TreeSelection;
27+
import org.eclipse.swt.SWT;
28+
import org.eclipse.swt.events.KeyAdapter;
29+
import org.eclipse.swt.events.KeyEvent;
30+
import org.eclipse.swt.graphics.Font;
31+
import org.eclipse.swt.graphics.GC;
32+
import org.eclipse.swt.graphics.Point;
33+
import org.eclipse.swt.graphics.Rectangle;
34+
import org.eclipse.swt.widgets.Label;
35+
import org.eclipse.swt.widgets.Text;
36+
import org.eclipse.swt.widgets.TreeItem;
37+
import org.eclipse.swt.widgets.Widget;
38+
import org.eclipse.ui.IViewActionDelegate;
39+
import org.eclipse.ui.IViewPart;
40+
import org.eclipse.ui.IWorkbenchPage;
41+
import org.eclipse.ui.PlatformUI;
42+
43+
public class BreakpointLabelAction implements IViewActionDelegate {
44+
45+
private IViewPart fView;
46+
protected IViewPart getView() {
47+
return fView;
48+
}
49+
50+
protected void setView(IViewPart view) {
51+
fView = view;
52+
}
53+
54+
@Override
55+
public void run(IAction action) {
56+
String emptyString = ""; //$NON-NLS-1$
57+
IStructuredSelection selection = getSelection();
58+
59+
if (selection instanceof TreeSelection treeSelect && selection.getFirstElement() instanceof Breakpoint breakpoint) {
60+
if (treeSelect.size() == 1) {
61+
IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
62+
IViewPart viewPart = page.findView(IDebugUIConstants.ID_BREAKPOINT_VIEW);
63+
if (viewPart instanceof BreakpointsView breakpointView) {
64+
TreeModelViewer treeViewer = breakpointView.getTreeModelViewer();
65+
Widget item = treeViewer.findItem(treeSelect.getPaths()[0]);
66+
if (item instanceof TreeItem tree) {
67+
String current = tree.getText();
68+
Rectangle bounds;
69+
try {
70+
bounds = tree.getBounds();
71+
} catch (ArrayIndexOutOfBoundsException e) { // TreeItem having FontData [Breakpoints having
72+
// custom label]
73+
tree.setFont(null);
74+
GC gc = new GC(tree.getParent());
75+
Font currentFont = gc.getFont();
76+
gc.setFont(currentFont);
77+
Point textWidth = gc.textExtent(tree.getText());
78+
gc.dispose();
79+
bounds = tree.getBounds(0);
80+
bounds.x = bounds.x + 10;
81+
bounds.width = textWidth.x + 20;
82+
83+
}
84+
Label label = new Label(tree.getParent(), SWT.WRAP);
85+
label.setText(ActionMessages.BreakpointLabelDialog);
86+
label.setBounds(bounds.x, bounds.y - 20, label.computeSize(SWT.DEFAULT, SWT.DEFAULT).x,
87+
label.computeSize(SWT.DEFAULT, SWT.DEFAULT).y);
88+
89+
Text inlineEditor = new Text(tree.getParent(), SWT.BORDER);
90+
inlineEditor.setBounds(bounds.x, bounds.y, bounds.width, bounds.height);
91+
inlineEditor.setText(current);
92+
inlineEditor.setFocus();
93+
94+
inlineEditor.addListener(SWT.FocusOut, event -> {
95+
tree.setText(current);
96+
label.dispose();
97+
inlineEditor.dispose();
98+
99+
});
100+
inlineEditor.addKeyListener(new KeyAdapter() {
101+
@Override
102+
public void keyPressed(KeyEvent e) {
103+
if (e.keyCode == SWT.ESC) {
104+
tree.setText(current);
105+
inlineEditor.dispose();
106+
label.dispose();
107+
} else if (e.keyCode == SWT.CR) {
108+
String newLabel = inlineEditor.getText();
109+
if (!newLabel.isEmpty() && !newLabel.equals(current)) {
110+
try {
111+
breakpoint.setBreakpointLabel(newLabel);
112+
} catch (CoreException e1) {
113+
DebugUIPlugin.log(e1);
114+
}
115+
} else if (newLabel.isEmpty()) {
116+
try {
117+
breakpoint.setBreakpointLabel(null); // Set to default
118+
} catch (CoreException e2) {
119+
DebugUIPlugin.log(e2);
120+
}
121+
}
122+
inlineEditor.dispose();
123+
label.dispose();
124+
}
125+
}
126+
});
127+
tree.setText(emptyString);
128+
129+
}
130+
131+
}
132+
}
133+
}
134+
135+
}
136+
137+
protected IStructuredSelection getSelection() {
138+
return (IStructuredSelection) getView().getViewSite().getSelectionProvider().getSelection();
139+
}
140+
141+
@Override
142+
public void selectionChanged(IAction action, ISelection selection) {
143+
}
144+
145+
@Override
146+
public void init(IViewPart view) {
147+
setView(view);
148+
}
149+
150+
}

debug/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/model/elements/BreakpointLabelProvider.java

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*****************************************************************
2-
* Copyright (c) 2009, 2010 Texas Instruments and others
2+
* Copyright (c) 2009, 2025 Texas Instruments and others
33
*
44
* This program and the accompanying materials
55
* are made available under the terms of the Eclipse Public License 2.0
@@ -15,6 +15,7 @@
1515
package org.eclipse.debug.internal.ui.model.elements;
1616

1717
import org.eclipse.core.runtime.CoreException;
18+
import org.eclipse.debug.core.model.Breakpoint;
1819
import org.eclipse.debug.core.model.IBreakpoint;
1920
import org.eclipse.debug.internal.core.IInternalDebugCoreConstants;
2021
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
@@ -31,6 +32,11 @@ public class BreakpointLabelProvider extends DebugElementLabelProvider {
3132
@Override
3233
protected String getLabel(TreePath elementPath, IPresentationContext presentationContext, String columnId, int columnIndex) throws CoreException {
3334
if (columnIndex == 0) {
35+
if (elementPath.getFirstSegment() instanceof Breakpoint breakpoint) {
36+
if (breakpoint.getBreakpointLabel() != null) {
37+
return breakpoint.getBreakpointLabel();
38+
}
39+
}
3440
return super.getLabel(elementPath, presentationContext, columnId, columnIndex);
3541
} else {
3642
return IInternalDebugCoreConstants.EMPTY_STRING;

debug/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/views/launch/DebugElementHelper.java

+28
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,21 @@
1616
import java.util.HashMap;
1717
import java.util.Map;
1818

19+
import org.eclipse.debug.core.model.Breakpoint;
1920
import org.eclipse.debug.internal.ui.DelegatingModelPresentation;
2021
import org.eclipse.debug.ui.IDebugModelPresentation;
22+
import org.eclipse.debug.ui.IDebugUIConstants;
2123
import org.eclipse.jface.resource.ImageDescriptor;
24+
import org.eclipse.jface.resource.JFaceResources;
2225
import org.eclipse.jface.viewers.IColorProvider;
2326
import org.eclipse.jface.viewers.IFontProvider;
27+
import org.eclipse.swt.SWT;
2428
import org.eclipse.swt.graphics.Color;
2529
import org.eclipse.swt.graphics.Font;
2630
import org.eclipse.swt.graphics.FontData;
2731
import org.eclipse.swt.graphics.Image;
2832
import org.eclipse.swt.graphics.RGB;
33+
import org.eclipse.swt.widgets.Display;
2934

3035
/**
3136
* Translates images, colors, and fonts into image descriptors, RGBs, and font
@@ -139,6 +144,20 @@ public static RGB getForeground(Object element, IDebugModelPresentation presenta
139144
if (color != null) {
140145
return color.getRGB();
141146
}
147+
148+
if (element instanceof Breakpoint breakpoint) {
149+
if (breakpoint.getBreakpointLabel() != null) {
150+
final RGB[] rgb = new RGB[1];
151+
Display.getDefault().syncExec(() -> {
152+
Color redColor = Display.getDefault().getSystemColor(SWT.COLOR_RED);
153+
rgb[0] = redColor.getRGB();
154+
});
155+
if (rgb[0] != null) {
156+
return rgb[0];
157+
}
158+
}
159+
return null;
160+
}
142161
return null;
143162
}
144163

@@ -217,7 +236,16 @@ public static FontData getFont(Object element, IDebugModelPresentation presentat
217236
if (font != null) {
218237
return font.getFontData()[0];
219238
}
239+
if (element instanceof Breakpoint breakpoint) {
240+
if (breakpoint.getBreakpointLabel() != null) {
241+
var fontNew = JFaceResources.getFontDescriptor(IDebugUIConstants.PREF_VARIABLE_TEXT_FONT)
242+
.getFontData()[0];
243+
return new FontData(fontNew.getName(), fontNew.getHeight(), fontNew.getStyle() ^ SWT.BOLD);
244+
}
245+
246+
}
220247
return null;
248+
221249
}
222250

223251
/**

0 commit comments

Comments
 (0)