/*******************************************************************************
* 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.ui.newui.AbstractPage;
import org.eclipse.cdt.ui.newui.ICPropertyTab;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Group;
import org.eclipse.ui.dialogs.PropertyPage;
import de.innot.avreclipse.core.properties.AVRProjectProperties;
import de.innot.avreclipse.core.properties.ProjectPropertyManager;
/**
* This is the parent for all AVR Project property pages.
* <p>
* This class extends CDT AbstractPage to participate in the build configuration
* handling.
* </p>
* <p>
* It acts as an interface to the {@link ProjectPropertyManager}, which manages
* the list of all {@link AVRProjectProperties} of the current project. It also
* maintains the current status of the "per Config" flag and informs all other
* registered AVR Pages when the flag is changed via the
* {@link AbstractAVRPage#setPerConfig(boolean)} method.
* </p>
*
* @see AbstractPage
*
* @author Thomas Holland
* @since 2.2
*
*/
public abstract class AbstractAVRPage extends AbstractPage {
private final static String TEXT_COPYBUTTON = "Copy &Project Settings";
/** The configuration selection group from the AbstractPage class */
private Group fConfigGroup;
/** The "Copy from Project" Button */
private Button fCopyButton;
/** The ProjectPropertyManager for the current project */
protected ProjectPropertyManager fPropertiesManager = null;
/*
* (non-Javadoc)
*
* @see org.eclipse.cdt.ui.newui.AbstractPage#contentForCDT(org.eclipse.swt.widgets.Composite)
*/
@Override
protected void contentForCDT(Composite composite) {
// We override this method to get a reference to the configuration
// selection group.
// This is a hack, but as far as I can see this is the only way to get
// the group without reimplementing most of the AbstractPage class.
super.contentForCDT(composite);
// Get the configuration selection group and set its visibility to the
// current setting of the "per config" flag.
fConfigGroup = findFirstGroup(composite);
loadPropertiesManager();
internalSetPerConfig(fPropertiesManager.isPerConfig());
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.preference.PreferencePage#contributeButtons(org.eclipse.swt.widgets.Composite)
*/
@Override
protected void contributeButtons(Composite parent) {
// Add a "Copy Project Settings" Button in addition to the "Default" and
// "Apply" Buttons from the PreferencePage superclass.
// This button is only actived in the "per Config" mode and will copy
// the project properties to the current configuration.
fCopyButton = new Button(parent, SWT.NONE);
fCopyButton.setText(TEXT_COPYBUTTON);
fCopyButton.setEnabled(isPerConfig());
fCopyButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
performCopy();
}
});
// Increase the number of columns in the parent layout
((GridLayout) parent.getLayout()).numColumns++;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.cdt.ui.newui.AbstractPage#performCancel()
*/
@Override
public boolean performCancel() {
// First remove any modifications made to the AVR properties,
// then let the superclass handle the CDT specific stuff.
AVRPropertyPageManager.performCancel(this);
return super.performCancel();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.cdt.ui.newui.AbstractPage#performOk()
*/
@Override
public boolean performOk() {
// First save and sync the AVR specific Properties,
// then let the superclass handle the CDT specific modifications.
AVRPropertyPageManager.performOK(this, getCfgsEditable());
return super.performOk();
}
/**
* Notifies that the "Copy from Project" button has been pressed.
*/
public void performCopy() {
// Get the per project properties and send them to all out tabs.
AVRProjectProperties projectprops = fPropertiesManager
.getProjectProperties();
if (!noContentOnPage && displayedConfig)
forEach(AbstractAVRPropertyTab.COPY, projectprops);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.cdt.ui.newui.AbstractPage#setVisible(boolean)
*/
@Override
public void setVisible(boolean visible) {
// I override this method just to make sure that the
// ProjectPropertiesManager has been loaded.
// There were some problems before.
if (visible) {
loadPropertiesManager();
}
super.setVisible(visible);
}
/**
* Returns the value of the "per config" flag for this project.
*
* @return <code>true</code> if each build configuration has its own
* properties.
*/
protected boolean isPerConfig() {
loadPropertiesManager();
return fPropertiesManager.isPerConfig();
}
/**
* Set the project "per config" flag.
* <p>
* This method will set the flag and inform all its tabs and all other AVR
* Property pages registered with the page manager about the change.
* </p>
*
* @param flag
* <code>true</code> to enable "per config" settings.
*/
protected void setPerConfig(boolean flag) {
// Test if flag value has changed to avoid the overhead of informing
// everyone for non-changes.
if (flag == isPerConfig()) {
return;
}
// inform all open AVRAbstractPages (including ourself) about the
// changed "per config" flag.
List<PropertyPage> allpages = AVRPropertyPageManager.getPages();
for (PropertyPage page : allpages) {
if ((page != null) && (page instanceof AbstractAVRPage)) {
AbstractAVRPage ap = (AbstractAVRPage) page;
ap.internalSetPerConfig(flag);
}
}
}
/**
* Set the "per config" flag for this page and inform all child tabs about
* the change.
*
* @param flag
* New value of the "per config" flag.
*/
private void internalSetPerConfig(boolean flag) {
fPropertiesManager.setPerConfig(flag);
if (fConfigGroup != null) {
setEnabled(fConfigGroup, flag);
}
// Inform all our Tabs about the change.
// We pass a ICResourceDescription, even if it is not used.
forEach(ICPropertyTab.UPDATE, getResDesc());
// Enable / disable the "Copy from Project" Button
if (fCopyButton != null) {
fCopyButton.setEnabled(flag);
}
}
/**
* get the Properties Manager from the page manager.
*/
private void loadPropertiesManager() {
// This call makes sure that the internal value for the getProject()
// call below has been initialized
checkElement();
// Get the Project Properties Manager (if it has not yet been loaded by
// another page)
fPropertiesManager = AVRPropertyPageManager.getPropertyManager(this,
getProject());
}
/**
* Get the configuration selection group from the parent.
* <p>
* This is a hack to get a reference to the configuration selection group of
* a standard {@link AbstractPage}. The returned reference can be used to
* enable/disable the group as required.
* </p>
*
* @param parent
* a composite having the configuration selection as its first
* group.
* @return A reference to the first group within the given composite
*/
private Group findFirstGroup(Composite parent) {
Control[] children = parent.getChildren();
if (children == null || children.length == 0) {
return null;
}
for (Control child : children) {
if (child instanceof Group) {
return (Group) child;
}
if (child instanceof Composite) {
Group recursive = findFirstGroup((Composite) child);
if (recursive != null) {
return recursive;
}
}
}
return null;
}
/**
* Enable / Disable the given Composite.
*
* @param compo
* A <code>Composite</code> with some controls.
* @param value
* <code>true</code> to enable, <code>false</code> to disable
* the given group.
*/
private void setEnabled(Composite compo, boolean value) {
Control[] children = compo.getChildren();
for (Control child : children) {
child.setEnabled(value);
}
}
}