/*******************************************************************************
* 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 java.util.List;
import org.eclipse.cdt.managedbuilder.core.IConfiguration;
import org.eclipse.cdt.managedbuilder.core.IMultiConfiguration;
import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.forms.events.ExpansionAdapter;
import org.eclipse.ui.forms.events.ExpansionEvent;
import org.eclipse.ui.forms.widgets.ExpandableComposite;
import org.osgi.service.prefs.BackingStoreException;
import de.innot.avreclipse.AVRPlugin;
import de.innot.avreclipse.core.properties.AVRDudeProperties;
import de.innot.avreclipse.core.properties.AVRProjectProperties;
/**
* The AVRDude property page.
* <p>
* This page is the container for all avrdude related tabs.
* </p>
* <p>
* For make the avrdude settings more transparent for the user, this page adds a
* avrdude command line preview below the tabs. Tabs based on this page should
* call {@link #updatePreview(AVRProjectProperties)} whenever something is
* modified in the current target properties. The preview will then be updated
* accordingly.
* </p>
* <p>
* As a convenience for the user, the state of the preview section (expanded /
* collapsed) and the size ratio between tabs and preview (based on a
* <code>SashForm</code>) is saved when the page is disposed and restored
* when the page is created.
* </p>
*
* @author Thomas Holland
* @since 2.2
*
*/
public class PageAVRDude extends AbstractAVRPage {
/** The preview <code>Text</code> Control */
private Text fPreviewText;
/** The <code>SashForm</code> for this page */
private SashForm fSashForm;
/** The Preview Composite */
private ExpandableComposite fPreviewCompo;
// The weights for the sash form, depending on the state of the
// ExpandableComposite for the preview text control.
// These values have been determined empirically and look good on my
// system.
private final int[][] fSashWeights = new int[][] { { 80, 20 }, { 95, 5 } };
private final static int EXPANDED = 0;
private final static int COLLAPSED = 1;
private final static String TEXT_PREVIEW = "AVRDude command line preview";
private static final String CLASSNAME = "avrdudepropertypage";
private static final String QUALIFIER = AVRPlugin.PLUGIN_ID + "/" + CLASSNAME;
private static final String KEY_ISEXPANDED = "previewexpanded";
private static final String KEY_WEIGHT_TOP_EXP = "weight_top_expanded";
private static final String KEY_WEIGHT_PREVIEW_EXP = "weight_preview_expanded";
private static final String KEY_WEIGHT_TOP_COLL = "weight_top_collapsed";
private static final String KEY_WEIGHT_PREVIEW_COLL = "weight_preview_collapsed";
/**
* Set up the page for avrdude tabs.
* <p>
* The page is set up as a <code>SashForm</code> with two areas: the main
* part for the normal tabs and a avrdude command line preview box below it.
* </p>
*/
@Override
public void createWidgets(Composite c) {
// Create the sash form
fSashForm = new SashForm(c, SWT.VERTICAL);
fSashForm.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
fSashForm.setLayout(new GridLayout(1, false));
// Let the superclass draw the tabs
super.createWidgets(fSashForm);
// Now add the avrdude command preview box
// This is am ExpandableComposite...
fPreviewCompo = new ExpandableComposite(fSashForm, SWT.NONE,
ExpandableComposite.CLIENT_INDENT | ExpandableComposite.TWISTIE);
fPreviewCompo.setLayoutData(new GridData(SWT.FILL, SWT.NONE, true, false));
fPreviewCompo.setLayout(new GridLayout(1, false));
fPreviewCompo.setText(TEXT_PREVIEW);
fPreviewCompo.addExpansionListener(new ExpansionAdapter() {
@Override
public void expansionStateChanged(ExpansionEvent e) {
// Save the current weight of the sashform and
// load the other set
int[] newweights;
if (fPreviewCompo.isExpanded()) {
fSashWeights[COLLAPSED] = fSashForm.getWeights();
newweights = fSashWeights[EXPANDED];
} else {
fSashWeights[EXPANDED] = fSashForm.getWeights();
newweights = fSashWeights[COLLAPSED];
}
fSashForm.setWeights(newweights);
}
});
// ...with one Text control in it
fPreviewText = new Text(fPreviewCompo, SWT.BORDER | SWT.MULTI | SWT.WRAP | SWT.V_SCROLL);
fPreviewText.setEditable(false);
GridData gd2 = new GridData(SWT.FILL, SWT.FILL, true, true);
gd2.horizontalIndent = 10; // does not work!
fPreviewText.setLayoutData(gd2);
// Add the Text control to the ExpandableComposite
// Read the previous page state from the preferences
IEclipsePreferences prefs = new InstanceScope().getNode(QUALIFIER);
boolean isexpanded = prefs.getBoolean(KEY_ISEXPANDED, false);
fSashWeights[EXPANDED][0] = prefs.getInt(KEY_WEIGHT_TOP_EXP, 80);
fSashWeights[EXPANDED][1] = prefs.getInt(KEY_WEIGHT_PREVIEW_EXP, 20);
fSashWeights[COLLAPSED][0] = prefs.getInt(KEY_WEIGHT_TOP_COLL, 95);
fSashWeights[COLLAPSED][1] = prefs.getInt(KEY_WEIGHT_PREVIEW_COLL, 5);
int[] currentweights = isexpanded ? fSashWeights[EXPANDED] : fSashWeights[COLLAPSED];
// and set the SashForm
// weights (for the collapsed state)
fPreviewCompo.setClient(fPreviewText);
fPreviewCompo.setExpanded(isexpanded);
fSashForm.setWeights(currentweights);
}
/**
* Update the avrdude command line preview.
*
* @param props
* The <code>AVRProjectProperties</code> for which to display
* the preview
*/
public void updatePreview(AVRDudeProperties avrdudeprops) {
// Don't do anything until this page is drawn.
if (fPreviewText == null) {
return;
}
StringBuffer sb = new StringBuffer("avrdude\t");
// Get the current configuration...
IConfiguration buildcfg = ManagedBuildManager.getConfigurationForDescription(getResDesc()
.getConfiguration());
if (buildcfg instanceof IMultiConfiguration) {
sb.append("command preview not available for multiconfiguration!");
} else {
// Get the standard AVRDude arguments as defined in the given
// properties.
List<String> allargs = avrdudeprops.getArguments();
for (String arg : allargs) {
sb.append(arg);
sb.append(" ");
}
sb.append("\n");
// ...and all action arguments for the current configuration
List<String> allactionargs = avrdudeprops.getActionArguments(buildcfg, true);
// append all actions, one per line for better readabilty
for (String arg : allactionargs) {
sb.append("\t\t\t");
sb.append(arg);
sb.append("\n");
}
}
fPreviewText.setText(sb.toString());
}
/*
* (non-Javadoc)
*
* @see org.eclipse.cdt.ui.newui.AbstractPage#isSingle()
*/
@Override
protected boolean isSingle() {
// This page uses multiple tabs
return false;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.cdt.ui.newui.AbstractPage#dispose()
*/
@Override
public void dispose() {
// Get the current SashForm weights
boolean isexpanded = fPreviewCompo != null ? fPreviewCompo.isExpanded() : false;
if (fSashForm != null) {
fSashWeights[isexpanded ? EXPANDED : COLLAPSED] = fSashForm.getWeights();
}
// Save the current GUI state
IEclipsePreferences prefs = new InstanceScope().getNode(QUALIFIER);
prefs.putBoolean(KEY_ISEXPANDED, isexpanded);
prefs.putInt(KEY_WEIGHT_TOP_EXP, fSashWeights[EXPANDED][0]);
prefs.putInt(KEY_WEIGHT_PREVIEW_EXP, fSashWeights[EXPANDED][1]);
prefs.putInt(KEY_WEIGHT_TOP_COLL, fSashWeights[COLLAPSED][0]);
prefs.putInt(KEY_WEIGHT_PREVIEW_COLL, fSashWeights[COLLAPSED][1]);
try {
prefs.flush();
} catch (BackingStoreException e) {
// Log an error that the prefs could not be written
IStatus status = new Status(Status.ERROR, AVRPlugin.PLUGIN_ID,
"Could not write to the preferences", e);
AVRPlugin.getDefault().log(status);
}
super.dispose();
}
}