/******************************************************************************* * Copyright (c) 2008, 2011 Thomas Holland (thomas@innot.de) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Thomas Holland - initial API and implementation *******************************************************************************/ package de.innot.avreclipse.ui.propertypages; import org.eclipse.cdt.core.settings.model.ICConfigurationDescription; import org.eclipse.cdt.managedbuilder.core.BuildException; import org.eclipse.cdt.managedbuilder.core.IConfiguration; import org.eclipse.cdt.managedbuilder.core.IOption; import org.eclipse.cdt.managedbuilder.core.IToolChain; import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.swt.SWT; 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.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.Label; import org.eclipse.swt.widgets.Text; import de.innot.avreclipse.AVRPlugin; import de.innot.avreclipse.PluginIDs; import de.innot.avreclipse.core.properties.AVRDudeProperties; /** * The AVRDude Flash and EEPROM Tab page. * <p> * On this tab, the following properties are edited: * <ul> * <li>Upload of a Flash image</li> * <li>Upload of a EEPROM imagey</li> * </ul> * The hex image files are either taken from the current Build Configuration (this is internally * handled as an empty filename), or from a user selectable image file. * </p> * * @author Thomas Holland * @since 2.2 * */ public class TabAVRDudeFlashEEPROM extends AbstractAVRDudePropertyTab { // The GUI texts private final static String GROUP_FLASH = "Upload Flash Memory Image"; private final static String TEXT_FLASH_NOUPLOAD = "do not upload flash memory image"; private final static String TEXT_FLASH_FROMCONFIG = "from build"; private final static String TEXT_FLASH_FROMFILE = "from Flash memory image file:"; private final static String GROUP_EEPROM = "Upload EEPROM Image"; private final static String TEXT_EEPROM_NOUPLOAD = "do not upload eeprom image"; private final static String TEXT_EEPROM_FROMCONFIG = "from build"; private final static String TEXT_EEPROM_FROMFILE = "from EEPROM image file:"; // The GUI widgets private Button fFlashNoUploadButton; private Button fFlashUploadConfigButton; private Button fFlashUploadFileButton; private Text fFlashFileText; private Button fFlashWorkplaceButton; private Button fFlashFilesystemButton; private Button fFlashVariableButton; private Button fEEPROMNoUploadButton; private Button fEEPROMUploadConfigButton; private Button fEEPROMUploadFileButton; private Text fEEPROMFileText; private Button fEEPROMWorkplaceButton; private Button fEEPROMFilesystemButton; private Button fEEPROMVariableButton; /** The Properties that this page works with */ private AVRDudeProperties fTargetProps; /** The file extensions for image files. Used by the file selector. */ private final static String[] IMAGE_EXTS = new String[] { "*.hex", "*.eep", "*.bin", "*.srec" }; /* * (non-Javadoc) * * @see org.eclipse.cdt.ui.newui.AbstractCPropertyTab#createControls(org.eclipse.swt.widgets.Composite) */ @Override public void createControls(Composite parent) { parent.setLayout(new GridLayout(1, false)); addFlashSection(parent); addEEPROMSection(parent); } /** * Add the flash image selection group. * <p> * This group has three radio buttons: * <ul> * <li>No upload</li> * <li>Upload the file generated in the build configuration</li> * <li>Upload a user selectable file.</li> * </ul> * The last option has a Text control to enter a filename and three buttons to select the * filename from the workplace, the filesystem or from a build variable. * </p> * * @param parent * Parent <code>Composite</code> */ private void addFlashSection(Composite parent) { // Group Setup Group group = new Group(parent, SWT.NONE); group.setText(GROUP_FLASH); group.setLayout(new GridLayout(2, false)); group.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1)); // No Upload Button fFlashNoUploadButton = new Button(group, SWT.RADIO); fFlashNoUploadButton.setText(TEXT_FLASH_NOUPLOAD); fFlashNoUploadButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, 2, 1)); fFlashNoUploadButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { fTargetProps.setWriteFlash(false); enableFlashFileGroup(false); updateAVRDudePreview(fTargetProps); } }); // Upload from Config Button fFlashUploadConfigButton = new Button(group, SWT.RADIO); fFlashUploadConfigButton.setText(TEXT_FLASH_FROMCONFIG); fFlashUploadConfigButton .setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, 2, 1)); fFlashUploadConfigButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { fTargetProps.setWriteFlash(true); fTargetProps.setFlashFromConfig(true); // Set the corresponding "Generate Flash Image" in the current // toolchain(s). setBuildConfigGenerateFlag(PluginIDs.PLUGIN_TOOLCHAIN_OPTION_GENERATEFLASH); enableFlashFileGroup(false); updateAVRDudePreview(fTargetProps); } }); // Upload from file Button fFlashUploadFileButton = new Button(group, SWT.RADIO); fFlashUploadFileButton.setText(TEXT_FLASH_FROMFILE); fFlashUploadFileButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false)); fFlashUploadFileButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { fTargetProps.setWriteFlash(true); fTargetProps.setFlashFromConfig(false); fFlashFileText.setText(fTargetProps.getFlashFile()); enableFlashFileGroup(true); updateAVRDudePreview(fTargetProps); } }); // The image file Text Control fFlashFileText = new Text(group, SWT.BORDER); fFlashFileText.setLayoutData(new GridData(SWT.FILL, SWT.NONE, true, false)); fFlashFileText.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent e) { String newpath = fFlashFileText.getText(); fTargetProps.setFlashFile(newpath); updateAVRDudePreview(fTargetProps); } }); // The three File Dialog Buttons (and a alignment/filler Label), // all wrapped in a composite. Composite compo = new Composite(group, SWT.NONE); compo.setBackgroundMode(SWT.INHERIT_FORCE); compo.setLayoutData(new GridData(SWT.FILL, SWT.NONE, true, false, 2, 1)); compo.setLayout(new GridLayout(4, false)); Label label = new Label(compo, SWT.NONE); // Filler label.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); fFlashWorkplaceButton = setupWorkplaceButton(compo, fFlashFileText); fFlashFilesystemButton = setupFilesystemButton(compo, fFlashFileText, IMAGE_EXTS); fFlashVariableButton = setupVariableButton(compo, fFlashFileText); } /** * Enable / Disable the Flash file selector Controls * * @param enabled * <code>true</code> to enable them, <code>false</code> to disable. */ private void enableFlashFileGroup(boolean enabled) { fFlashFileText.setEnabled(enabled); fFlashWorkplaceButton.setEnabled(enabled); fFlashFilesystemButton.setEnabled(enabled); fFlashVariableButton.setEnabled(enabled); } /** * Add the eeprom image selection group. * <p> * This group has three radio buttons: * <ul> * <li>No upload</li> * <li>Upload the file generated in the build configuration</li> * <li>Upload a user selectable file.</li> * </ul> * The last option has a Text control to enter a filename and three buttons to select the * filename from the workplace, the filesystem or from a build variable. * </p> * * @param parent * Parent <code>Composite</code> */ private void addEEPROMSection(Composite parent) { // Group Setup Group group = new Group(parent, SWT.NONE); group.setText(GROUP_EEPROM); group.setLayout(new GridLayout(2, false)); group.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1)); // No Upload Button fEEPROMNoUploadButton = new Button(group, SWT.RADIO); fEEPROMNoUploadButton.setText(TEXT_EEPROM_NOUPLOAD); fEEPROMNoUploadButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, 2, 1)); fEEPROMNoUploadButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { fTargetProps.setWriteEEPROM(false); enableEEPROMFileGroup(false); updateAVRDudePreview(fTargetProps); } }); // Upload from Config Button fEEPROMUploadConfigButton = new Button(group, SWT.RADIO); fEEPROMUploadConfigButton.setText(TEXT_EEPROM_FROMCONFIG); fEEPROMUploadConfigButton .setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, 2, 1)); fEEPROMUploadConfigButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { fTargetProps.setWriteEEPROM(true); fTargetProps.setEEPROMFromConfig(true); enableEEPROMFileGroup(false); // Set the corresponding "Generate EEPROM Image" in the current // toolchain(s). setBuildConfigGenerateFlag(PluginIDs.PLUGIN_TOOLCHAIN_OPTION_GENERATEEEPROM); updateAVRDudePreview(fTargetProps); } }); // Upload from file Button fEEPROMUploadFileButton = new Button(group, SWT.RADIO); fEEPROMUploadFileButton.setText(TEXT_EEPROM_FROMFILE); fEEPROMUploadFileButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false)); fEEPROMUploadFileButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { fTargetProps.setWriteEEPROM(true); fTargetProps.setEEPROMFromConfig(false); fEEPROMFileText.setText(fTargetProps.getEEPROMFile()); enableEEPROMFileGroup(true); updateAVRDudePreview(fTargetProps); } }); // The image file Text Control fEEPROMFileText = new Text(group, SWT.BORDER); fEEPROMFileText.setLayoutData(new GridData(SWT.FILL, SWT.NONE, true, false)); fEEPROMFileText.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent e) { String newpath = fEEPROMFileText.getText(); fTargetProps.setEEPROMFile(newpath); updateAVRDudePreview(fTargetProps); } }); // The three File Dialog Buttons (and a alignment/filler Label), // all wrapped in a composite. Composite compo = new Composite(group, SWT.NONE); compo.setBackgroundMode(SWT.INHERIT_FORCE); compo.setLayoutData(new GridData(SWT.FILL, SWT.NONE, true, false, 2, 1)); compo.setLayout(new GridLayout(4, false)); Label label = new Label(compo, SWT.NONE); // Filler label.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); fEEPROMWorkplaceButton = setupWorkplaceButton(compo, fEEPROMFileText); fEEPROMFilesystemButton = setupFilesystemButton(compo, fEEPROMFileText, IMAGE_EXTS); fEEPROMVariableButton = setupVariableButton(compo, fEEPROMFileText); } /** * Enable / Disable the EEPROM file selector Controls * * @param enabled * <code>true</code> to enable them, <code>false</code> to disable. */ private void enableEEPROMFileGroup(boolean enabled) { fEEPROMFileText.setEnabled(enabled); fEEPROMWorkplaceButton.setEnabled(enabled); fEEPROMFilesystemButton.setEnabled(enabled); fEEPROMVariableButton.setEnabled(enabled); } /* * (non-Javadoc) * * @see de.innot.avreclipse.ui.propertypages.AbstractAVRPropertyTab#performApply(de.innot.avreclipse.core.preferences.AVRProjectProperties) */ @Override protected void performApply(AVRDudeProperties dstprops) { if (fTargetProps == null) { // updataData() has not been called and this tab has no (modified) // settings yet. return; } // Copy the currently selected values of this tab to the given, fresh // Properties. // The caller of this method will handle the actual saving dstprops.setWriteFlash(fTargetProps.getWriteFlash()); dstprops.setFlashFromConfig(fTargetProps.getFlashFromConfig()); dstprops.setFlashFile(fTargetProps.getFlashFile()); dstprops.setWriteEEPROM(fTargetProps.getWriteEEPROM()); dstprops.setEEPROMFromConfig(fTargetProps.getEEPROMFromConfig()); dstprops.setEEPROMFile(fTargetProps.getEEPROMFile()); // Update the "Generate xxx images" options of // the current toolchain / all toolchains as required if (fTargetProps.getWriteFlash() && !fTargetProps.getFlashFromConfig()) { setBuildConfigGenerateFlag(PluginIDs.PLUGIN_TOOLCHAIN_OPTION_GENERATEFLASH); } if (fTargetProps.getWriteEEPROM() && !fTargetProps.getEEPROMFromConfig()) { setBuildConfigGenerateFlag(PluginIDs.PLUGIN_TOOLCHAIN_OPTION_GENERATEEEPROM); } } /* * (non-Javadoc) * * @see de.innot.avreclipse.ui.propertypages.AbstractAVRPropertyTab#performDefaults(de.innot.avreclipse.core.preferences.AVRProjectProperties) */ @Override protected void performCopy(AVRDudeProperties srcprops) { // Reload the items on this page fTargetProps.setWriteFlash(srcprops.getWriteFlash()); fTargetProps.setFlashFromConfig(srcprops.getFlashFromConfig()); fTargetProps.setFlashFile(srcprops.getFlashFile()); fTargetProps.setWriteEEPROM(srcprops.getWriteEEPROM()); fTargetProps.setEEPROMFromConfig(srcprops.getEEPROMFromConfig()); fTargetProps.setEEPROMFile(srcprops.getEEPROMFile()); updateData(fTargetProps); } /* * (non-Javadoc) * * @see de.innot.avreclipse.ui.propertypages.AbstractAVRPropertyTab#updateData(de.innot.avreclipse.core.preferences.AVRProjectProperties) */ @Override protected void updateData(AVRDudeProperties props) { fTargetProps = props; // Update the flash group // There are three possibilities: // a) No upload wanted: WriteFlash == false // b) Upload from config: WriteFlash == true && FromConfig == true // c) Upload from file: WriteFlash == true && FromConfig == false if (!fTargetProps.getWriteFlash()) { // a) No upload wanted fFlashNoUploadButton.setSelection(true); fFlashUploadConfigButton.setSelection(false); fFlashUploadFileButton.setSelection(false); enableFlashFileGroup(false); } else { // write flash fFlashNoUploadButton.setSelection(false); if (fTargetProps.getFlashFromConfig()) { // b) write flash - use build config filename fFlashUploadConfigButton.setSelection(true); fFlashUploadFileButton.setSelection(false); enableFlashFileGroup(false); } else { // c) write flash - user supplied filename fFlashUploadConfigButton.setSelection(false); fFlashUploadFileButton.setSelection(true); enableFlashFileGroup(true); } } fFlashFileText.setText(fTargetProps.getFlashFile()); // Update the eeprom group // There are three possibilities: // a) No upload wanted: WriteEEPROM == false // b) Upload from config: WriteEEPROM == true && FromConfig == true // c) Upload from file: WriteEEPROM == true && FromConfig == false if (!fTargetProps.getWriteEEPROM()) { // a) don't write eeprom fEEPROMNoUploadButton.setSelection(true); fEEPROMUploadConfigButton.setSelection(false); fEEPROMUploadFileButton.setSelection(false); enableEEPROMFileGroup(false); } else { // write eeprom fEEPROMNoUploadButton.setSelection(false); if (fTargetProps.getEEPROMFromConfig()) { // b) write eeprom - use build config filename fEEPROMUploadConfigButton.setSelection(true); fEEPROMUploadFileButton.setSelection(false); enableEEPROMFileGroup(false); } else { // c) write eeprom - user supplied filename fEEPROMUploadConfigButton.setSelection(false); fEEPROMUploadFileButton.setSelection(true); enableEEPROMFileGroup(true); } } fEEPROMFileText.setText(fTargetProps.getEEPROMFile()); } /** * Set the value of the given toolchain option to <code>true</code>, if the "avrdude" option * is <code>true</code>. * <p> * If the "per Config" flasg is set for the project, only the current config is modified. If * "per config" is not set, then all known build configurations of the project have the * specified toolchain option set. * </p> * <p> * This is supposed to be a convenience for the user, as we assume that if he wants to upload an * image to the MCU, than he also wants the image file to be created during the build. * </p> * * @param optionid * <code>String</code> with the id of the boolean option. */ private void setBuildConfigGenerateFlag(String optionid) { // Test if we are perProject or perConfig. // If per Project, we update the "Generate xxx image" for all // configurations, not just the selected one if (isPerConfig()) { IConfiguration buildcfg = getCfg(); setBuildConfigGenerateFlag(buildcfg, optionid); } else { // per Project settings. // Get all Configurations of this page and set the generate image // flag as required. ICConfigurationDescription[] allconfigdesc = page.getCfgsEditable(); for (ICConfigurationDescription cfgdesc : allconfigdesc) { IConfiguration buildcfg = ManagedBuildManager .getConfigurationForDescription(cfgdesc); setBuildConfigGenerateFlag(buildcfg, optionid); } } } /** * Set the value of a toolchain option of the given build configuration to <code>true</code>, * if the "avrdude" option is <code>true</code>. * <p> * * @param buildcfg * <code>IConfiguration</code> for which the option value is to be set. * @param optionid * <code>String</code> with the id of the boolean option. */ private void setBuildConfigGenerateFlag(IConfiguration buildcfg, String optionid) { IToolChain toolchain = buildcfg.getToolChain(); // get the avrdude option. // The requested option will only be set to true, if the avrdude option // is true as well. IOption avrdudeoption = toolchain .getOptionBySuperClassId("de.innot.avreclipse.toolchain.options.toolchain.avrdude"); IOption option = toolchain.getOptionBySuperClassId(optionid); try { if (avrdudeoption.getBooleanValue()) { ManagedBuildManager.setOption(buildcfg, toolchain, option, true); } } catch (BuildException e) { IStatus status = new Status(Status.ERROR, AVRPlugin.PLUGIN_ID, "Internal Error: Toolchain Option " + optionid + " is not of type Boolean", e); AVRPlugin.getDefault().log(status); } } }