Skip to content

Commit 701df51

Browse files
committed
Add preference page for the stack frames grouping feature
1 parent 909b9ad commit 701df51

File tree

6 files changed

+360
-0
lines changed

6 files changed

+360
-0
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@ JavaSnippetEditor.label= Scrapbook
9898
javaStepFilterPrefName=Step Filtering
9999
javaDetailFormattersPrefName=Detail Formatters
100100

101+
javaStackFramePrefName=Stack Frames
102+
101103
javaVariableHoverLabel=Variable Values
102104
javaVariableHoverDescription=Shows the value of the selected variable when debugging.
103105

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2571,6 +2571,13 @@
25712571
id="org.eclipse.jdt.debug.ui.JavaDebugPreferencePage">
25722572
<keywordReference id="org.eclipse.jdt.debug.ui.general"/>
25732573
</page>
2574+
<page
2575+
name="%javaStackFramePrefName"
2576+
category="org.eclipse.jdt.debug.ui.JavaDebugPreferencePage"
2577+
class="org.eclipse.jdt.internal.debug.ui.JavaStackFramePreferencePage"
2578+
id="org.eclipse.jdt.debug.ui.JavaStackFramePreferencePage">
2579+
<keywordReference id="org.eclipse.jdt.debug.ui.stepFilters"/>
2580+
</page>
25742581
<page
25752582
name="%javaStepFilterPrefName"
25762583
category="org.eclipse.jdt.debug.ui.JavaDebugPreferencePage"

org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/DebugUIMessages.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,35 @@ public class DebugUIMessages extends NLS {
100100

101101
public static String JavaHotCodeReplaceListener_0;
102102

103+
public static String JavaStackFramesPreferencePage_title;
104+
public static String JavaStackFramesPreferencePage_description;
105+
public static String JavaStackFramesPreferencePage__Collapse_stack_frames;
106+
public static String JavaStackFramesPreferencePage_Defined_stack_frame_filters_for_platform;
107+
public static String JavaStackFramesPreferencePage_Defined_custom_stack_frame_filters;
108+
public static String JavaStackFramesPreferencePage_Appearance_of_stack_frames;
109+
public static String JavaStackFramesPreferencePage_category_platform;
110+
public static String JavaStackFramesPreferencePage_category_synthetic;
111+
public static String JavaStackFramesPreferencePage_category_library;
112+
public static String JavaStackFramesPreferencePage_category_test;
113+
public static String JavaStackFramesPreferencePage_category_production;
114+
public static String JavaStackFramesPreferencePage_category_custom_filter;
115+
public static String JavaStackFramesPreferencePage_Filter_platform;
116+
public static String JavaStackFramesPreferencePage_Filter_synthetic;
117+
public static String JavaStackFramesPreferencePage_Filter_library;
118+
public static String JavaStackFramesPreferencePage_Filter_test;
119+
public static String JavaStackFramesPreferencePage_Filter_production;
120+
public static String JavaStackFramesPreferencePage_Filter_custom;
121+
public static String JavaStackFramesPreferencePage_Add__Filter;
122+
public static String JavaStackFramesPreferencePage_Add__Package;
123+
public static String JavaStackFramesPreferencePage_Add__Type;
124+
public static String JavaStackFramesPreferencePage_Remove;
125+
public static String JavaStackFramesPreferencePage_Enable_All;
126+
public static String JavaStackFramesPreferencePage_Disable_All;
127+
public static String JavaStackFramesPreferencePage_Add_package_for_stack_filters;
128+
public static String JavaStackFramesPreferencePage_Select_a_package_for_stack_filter;
129+
public static String JavaStackFramesPreferencePage_Add_type_for_stack_filters;
130+
public static String JavaStackFramesPreferencePage_Select_a_type_for_stack_filter;
131+
103132
public static String JavaStepFilterPreferencePage_0;
104133

105134
public static String JavaStepFilterPreferencePage_Filter_co_nstructors_19;

org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/DebugUIMessages.properties

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,36 @@ JavaHotCodeReplaceListener_0=<unknown>
4747
JavaPrimitivesPreferencePage_0=Primitive Display Options
4848
JavaPrimitivesPreferencePage_1=Display options for primitive values
4949

50+
JavaStackFramesPreferencePage_title=Stack Frame Preferences
51+
JavaStackFramesPreferencePage_description=Displaying of the Stack Frames set accordingly to these filters when 'Mark Stack Frames differently' toggle is activated.
52+
JavaStackFramesPreferencePage__Collapse_stack_frames=Collapse non relevant stack frames
53+
JavaStackFramesPreferencePage_Defined_stack_frame_filters_for_platform=Filters to define &platform methods:
54+
JavaStackFramesPreferencePage_Defined_custom_stack_frame_filters=Filters for highlighted stack frames:
55+
JavaStackFramesPreferencePage_category_custom_filter=Highlighted methods
56+
JavaStackFramesPreferencePage_category_synthetic=Synthetic methods
57+
JavaStackFramesPreferencePage_category_platform=Platform methods
58+
JavaStackFramesPreferencePage_category_test=Your test code
59+
JavaStackFramesPreferencePage_category_production=Your source code
60+
JavaStackFramesPreferencePage_category_library=Library code
61+
JavaStackFramesPreferencePage_Filter_custom=Mark &highlighted stack frames differently
62+
JavaStackFramesPreferencePage_Filter_synthetic=Mark s&ynthetic methods differently
63+
JavaStackFramesPreferencePage_Filter_platform=Mark &platform methods differently
64+
JavaStackFramesPreferencePage_Filter_test=Mark your &test code differently
65+
JavaStackFramesPreferencePage_Filter_production=Mark your &source code differently
66+
JavaStackFramesPreferencePage_Filter_library=Mark &library code differently
67+
68+
JavaStackFramesPreferencePage_Add__Filter=Add &Filter...
69+
JavaStackFramesPreferencePage_Add__Package=Add &Packages...
70+
JavaStackFramesPreferencePage_Add__Type=Add &Class...
71+
JavaStackFramesPreferencePage_Remove=&Remove
72+
JavaStackFramesPreferencePage_Enable_All=&Enable All
73+
JavaStackFramesPreferencePage_Disable_All=D&isable All
74+
75+
JavaStackFramesPreferencePage_Add_package_for_stack_filters=Add Packages to Stack Filters
76+
JavaStackFramesPreferencePage_Select_a_package_for_stack_filter=&Select a package for stack filtering:
77+
JavaStackFramesPreferencePage_Add_type_for_stack_filters=Add Class to Stack Filters
78+
JavaStackFramesPreferencePage_Select_a_type_for_stack_filter=&Select a class for stack filtering:
79+
5080
JavaStepFilterPreferencePage_Filter_co_nstructors_19=Filter co&nstructors
5181
JavaStepFilterPreferencePage_Filter_s_ynthetic_methods__requires_VM_support__17=Filter s&ynthetic methods (requires VM support)
5282
JavaStepFilterPreferencePage_Filter_static__initializers_18=Filter static &initializers

org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/IJavaDebugHelpContextIds.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ public interface IJavaDebugHelpContextIds {
5252
public static final String LAUNCH_JRE_PROPERTY_PAGE= PREFIX + "launch_jre_property_page_context"; //$NON-NLS-1$
5353
public static final String JAVA_DEBUG_PREFERENCE_PAGE= PREFIX + "java_debug_preference_page_context"; //$NON-NLS-1$
5454
public static final String JAVA_STEP_FILTER_PREFERENCE_PAGE= PREFIX + "java_step_filter_preference_page_context"; //$NON-NLS-1$
55+
public static final String JAVA_STACK_FRAMES_PREFERENCE_PAGE = PREFIX + "java_stack_frames_preference_page_context"; //$NON-NLS-1$
5556
public static final String JAVA_BREAKPOINT_PREFERENCE_PAGE= PREFIX + "java_breakpoint_preference_page_context"; //$NON-NLS-1$
5657
public static final String JAVA_DETAIL_FORMATTER_PREFERENCE_PAGE= PREFIX + "java_detail_formatter_preference_page_context"; //$NON-NLS-1$
5758
public static final String JAVA_PRIMITIVES_PREFERENCE_PAGE= PREFIX + "java_primitives_preference_page_context"; //$NON-NLS-1$
Lines changed: 291 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,291 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2022, 2025 Zsombor Gegesy and others.
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+
* Zsombor Gegesy - initial API and implementation
13+
*******************************************************************************/
14+
package org.eclipse.jdt.internal.debug.ui;
15+
16+
import java.util.ArrayList;
17+
import java.util.List;
18+
import java.util.function.Consumer;
19+
20+
import org.eclipse.debug.internal.ui.SWTFactory;
21+
import org.eclipse.jdt.debug.core.IJavaStackFrame.Category;
22+
import org.eclipse.jdt.internal.ui.filtertable.Filter;
23+
import org.eclipse.jdt.internal.ui.filtertable.JavaFilterTable;
24+
import org.eclipse.jdt.internal.ui.filtertable.JavaFilterTable.ButtonLabel;
25+
import org.eclipse.jdt.internal.ui.filtertable.JavaFilterTable.DialogLabels;
26+
import org.eclipse.jdt.internal.ui.filtertable.JavaFilterTable.FilterTableConfig;
27+
import org.eclipse.jface.preference.IPreferenceStore;
28+
import org.eclipse.jface.preference.PreferencePage;
29+
import org.eclipse.swt.events.SelectionAdapter;
30+
import org.eclipse.swt.events.SelectionEvent;
31+
import org.eclipse.swt.layout.GridData;
32+
import org.eclipse.swt.widgets.Button;
33+
import org.eclipse.swt.widgets.Composite;
34+
import org.eclipse.swt.widgets.Control;
35+
import org.eclipse.ui.IWorkbench;
36+
import org.eclipse.ui.IWorkbenchPreferencePage;
37+
import org.eclipse.ui.PlatformUI;
38+
39+
/**
40+
* The preference page for Java stack frame categorization, located at the node Java > Debug > Stack Frames
41+
*
42+
* @since 3.15
43+
*/
44+
public class JavaStackFramePreferencePage extends PreferencePage implements IWorkbenchPreferencePage {
45+
46+
private static class ButtonWrapper<A> {
47+
private final Button button;
48+
protected final A key;
49+
50+
ButtonWrapper(Composite container, String label, A key, boolean checked, Consumer<Boolean> stateChangeConsumer) {
51+
this.button = SWTFactory.createCheckButton(container, label, null, checked, 2);
52+
this.key = key;
53+
if (stateChangeConsumer != null) {
54+
widgetSelected(stateChangeConsumer);
55+
}
56+
}
57+
58+
void setChecked(boolean checked) {
59+
button.setSelection(checked);
60+
}
61+
62+
boolean isChecked() {
63+
return button.getSelection();
64+
}
65+
66+
void setEnabled(boolean enabled) {
67+
this.button.setEnabled(enabled);
68+
}
69+
70+
ButtonWrapper<A> widgetSelected(Consumer<Boolean> consumer) {
71+
this.button.addSelectionListener(new SelectionAdapter() {
72+
@Override
73+
public void widgetSelected(SelectionEvent e) {
74+
consumer.accept(button.getSelection());
75+
}
76+
});
77+
return this;
78+
}
79+
80+
}
81+
82+
private static class PreferenceButton extends ButtonWrapper<String> {
83+
84+
PreferenceButton(Composite container, String label, IPreferenceStore store, String flag, Consumer<Boolean> stateChangeConsumer) {
85+
super(container, label, flag, store.getBoolean(flag), stateChangeConsumer);
86+
}
87+
88+
boolean performDefault(IPreferenceStore store) {
89+
var defValue = store.getBoolean(key);
90+
setChecked(defValue);
91+
return defValue;
92+
}
93+
94+
void performOk(IPreferenceStore store) {
95+
store.setValue(key, isChecked());
96+
}
97+
}
98+
99+
private static class CategoryButton extends ButtonWrapper<Category> {
100+
101+
CategoryButton(Composite container, String label, StackFrameCategorizer categorizer, Category category, Consumer<Boolean> stateChangeConsumer) {
102+
super(container, label, category, categorizer.isEnabled(category), stateChangeConsumer);
103+
}
104+
105+
boolean performDefault(StackFrameCategorizer store) {
106+
var defValue = store.isEnabled(key);
107+
setChecked(defValue);
108+
return defValue;
109+
}
110+
111+
void performOk(StackFrameCategorizer store) {
112+
store.setEnabled(key, isChecked());
113+
}
114+
115+
}
116+
public static final String PAGE_ID = "org.eclipse.jdt.debug.ui.JavaStackFramePreferencePage"; //$NON-NLS-1$
117+
118+
//widgets
119+
private PreferenceButton fCollapseStackFrames;
120+
private List<CategoryButton> categoryButtons;
121+
private CategoryButton fEnablePlatformButton;
122+
private CategoryButton fEnableCustomButton;
123+
private JavaFilterTable fPlatformStackFilterTable;
124+
private JavaFilterTable fCustomStackFilterTable;
125+
private StackFrameCategorizer categorizer;
126+
127+
public JavaStackFramePreferencePage() {
128+
super();
129+
setPreferenceStore(JDIDebugUIPlugin.getDefault().getPreferenceStore());
130+
setTitle(DebugUIMessages.JavaStackFramesPreferencePage_title);
131+
setDescription(DebugUIMessages.JavaStackFramesPreferencePage_description);
132+
this.categorizer = JDIDebugUIPlugin.getDefault().getStackFrameCategorizer();
133+
categoryButtons = new ArrayList<>();
134+
}
135+
136+
@Override
137+
protected Control createContents(Composite parent) {
138+
PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(), IJavaDebugHelpContextIds.JAVA_STACK_FRAMES_PREFERENCE_PAGE);
139+
// The main composite
140+
Composite composite = SWTFactory.createComposite(parent, parent.getFont(), 1, 1, GridData.FILL_BOTH, 0, 0);
141+
createStepFilterPreferences(composite);
142+
return composite;
143+
}
144+
145+
@Override
146+
public void init(IWorkbench workbench) {}
147+
148+
/**
149+
* Create a group to contain the step filter related widgets
150+
*/
151+
private void createStepFilterPreferences(Composite parent) {
152+
var store = getPreferenceStore();
153+
Composite container = SWTFactory.createComposite(parent, parent.getFont(), 2, 1, GridData.FILL_BOTH, 0, 0);
154+
155+
fCollapseStackFrames = new PreferenceButton(container, DebugUIMessages.JavaStackFramesPreferencePage__Collapse_stack_frames, store, IJDIPreferencesConstants.PREF_COLLAPSE_STACK_FRAMES, this::updateCheckboxes);
156+
initializeDialogUnits(container);
157+
158+
this.fEnableCustomButton = new CategoryButton(container, DebugUIMessages.JavaStackFramesPreferencePage_Filter_custom, categorizer, StackFrameCategorizer.CATEGORY_CUSTOM_FILTERED, //
159+
selected -> fCustomStackFilterTable.setEnabled(selected && isCategoryHandlingEnabled()));
160+
categoryButtons.add(this.fEnableCustomButton);
161+
162+
fCustomStackFilterTable = new JavaFilterTable(new JavaFilterTable.FilterStorage() {
163+
164+
@Override
165+
public Filter[] getStoredFilters(boolean defaults) {
166+
return combineFilterLists(categorizer.getActiveCustomStackFilter(), categorizer.getInactiveCustomStackFilter());
167+
}
168+
169+
@Override
170+
public void setStoredFilters(IPreferenceStore store, Filter[] filters) {
171+
categorizer.setCustomFilters(filters);
172+
}
173+
174+
},
175+
new FilterTableConfig() // configuration for the table
176+
.setAddFilter(new ButtonLabel(DebugUIMessages.JavaStackFramesPreferencePage_Add__Filter))
177+
.setAddPackage(new ButtonLabel(DebugUIMessages.JavaStackFramesPreferencePage_Add__Package))
178+
.setAddType(new ButtonLabel(DebugUIMessages.JavaStackFramesPreferencePage_Add__Type))
179+
.setRemove(new ButtonLabel(DebugUIMessages.JavaStackFramesPreferencePage_Remove))
180+
.setSelectAll(new ButtonLabel(DebugUIMessages.JavaStackFramesPreferencePage_Enable_All))
181+
.setDeselectAll(new ButtonLabel(DebugUIMessages.JavaStackFramesPreferencePage_Disable_All))
182+
.setAddPackageDialog(new DialogLabels(DebugUIMessages.JavaStackFramesPreferencePage_Add_package_for_stack_filters, DebugUIMessages.JavaStackFramesPreferencePage_Select_a_package_for_stack_filter))
183+
.setAddTypeDialog(new DialogLabels(DebugUIMessages.JavaStackFramesPreferencePage_Add_type_for_stack_filters, DebugUIMessages.JavaStackFramesPreferencePage_Select_a_package_for_stack_filter))
184+
.setLabelText(DebugUIMessages.JavaStackFramesPreferencePage_Defined_custom_stack_frame_filters)
185+
.setHelpContextId(IJavaDebugHelpContextIds.JAVA_STACK_FRAMES_PREFERENCE_PAGE));
186+
fCustomStackFilterTable.createTable(container);
187+
188+
categoryButtons.add(new CategoryButton(container, DebugUIMessages.JavaStackFramesPreferencePage_Filter_synthetic, categorizer, StackFrameCategorizer.CATEGORY_SYNTHETIC, null));
189+
190+
this.fEnablePlatformButton = new CategoryButton(container, DebugUIMessages.JavaStackFramesPreferencePage_Filter_platform, categorizer, StackFrameCategorizer.CATEGORY_PLATFORM, //
191+
selected -> fPlatformStackFilterTable.setEnabled(selected && isCategoryHandlingEnabled()));
192+
categoryButtons.add(fEnablePlatformButton);
193+
194+
fPlatformStackFilterTable = new JavaFilterTable(new JavaFilterTable.FilterStorage() {
195+
@Override
196+
public Filter[] getStoredFilters(boolean defaults) {
197+
return combineFilterLists(categorizer.getActivePlatformStackFilter(), categorizer.getInactivePlatformStackFilter());
198+
}
199+
200+
@Override
201+
public void setStoredFilters(IPreferenceStore store, Filter[] filters) {
202+
categorizer.setPlatformFilters(filters);
203+
}
204+
205+
},
206+
new FilterTableConfig()
207+
.setAddFilter(new ButtonLabel(DebugUIMessages.JavaStackFramesPreferencePage_Add__Filter))
208+
.setAddPackage(new ButtonLabel(DebugUIMessages.JavaStackFramesPreferencePage_Add__Package))
209+
.setAddType(new ButtonLabel(DebugUIMessages.JavaStackFramesPreferencePage_Add__Type))
210+
.setRemove(new ButtonLabel(DebugUIMessages.JavaStackFramesPreferencePage_Remove))
211+
.setSelectAll(new ButtonLabel(DebugUIMessages.JavaStackFramesPreferencePage_Enable_All))
212+
.setDeselectAll(new ButtonLabel(DebugUIMessages.JavaStackFramesPreferencePage_Disable_All))
213+
.setAddPackageDialog(new DialogLabels(DebugUIMessages.JavaStackFramesPreferencePage_Add_package_for_stack_filters,
214+
DebugUIMessages.JavaStackFramesPreferencePage_Select_a_package_for_stack_filter))
215+
.setAddTypeDialog(new DialogLabels(DebugUIMessages.JavaStackFramesPreferencePage_Add_type_for_stack_filters,
216+
DebugUIMessages.JavaStackFramesPreferencePage_Select_a_package_for_stack_filter))
217+
.setLabelText(DebugUIMessages.JavaStackFramesPreferencePage_Defined_stack_frame_filters_for_platform)
218+
.setHelpContextId(IJavaDebugHelpContextIds.JAVA_STACK_FRAMES_PREFERENCE_PAGE)
219+
);
220+
fPlatformStackFilterTable.createTable(container);
221+
222+
categoryButtons.add(new CategoryButton(container, DebugUIMessages.JavaStackFramesPreferencePage_Filter_test, categorizer, StackFrameCategorizer.CATEGORY_TEST, null));
223+
categoryButtons.add(new CategoryButton(container, DebugUIMessages.JavaStackFramesPreferencePage_Filter_production, categorizer, StackFrameCategorizer.CATEGORY_PRODUCTION, null));
224+
categoryButtons.add(new CategoryButton(container, DebugUIMessages.JavaStackFramesPreferencePage_Filter_library, categorizer, StackFrameCategorizer.CATEGORY_LIBRARY, null));
225+
226+
setPageEnablement(isCategoryHandlingEnabled());
227+
}
228+
229+
private static Filter[] combineFilterLists(String[] activefilters, String[] inactivefilters) {
230+
Filter[] filters = new Filter[activefilters.length + inactivefilters.length];
231+
for (int i = 0; i < activefilters.length; i++) {
232+
filters[i] = new Filter(activefilters[i], true);
233+
}
234+
for (int i = 0; i < inactivefilters.length; i++) {
235+
filters[i + activefilters.length] = new Filter(inactivefilters[i], false);
236+
}
237+
return filters;
238+
}
239+
240+
protected void updateCheckboxes(@SuppressWarnings("unused") boolean flag) {
241+
setPageEnablement(isCategoryHandlingEnabled());
242+
}
243+
244+
private boolean isCategoryHandlingEnabled() {
245+
return fCollapseStackFrames.isChecked();
246+
}
247+
248+
/**
249+
* Enables or disables the widgets on the page according to the passed boolean
250+
*
251+
* @param enabled
252+
* the new enablement status of the page's widgets
253+
*/
254+
protected void setPageEnablement(boolean enabled) {
255+
fPlatformStackFilterTable.setEnabled(enabled && fEnablePlatformButton.isChecked());
256+
fCustomStackFilterTable.setEnabled(enabled && fEnableCustomButton.isChecked());
257+
for (var categoryButton : categoryButtons) {
258+
categoryButton.setEnabled(enabled);
259+
}
260+
}
261+
262+
@Override
263+
public boolean performOk() {
264+
IPreferenceStore store = getPreferenceStore();
265+
fCollapseStackFrames.performOk(store);
266+
fPlatformStackFilterTable.performOk(store);
267+
fCustomStackFilterTable.performOk(store);
268+
for (var categoryButton : categoryButtons) {
269+
categoryButton.performOk(categorizer);
270+
}
271+
return super.performOk();
272+
}
273+
274+
@Override
275+
protected void performDefaults() {
276+
var store = getPreferenceStore();
277+
boolean enabled = fCollapseStackFrames.performDefault(store);
278+
279+
for (var categoryButton : categoryButtons) {
280+
categoryButton.performDefault(categorizer);
281+
}
282+
283+
setPageEnablement(enabled);
284+
285+
fPlatformStackFilterTable.performDefaults();
286+
fCustomStackFilterTable.performDefaults();
287+
super.performDefaults();
288+
}
289+
290+
291+
}

0 commit comments

Comments
 (0)