diff --git a/bundles/com.espressif.idf.ui/plugin.xml b/bundles/com.espressif.idf.ui/plugin.xml index ba3542ed2..f14736fcb 100644 --- a/bundles/com.espressif.idf.ui/plugin.xml +++ b/bundles/com.espressif.idf.ui/plugin.xml @@ -521,6 +521,21 @@ + + + + + + + + + + diff --git a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/LaunchBarListener.java b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/LaunchBarListener.java index 983d8271d..5d79ef522 100644 --- a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/LaunchBarListener.java +++ b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/LaunchBarListener.java @@ -51,7 +51,7 @@ public static void setIgnoreTargetChange(boolean status) @Override public void activeLaunchTargetChanged(ILaunchTarget target) { - Display.getDefault().asyncExec(() -> { + Display.getDefault().syncExec(() -> { if (target != null) { String targetName = target.getAttribute("com.espressif.idf.launch.serial.core.idfTarget", //$NON-NLS-1$ diff --git a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/dialogs/Messages.java b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/dialogs/Messages.java index 54eb9de7d..113455edb 100644 --- a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/dialogs/Messages.java +++ b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/dialogs/Messages.java @@ -28,6 +28,12 @@ public class Messages extends NLS public static String HintDetailsTitle; public static String FilterMessage; public static String HintsYmlNotFoundErrMsg; + public static String SelectDebugConfigDialog_LableText; + public static String SelectDebugConfigDialog_Text; + public static String SelectDebugConfigDialog_Title; + public static String SelectLaunchConfigDialog_LableText; + public static String SelectLaunchConfigDialog_Text; + public static String SelectLaunchConfigDialog_Title; public static String WriteFlashDialog_Bin_Path_Lbl; public static String WriteFlashDialog_BinFileErrFormatErrMsg; public static String WriteFlashDialog_Browse_Btn; diff --git a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/dialogs/SelectDebugConfigDialog.java b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/dialogs/SelectDebugConfigDialog.java new file mode 100644 index 000000000..ae6649032 --- /dev/null +++ b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/dialogs/SelectDebugConfigDialog.java @@ -0,0 +1,111 @@ +/******************************************************************************* + * Copyright 2024-2025 Espressif Systems (Shanghai) PTE LTD. All rights reserved. + * Use is subject to license terms. + *******************************************************************************/ +package com.espressif.idf.ui.dialogs; + +import java.util.List; +import java.util.Optional; +import java.util.stream.Stream; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.dialogs.IMessageProvider; +import org.eclipse.jface.dialogs.TitleAreaDialog; +import org.eclipse.launchbar.core.ILaunchBarManager; +import org.eclipse.launchbar.core.ILaunchDescriptor; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; + +import com.espressif.idf.core.logging.Logger; +import com.espressif.idf.ui.UIPlugin; + +public class SelectDebugConfigDialog extends TitleAreaDialog +{ + + private Combo descriptorsCombo; + private final List suitableConfiguratios; + + public SelectDebugConfigDialog(Shell parentShell, List suitableConfiguratios) + { + super(parentShell); + this.suitableConfiguratios = suitableConfiguratios; + } + + @Override + public void create() + { + super.create(); + setTitle(Messages.SelectDebugConfigDialog_Title); + setMessage(Messages.SelectDebugConfigDialog_Text, IMessageProvider.INFORMATION); + } + + @Override + protected void configureShell(Shell newShell) + { + super.configureShell(newShell); + newShell.setText(Messages.SelectDebugConfigDialog_Title); + } + + @Override + protected void createButtonsForButtonBar(Composite parent) + { + // create OK and Cancel buttons by default + createButton(parent, IDialogConstants.OK_ID, "Debug", true); //$NON-NLS-1$ + createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false); + } + + @Override + protected Control createDialogArea(Composite parent) + { + Composite area = (Composite) super.createDialogArea(parent); + Composite container = new Composite(area, SWT.NONE); + container.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + GridLayout layout = new GridLayout(2, false); + container.setLayout(layout); + + Label descriptorsLabel = new Label(container, SWT.NONE); + descriptorsLabel.setText(Messages.SelectDebugConfigDialog_LableText); + + GridData comboLayoutData = new GridData(); + comboLayoutData.grabExcessHorizontalSpace = true; + comboLayoutData.horizontalAlignment = GridData.FILL; + comboLayoutData.horizontalSpan = 1; + + descriptorsCombo = new Combo(container, SWT.READ_ONLY); + descriptorsCombo.setItems(suitableConfiguratios.toArray(new String[0])); + descriptorsCombo.select(0); + descriptorsCombo.setLayoutData(comboLayoutData); + return super.createDialogArea(parent); + } + + @Override + protected void okPressed() + { + ILaunchBarManager launchBarManager = UIPlugin.getService(ILaunchBarManager.class); + try + { + ILaunchDescriptor[] descriptors = launchBarManager.getLaunchDescriptors(); + Optional optDisc = Stream.of(descriptors) + .filter(disc -> disc.getName().contentEquals(descriptorsCombo.getText())).findFirst(); + if (optDisc.isPresent()) + { + launchBarManager.setActiveLaunchDescriptor(optDisc.get()); + } + + } + catch (CoreException e) + { + Logger.log(e); + } + + super.okPressed(); + } + +} diff --git a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/dialogs/SelectLaunchConfigDialog.java b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/dialogs/SelectLaunchConfigDialog.java new file mode 100644 index 000000000..7f657060e --- /dev/null +++ b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/dialogs/SelectLaunchConfigDialog.java @@ -0,0 +1,110 @@ +/******************************************************************************* + * Copyright 2024-2025 Espressif Systems (Shanghai) PTE LTD. All rights reserved. + * Use is subject to license terms. + *******************************************************************************/ +package com.espressif.idf.ui.dialogs; + +import java.util.List; +import java.util.Optional; +import java.util.stream.Stream; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.dialogs.IMessageProvider; +import org.eclipse.jface.dialogs.TitleAreaDialog; +import org.eclipse.launchbar.core.ILaunchBarManager; +import org.eclipse.launchbar.core.ILaunchDescriptor; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; + +import com.espressif.idf.core.logging.Logger; +import com.espressif.idf.ui.UIPlugin; + +public class SelectLaunchConfigDialog extends TitleAreaDialog +{ + private Combo descriptorsCombo; + private final List suitableConfiguratios; + + public SelectLaunchConfigDialog(Shell parentShell, List suitableConfiguratios) + { + super(parentShell); + this.suitableConfiguratios = suitableConfiguratios; + } + + @Override + protected void configureShell(Shell newShell) + { + super.configureShell(newShell); + newShell.setText(Messages.SelectLaunchConfigDialog_Title); + } + + @Override + public void create() + { + super.create(); + setTitle(Messages.SelectLaunchConfigDialog_Title); + setMessage(Messages.SelectLaunchConfigDialog_Text, IMessageProvider.INFORMATION); + } + + @Override + protected void createButtonsForButtonBar(Composite parent) + { + // create OK and Cancel buttons by default + createButton(parent, IDialogConstants.OK_ID, "Launch", true); //$NON-NLS-1$ + createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false); + } + + @Override + protected Control createDialogArea(Composite parent) + { + Composite area = (Composite) super.createDialogArea(parent); + Composite container = new Composite(area, SWT.NONE); + container.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + GridLayout layout = new GridLayout(2, false); + container.setLayout(layout); + + Label descriptorsLabel = new Label(container, SWT.NONE); + descriptorsLabel.setText(Messages.SelectLaunchConfigDialog_LableText); + + GridData comboLayoutData = new GridData(); + comboLayoutData.grabExcessHorizontalSpace = true; + comboLayoutData.horizontalAlignment = GridData.FILL; + comboLayoutData.horizontalSpan = 1; + + descriptorsCombo = new Combo(container, SWT.READ_ONLY); + descriptorsCombo.setItems(suitableConfiguratios.toArray(new String[0])); + descriptorsCombo.select(0); + descriptorsCombo.setLayoutData(comboLayoutData); + return super.createDialogArea(parent); + } + + @Override + protected void okPressed() + { + ILaunchBarManager launchBarManager = UIPlugin.getService(ILaunchBarManager.class); + try + { + ILaunchDescriptor[] descriptors = launchBarManager.getLaunchDescriptors(); + Optional optDisc = Stream.of(descriptors) + .filter(disc -> disc.getName().contentEquals(descriptorsCombo.getText())).findFirst(); + if (optDisc.isPresent()) + { + launchBarManager.setActiveLaunchDescriptor(optDisc.get()); + } + + } + catch (CoreException e) + { + Logger.log(e); + } + + super.okPressed(); + } + +} diff --git a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/dialogs/messages.properties b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/dialogs/messages.properties index 6695fbc8a..c8a637331 100644 --- a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/dialogs/messages.properties +++ b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/dialogs/messages.properties @@ -21,6 +21,12 @@ DeleteResourcesWizard_project_deleteConfigurations=Delete all related configurat HintDetailsTitle=Hint Details FilterMessage=type filter text HintsYmlNotFoundErrMsg={0} is missing. Hints are only supported from esp-idf v5.0 and higher +SelectDebugConfigDialog_LableText=Suitable Debug Configurations: +SelectDebugConfigDialog_Text=To debug a project, the Debug Configuration should be selected. Select a Debug Configuration and click "Debug" +SelectDebugConfigDialog_Title=Select Debug Configuration +SelectLaunchConfigDialog_LableText=Suitable Launch Configurations: +SelectLaunchConfigDialog_Text=To launch a project, the Launch Configuration should be selected. Select a Launch Configuration and click "Launch" +SelectLaunchConfigDialog_Title=Select Launch Configuration WriteFlashDialog_Bin_Path_Lbl=Bin Path: WriteFlashDialog_BinFileErrFormatErrMsg=%s bin file doens't exist WriteFlashDialog_Browse_Btn=Browse diff --git a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/handlers/Messages.java b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/handlers/Messages.java index 79c542845..0552d3a2e 100644 --- a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/handlers/Messages.java +++ b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/handlers/Messages.java @@ -20,6 +20,11 @@ public class Messages extends NLS public static String UpdateEspIdfCommand_JobMsg; public static String UpdateEspIdfCommand_InstallToolsJobMsg; public static String UpdateEspIdfCommand_SuggestToOpenInstallToolsWizard; + public static String MissingDebugConfigurationTitle; + public static String DebugConfigurationNotFoundMsg; + + public static String RunActionHandler_NoProjectQuestionText; + public static String RunActionHandler_NoProjectQuestionTitle; static { diff --git a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/handlers/RunActionHandler.java b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/handlers/RunActionHandler.java new file mode 100644 index 000000000..805a9aa32 --- /dev/null +++ b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/handlers/RunActionHandler.java @@ -0,0 +1,169 @@ +/******************************************************************************* + * Copyright 2024-2025 Espressif Systems (Shanghai) PTE LTD. All rights reserved. + * Use is subject to license terms. + *******************************************************************************/ +package com.espressif.idf.ui.handlers; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.Status; +import org.eclipse.debug.core.DebugPlugin; +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.debug.core.ILaunchManager; +import org.eclipse.debug.core.ILaunchMode; +import org.eclipse.debug.ui.DebugUITools; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.window.Window; +import org.eclipse.jface.wizard.WizardDialog; +import org.eclipse.launchbar.core.ILaunchBarManager; +import org.eclipse.launchbar.ui.ILaunchBarUIManager; +import org.eclipse.launchbar.ui.NewLaunchConfigWizard; +import org.eclipse.launchbar.ui.NewLaunchConfigWizardDialog; +import org.eclipse.launchbar.ui.internal.commands.LaunchActiveCommandHandler; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; + +import com.espressif.idf.core.build.IDFLaunchConstants; +import com.espressif.idf.core.logging.Logger; +import com.espressif.idf.core.util.StringUtil; +import com.espressif.idf.ui.UIPlugin; +import com.espressif.idf.ui.dialogs.SelectDebugConfigDialog; +import com.espressif.idf.ui.dialogs.SelectLaunchConfigDialog; + +@SuppressWarnings("restriction") +public class RunActionHandler extends LaunchActiveCommandHandler +{ + + @Override + public Object execute(ExecutionEvent event) throws ExecutionException + { + try + { + ILaunchBarManager launchBarManager = UIPlugin.getService(ILaunchBarManager.class); + new StopLaunchBuildHandler().stop(); + ILaunchConfiguration config = launchBarManager.getActiveLaunchConfiguration(); + if (config == null) + { + return Status.OK_STATUS; + } + + ILaunchMode launchMode = launchBarManager.getActiveLaunchMode(); + if (launchMode == null) + { + return Status.OK_STATUS; + } + int returnCode = Window.OK; + String projectName = config.getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_NAME, + StringUtil.EMPTY); + if (projectName.isBlank()) + { + Boolean isYes = MessageDialog.openQuestion(Display.getDefault().getActiveShell(), + Messages.RunActionHandler_NoProjectQuestionTitle, + Messages.RunActionHandler_NoProjectQuestionText); + if (isYes) + { + ILaunchBarUIManager uiManager = UIPlugin.getService(ILaunchBarUIManager.class); + uiManager.openConfigurationEditor(launchBarManager.getActiveLaunchDescriptor()); + } + return Status.CANCEL_STATUS; + } + if (launchMode.getIdentifier().equals(ILaunchManager.DEBUG_MODE) + && config.getType().getIdentifier().contentEquals(IDFLaunchConstants.RUN_LAUNCH_CONFIG_TYPE)) + { + List suitableDescNames = findSuitableDescNames(projectName, + IDFLaunchConstants.DEBUG_LAUNCH_CONFIG_TYPE); + if (suitableDescNames.isEmpty()) + { + showMessage(Messages.DebugConfigurationNotFoundMsg); + return Status.CANCEL_STATUS; + } + returnCode = new SelectDebugConfigDialog(Display.getDefault().getActiveShell(), suitableDescNames) + .open(); + } + else if (launchMode.getIdentifier().equals(ILaunchManager.RUN_MODE) + && config.getType().getIdentifier().contentEquals(IDFLaunchConstants.DEBUG_LAUNCH_CONFIG_TYPE)) + { + List suitableDescNames = findSuitableDescNames(projectName, + IDFLaunchConstants.RUN_LAUNCH_CONFIG_TYPE); + returnCode = new SelectLaunchConfigDialog(Display.getDefault().getActiveShell(), suitableDescNames) + .open(); + } + if (returnCode == Window.OK) + { + launchBarManager.setActiveLaunchMode(launchMode); + config = launchBarManager.getActiveLaunchConfiguration(); + DebugUITools.launch(config, launchMode.getIdentifier()); + } + + return Status.OK_STATUS; + } + catch (CoreException e) + { + return e.getStatus(); + } + } + + private List findSuitableDescNames(String projectName, String configType) + { + ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager(); + List configList = new ArrayList<>(); + try + { + configList = Arrays.asList( + launchManager.getLaunchConfigurations(launchManager.getLaunchConfigurationType(configType))); + + } + catch (CoreException e) + { + Logger.log(e); + } + return configList.stream().filter(config -> { + try + { + return config.getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_NAME, StringUtil.EMPTY) + .contentEquals(projectName); + } + catch (CoreException e) + { + Logger.log(e); + } + return false; + }).map(config -> config.getName()).collect(Collectors.toList()); + } + + private void showMessage(final String message) + { + Display.getDefault().asyncExec(new Runnable() + { + @Override + public void run() + { + Shell activeShell = Display.getDefault().getActiveShell(); + boolean isYes = MessageDialog.openQuestion(activeShell, Messages.MissingDebugConfigurationTitle, + message); + if (isYes) + { + + NewLaunchConfigWizard wizard = new NewLaunchConfigWizard(); + WizardDialog dialog = new NewLaunchConfigWizardDialog(activeShell, wizard); + dialog.open(); + try + { + wizard.getWorkingCopy().doSave(); + } + catch (CoreException e) + { + Logger.log(e); + } + } + } + }); + } +} diff --git a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/handlers/messages.properties b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/handlers/messages.properties index 7d487ae6f..69c0d3a4a 100644 --- a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/handlers/messages.properties +++ b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/handlers/messages.properties @@ -12,4 +12,8 @@ PythonCleanCommandHandler_RunningPythonCleanJobName=Running python-clean command StopLaunchBuildHandler_0=Stopping build UpdateEspIdfCommand_JobMsg=Updating ESP-IDF master... UpdateEspIdfCommand_InstallToolsJobMsg=Installing tools... -UpdateEspIdfCommand_SuggestToOpenInstallToolsWizard = A new set of tools might be required to install. Do you want to open the Install Tools dialog? \ No newline at end of file +UpdateEspIdfCommand_SuggestToOpenInstallToolsWizard = A new set of tools might be required to install. Do you want to open the Install Tools dialog? +MissingDebugConfigurationTitle=Missing debug configuration +DebugConfigurationNotFoundMsg=No matching debug configuration was found for the selected project. Do you want to create it? +RunActionHandler_NoProjectQuestionText=The selected configuration does not include a project. Would you like to edit the active launch configuration and specify the project? +RunActionHandler_NoProjectQuestionTitle=Edit Active Configuration?