/******************************************************************************* * This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/cpl-v10.html * * Contributors: * Synopsys, Inc. - ARC GNU Toolchain support *******************************************************************************/ package com.arc.embeddedcdt.gui; import java.io.File; import org.eclipse.cdt.launch.internal.ui.LaunchMessages; import org.eclipse.cdt.launch.internal.ui.LaunchUIPlugin; import org.eclipse.cdt.launch.internal.ui.WorkingDirectoryBlock; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.variables.IStringVariableManager; import org.eclipse.core.variables.VariablesPlugin; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; import org.eclipse.debug.internal.ui.SWTFactory; import org.eclipse.swt.SWT; import org.eclipse.swt.accessibility.AccessibleAdapter; import org.eclipse.swt.accessibility.AccessibleEvent; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Text; import com.arc.embeddedcdt.common.InvalidDirectoryPathException; import com.arc.embeddedcdt.dsf.utils.ConfigurationReader; import com.arc.embeddedcdt.dsf.utils.ConfigurationWriter; /** * This class is used to add working directory block to GDB server setting page for nSIM. Other GDB * servers do not support passing working directory to them, so this block should be there for nSIM * only. Need to override some methods of WorkingDirectoryBlock class due to specifics of * RemoteGdbDebuggerPage: nSIM group might be disposed, so we might not be able to set (or read) * fields' values in IDE directly, as it is done in WorkingDirectoryBlock class. Instead we store * fields' values in class fields. * * Also validity check for working directory value is improved comparing to WorkingDirectoryBlock. * */ @SuppressWarnings("restriction") public class ARCWorkingDirectoryBlock extends WorkingDirectoryBlock { // Shows if 'Use default' is checked private boolean isDefaultWorkingDir = true; // Working directory path containing unresolved variables private String workingDir = ""; /** * A listener to update for text changes and widget selection */ private class WidgetListener extends SelectionAdapter implements ModifyListener { @Override public void modifyText(ModifyEvent e) { workingDir = getAttributeValueFrom(fWorkingDirText); updateLaunchConfigurationDialog(); } @Override public void widgetSelected(SelectionEvent e) { Object source = e.getSource(); if (source == fWorkspaceButton) { handleWorkspaceDirBrowseButtonSelected(); } else if (source == fFileSystemButton) { handleWorkingDirBrowseButtonSelected(); } else if (source == fUseDefaultWorkingDirButton) { isDefaultWorkingDir = fUseDefaultWorkingDirButton.getSelection(); handleUseDefaultWorkingDirButtonSelected(); } } } private WidgetListener fListener = new WidgetListener(); /* * The way that WorkingDirectoryBlock.createControl() method creates working directory group is * not suitable for nSIM page, because created group is contained in just one of the three * columns that nSIM group has. So we specify that working directory group should have one * column. * * The other thing that differs from WorkingDirectoryBlock.createControl() is that we set values * of the working directory path field and "Use default" checkbox here since we do not set these * values in initialize() method because they might be disposed when initialize() is called. */ @Override public void createControl(Composite parent) { Font font = parent.getFont(); Group group = SWTFactory.createGroup(parent, LaunchMessages.WorkingDirectoryBlock_Working_directory, 1, 15, GridData.FILL_HORIZONTAL); setControl(group); fWorkingDirText = new Text(group, SWT.SINGLE | SWT.BORDER); fWorkingDirText.getAccessible().addAccessibleListener(new AccessibleAdapter() { @Override public void getName(AccessibleEvent e) { e.result = LaunchMessages.WorkingDirectoryBlock_Working_directory; } }); GridData gd = new GridData(GridData.FILL_HORIZONTAL); fWorkingDirText.setLayoutData(gd); fWorkingDirText.setFont(font); fWorkingDirText.addModifyListener(fListener); fUseDefaultWorkingDirButton = new Button(group, SWT.CHECK); fUseDefaultWorkingDirButton.setText(LaunchMessages.WorkingDirectoryBlock_Use_default); gd = new GridData(GridData.FILL, GridData.BEGINNING, true, false); fUseDefaultWorkingDirButton.setLayoutData(gd); fUseDefaultWorkingDirButton.setFont(font); fUseDefaultWorkingDirButton.addSelectionListener(fListener); Composite buttonComp = new Composite(group, SWT.NONE); GridLayout layout = new GridLayout(3, false); layout.marginHeight = 0; layout.marginWidth = 0; buttonComp.setLayout(layout); gd = new GridData(GridData.HORIZONTAL_ALIGN_END); buttonComp.setLayoutData(gd); buttonComp.setFont(font); fWorkspaceButton = createPushButton(buttonComp, LaunchMessages.WorkingDirectoryBlock_0, null); fWorkspaceButton.addSelectionListener(fListener); fFileSystemButton = createPushButton(buttonComp, LaunchMessages.WorkingDirectoryBlock_1, null); fFileSystemButton.addSelectionListener(fListener); fVariablesButton = createVariablesButton(buttonComp, LaunchMessages.WorkingDirectoryBlock_17, fWorkingDirText); if (!workingDir.isEmpty()) { fWorkingDirText.setText(workingDir); } fUseDefaultWorkingDirButton.setSelection(isDefaultWorkingDir); handleUseDefaultWorkingDirButtonSelected(); } /* * Check that working directory path field is not empty, resolve variables and check that file * corresponding to obtained path exists. */ @Override public boolean isValid(ILaunchConfiguration config) { setErrorMessage(null); setMessage(null); String workingDir = getAttributeValueFrom(fWorkingDirText); try { resolveDirectoryPath(workingDir); } catch (InvalidDirectoryPathException e) { setErrorMessage(e.getMessage()); return false; } return true; } public static String resolveDirectoryPath(String path) throws InvalidDirectoryPathException { if (path == null || path.isEmpty()) { throw new InvalidDirectoryPathException("Working directory can not be empty."); } IStringVariableManager manager = VariablesPlugin.getDefault().getStringVariableManager(); String workingDirPath; try { workingDirPath = manager.performStringSubstitution(path, true); } catch (CoreException e) { throw new InvalidDirectoryPathException(e.getMessage()); } if (!new File(workingDirPath).isDirectory()) { throw new InvalidDirectoryPathException( "Directory \'" + workingDirPath + "\' does not exist."); } return workingDirPath; } @Override public void initializeFrom(ILaunchConfiguration configuration) { setLaunchConfiguration(configuration); ConfigurationReader cfgReader = new ConfigurationReader(configuration); workingDir = cfgReader.getNsimWorkingDirectoryPath(); isDefaultWorkingDir = cfgReader.getNsimUseDefaultDirectory(); if (workingDir.isEmpty()) { isDefaultWorkingDir = true; } } /* * Save working directory to configuration even if it is default one so that we could read it * from configuration when launching nSIM. This way we have to save value of 'Use default' * checkbox too. */ @Override public void performApply(ILaunchConfigurationWorkingCopy configuration) { ConfigurationWriter cfgWriter = new ConfigurationWriter(configuration); cfgWriter.setNsimWorkingDirectoryPath(workingDir); cfgWriter.setNsimUseDefaultDirectory(isDefaultWorkingDir); } /* * Need to differentiate empty string from null since if working directory path is null it is * considered that default working directory is chosen. So if you press 'Apply' button while * working directory path is empty and then close debug configuration and open it again, you * will see that default directory is chosen. * * We do not allow working directory to be empty either, but I think that behavior described * above is counterintuitive and should be changed to more clear one. */ @Override protected String getAttributeValueFrom(Text text) { return text.getText().trim(); } @Override protected boolean isDefaultWorkingDirectory() { return isDefaultWorkingDir; } }