diff --git a/platform/platform-resources-en/src/messages/ActionsBundle.properties b/platform/platform-resources-en/src/messages/ActionsBundle.properties index a1ff4871eb68..e183ea936d99 100644 --- a/platform/platform-resources-en/src/messages/ActionsBundle.properties +++ b/platform/platform-resources-en/src/messages/ActionsBundle.properties @@ -2914,6 +2914,7 @@ action.TopStripeUnPinButton.text=Unpin group.Documentation.Navigation.text=Quick Documentation Navigation action.AddBreakpoint.text=Add Breakpoint action.AddConditionalBreakpoint.text=Add Conditional Breakpoint\u2026 +action.AddLoggingBreakpoint.text=Add Logging Breakpoint\u2026 group.XDebugger.Attach.Dialog.Settings.text=Attach dialog settings action.XDebugger.Show.Breakpoints.Over.Line.Numbers.text=Breakpoints Over Line Numbers diff --git a/platform/xdebugger-impl/resources/META-INF/xdebugger.xml b/platform/xdebugger-impl/resources/META-INF/xdebugger.xml index f7020e586eda..70429ff2d8cf 100644 --- a/platform/xdebugger-impl/resources/META-INF/xdebugger.xml +++ b/platform/xdebugger-impl/resources/META-INF/xdebugger.xml @@ -231,6 +231,7 @@ + diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/handlers/AddLineBreakpointAction.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/handlers/AddLineBreakpointAction.java index ecb078585fce..3d0285c46206 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/handlers/AddLineBreakpointAction.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/handlers/AddLineBreakpointAction.java @@ -16,9 +16,12 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.ExperimentalUI; import com.intellij.util.ModalityUiUtil; import com.intellij.xdebugger.XSourcePosition; +import com.intellij.xdebugger.breakpoints.SuspendPolicy; import com.intellij.xdebugger.impl.XDebuggerManagerImpl; import com.intellij.xdebugger.impl.XSourcePositionImpl; import com.intellij.xdebugger.impl.breakpoints.XBreakpointUtil; +import com.intellij.xdebugger.impl.breakpoints.XExpressionImpl; +import com.intellij.xdebugger.impl.breakpoints.XLineBreakpointProxy; import com.intellij.xdebugger.impl.ui.DebuggerUIUtil; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; @@ -39,9 +42,10 @@ public class AddLineBreakpointAction extends DumbAwareAction implements ActionRe if (editor == null) return; XSourcePosition position = getLineBreakpointPosition(e); assert position != null; + String selection = editor.getSelectionModel().getSelectedText(); XBreakpointUtil.toggleLineBreakpointProxy(project, position, false, editor, false, false, true) .thenAccept(bp -> { - if (bp != null && isConditional()) { + if (bp != null && editBreakpointSettings(bp, selection)) { ModalityUiUtil.invokeLaterIfNeeded(ModalityState.defaultModalityState(), () -> { EditorGutterComponentEx gutter = (EditorGutterComponentEx)editor.getGutter(); int x = -gutter.getWidth() + gutter.getLineNumberAreaOffset() + gutter.getLineNumberAreaWidth() / 2; @@ -82,13 +86,34 @@ public class AddLineBreakpointAction extends DumbAwareAction implements ActionRe return null; } - protected boolean isConditional() { + /** + * Tweak breakpoint settings after its creation. + * @return true, if a breakpoint editor UI should be shown + */ + @ApiStatus.OverrideOnly + protected boolean editBreakpointSettings(XLineBreakpointProxy bp, @Nullable String editorSelection) { return false; } public static class WithCondition extends AddLineBreakpointAction implements ActionRemoteBehaviorSpecification.FrontendOtherwiseBackend { @Override - protected boolean isConditional() { + protected boolean editBreakpointSettings(XLineBreakpointProxy bp, @Nullable String editorSelection) { + bp.setConditionEnabled(true); + bp.setConditionExpression(XExpressionImpl.fromText(editorSelection)); + return true; + } + } + + public static class WithLogging extends AddLineBreakpointAction implements ActionRemoteBehaviorSpecification.FrontendOtherwiseBackend { + @Override + protected boolean editBreakpointSettings(XLineBreakpointProxy bp, @Nullable String editorSelection) { + bp.setSuspendPolicy(SuspendPolicy.NONE); + if (editorSelection != null) { + bp.setLogExpressionObject(XExpressionImpl.fromText(editorSelection)); + } + else { + bp.setLogMessage(true); + } return true; } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XBreakpointActionsPanel.form b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XBreakpointActionsPanel.form index cb1f3e2d478c..3729b945b3ae 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XBreakpointActionsPanel.form +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XBreakpointActionsPanel.form @@ -27,15 +27,14 @@ - + - + - - - - - + + + + @@ -77,7 +76,7 @@ - + diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XBreakpointActionsPanel.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XBreakpointActionsPanel.java index 6cc5704c457d..36d86d6903f0 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XBreakpointActionsPanel.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XBreakpointActionsPanel.java @@ -2,8 +2,10 @@ package com.intellij.xdebugger.impl.breakpoints.ui; import com.intellij.openapi.project.Project; +import com.intellij.ui.components.JBCheckBox; import com.intellij.util.ui.JBUI; import com.intellij.util.ui.UIUtil; +import com.intellij.xdebugger.XDebuggerBundle; import com.intellij.xdebugger.XExpression; import com.intellij.xdebugger.XSourcePosition; import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider; @@ -25,8 +27,10 @@ import java.awt.event.ActionListener; public class XBreakpointActionsPanel extends XBreakpointPropertiesSubPanel { public static final String LOG_EXPRESSION_HISTORY_ID = "breakpointLogExpression"; + private JLabel myLogMessageLabel; private JCheckBox myLogMessageCheckBox; private JCheckBox myLogExpressionCheckBox; + private JPanel myLogExpressionCheckBoxPanel; private JPanel myLogExpressionPanel; private JPanel myContentPane; private JPanel myMainPanel; @@ -36,8 +40,14 @@ public class XBreakpointActionsPanel extends XBreakpointPropertiesSubPanel { private JCheckBox myLogStack; private @Nullable XDebuggerExpressionComboBox myLogExpressionComboBox; - public void init(Project project, @NotNull XBreakpointProxy breakpoint, @Nullable XDebuggerEditorsProvider debuggerEditorsProvider) { + private boolean myShowAllOptions; + + public void init(Project project, + @NotNull XBreakpointProxy breakpoint, + @Nullable XDebuggerEditorsProvider debuggerEditorsProvider, + boolean showAllOptions) { init(project, breakpoint); + myShowAllOptions = showAllOptions; if (debuggerEditorsProvider != null) { ActionListener listener = new ActionListener() { @Override @@ -45,6 +55,7 @@ public class XBreakpointActionsPanel extends XBreakpointPropertiesSubPanel { onCheckboxChanged(); } }; + myLogExpressionCheckBox = new JBCheckBox(XDebuggerBundle.message("xbreakpoints.log.expression.checkbox")); myLogExpressionComboBox = new XDebuggerExpressionComboBox(project, debuggerEditorsProvider, LOG_EXPRESSION_HISTORY_ID, null, true, false); myLanguageChooserPanel.add(myLogExpressionComboBox.getLanguageChooser(), BorderLayout.CENTER); @@ -100,7 +111,20 @@ public class XBreakpointActionsPanel extends XBreakpointPropertiesSubPanel { if (myLogExpressionComboBox != null) { XExpression logExpression = myBreakpoint.getLogExpressionObjectInt(); myLogExpressionComboBox.setExpression(logExpression); - myLogExpressionCheckBox.setSelected(myBreakpoint.isLogExpressionEnabled() && logExpression != null); + boolean hideCheckbox = !myShowAllOptions && logExpression == null; + myLogExpressionCheckBox.setSelected(hideCheckbox || (myBreakpoint.isLogExpressionEnabled() && logExpression != null)); + myLogExpressionCheckBoxPanel.removeAll(); + if (hideCheckbox) { + var label = new JLabel(XDebuggerBundle.message("xbreakpoints.log.expression.checkbox")); + label.setBorder(JBUI.Borders.empty(0, 4, 4, 0)); + label.setLabelFor(myLogExpressionComboBox.getComboBox()); + myLogExpressionCheckBoxPanel.add(label); + myLogExpressionPanel.setBorder(JBUI.Borders.emptyLeft(3)); + myLogMessageLabel.setBorder(JBUI.Borders.empty(0, 4, 4, 0)); // to unify with other labels + } else { + myLogExpressionCheckBoxPanel.add(myLogExpressionCheckBox); + myLogExpressionPanel.setBorder(JBUI.Borders.emptyLeft(UIUtil.getCheckBoxTextHorizontalOffset(myLogExpressionCheckBox))); + } } onCheckboxChanged(); } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.java index e814460f84f3..24e39c26684a 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.java @@ -19,10 +19,7 @@ import com.intellij.xdebugger.XDebuggerBundle; import com.intellij.xdebugger.XDebuggerManager; import com.intellij.xdebugger.XExpression; import com.intellij.xdebugger.XSourcePosition; -import com.intellij.xdebugger.breakpoints.XBreakpointManager; -import com.intellij.xdebugger.breakpoints.XBreakpointType; -import com.intellij.xdebugger.breakpoints.XLineBreakpoint; -import com.intellij.xdebugger.breakpoints.XLineBreakpointType; +import com.intellij.xdebugger.breakpoints.*; import com.intellij.xdebugger.breakpoints.ui.XBreakpointCustomPropertiesPanel; import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider; import com.intellij.xdebugger.impl.XDebuggerUtilImpl; @@ -152,7 +149,7 @@ public class XLightBreakpointPropertiesPanel implements XSuspendPolicyPanel.Dele XDebuggerEditorsProvider debuggerEditorsProvider = breakpoint.getEditorsProvider(); if (breakpointType.getVisibleStandardPanels().contains(XBreakpointType.StandardPanels.ACTIONS)) { - myActionsPanel.init(project, breakpoint, debuggerEditorsProvider); + myActionsPanel.init(project, breakpoint, debuggerEditorsProvider, myShowAllOptions); mySubPanels.add(myActionsPanel); } else { @@ -229,12 +226,17 @@ public class XLightBreakpointPropertiesPanel implements XSuspendPolicyPanel.Dele @Override public void focusGained(FocusEvent event) { JComponent compToFocus = null; - if (myConditionComboBox != null && myConditionComboBox.getComboBox().isEnabled()) { - compToFocus = myConditionComboBox.getEditorComponent(); - } - else if (breakpointType.getVisibleStandardPanels().contains(XBreakpointType.StandardPanels.ACTIONS)) { + var actionsAvailable = breakpointType.getVisibleStandardPanels().contains(XBreakpointType.StandardPanels.ACTIONS); + var conditionEditable = myConditionComboBox != null && myConditionComboBox.getComboBox().isEnabled(); + var isSuspending = breakpoint.getSuspendPolicy() != SuspendPolicy.NONE; + if (actionsAvailable && (!isSuspending || !conditionEditable)) { + // Focus actions panel in case of non-suspending breakpoint (or if condition is explicitly disabled). + // This is important for the "Add Logging Breakpoint" action which should focus on the logging expression. compToFocus = myActionsPanel.getDefaultFocusComponent(); } + else if (conditionEditable) { + compToFocus = myConditionComboBox.getEditorComponent(); + } if (compToFocus != null) { IdeFocusManager.findInstance().requestFocus(compToFocus, false); }