core/com.nokia.carbide.cpp.sdk.ui/src/com/nokia/carbide/cpp/sdk/ui/shared/BuildTargetsPage.java
/*
* Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:
*
*/
package com.nokia.carbide.cpp.sdk.ui.shared;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.dialogs.DialogPage;
import org.eclipse.jface.dialogs.IDialogPage;
import org.eclipse.jface.viewers.CheckStateChangedEvent;
import org.eclipse.jface.viewers.ICheckStateListener;
import org.eclipse.jface.viewers.IFilter;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.TreeNode;
import org.eclipse.jface.viewers.TreeNodeContentProvider;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.window.Window;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
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.Label;
import org.eclipse.swt.widgets.Link;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.ContainerCheckedTreeViewer;
import org.eclipse.ui.dialogs.PreferencesUtil;
import com.nokia.carbide.cpp.internal.api.sdk.ui.TemplateUtils;
import com.nokia.carbide.cpp.internal.sdk.ui.Messages;
import com.nokia.carbide.cpp.internal.sdk.ui.SDKUIHelpIds;
import com.nokia.carbide.cpp.sdk.core.ISymbianBuildContext;
import com.nokia.carbide.cpp.sdk.core.ISymbianSDK;
import com.nokia.carbide.internal.api.templatewizard.ui.IWizardDataPage;
import com.nokia.carbide.template.engine.ITemplate;
import com.nokia.cpp.internal.api.utils.core.Check;
/**
* Wizard page used to select a list of Carbide.c++ build configurations. Currently used
* by the new project and import bld.inf wizards, but can be used by any wizard that needs
* to get a list of build configs.
*/
public class BuildTargetsPage extends WizardPage implements IWizardDataPage {
protected static final String UID = ".uid"; //$NON-NLS-1$
protected static final String SELECTED_BUILD_CONFIGS_VALUE_KEY = "selectedBuildConfigs"; //$NON-NLS-1$
/**
* @since 1.4
*/
public static final String SBSV2BUILDER = "useSBSv2Builder"; //$NON-NLS-1$
protected static class FilteringContentProviderWrapper implements ITreeContentProvider {
protected ITreeContentProvider wrappedProvider;
protected IFilter filter;
protected IFilter configFilter;
public FilteringContentProviderWrapper(ITreeContentProvider wrappedProvider) {
super();
Check.checkArg(wrappedProvider);
this.wrappedProvider = wrappedProvider;
}
public Object[] getElements(Object inputElement) {
List<Object> filteredElements = new ArrayList<Object>();
Object[] elements = wrappedProvider.getElements(inputElement);
for (int i = 0; i < elements.length; i++) {
Object object = elements[i];
if (filter == null || filter.select(object))
filteredElements.add(object);
}
return filteredElements.toArray();
}
public void dispose() {
wrappedProvider.dispose();
}
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
wrappedProvider.inputChanged(viewer, oldInput, newInput);
}
public Object[] getChildren(Object parentElement) {
List<Object> filteredElements = new ArrayList<Object>();
Object[] elements = wrappedProvider.getChildren(parentElement);
if (elements != null) {
for (int i = 0; i < elements.length; i++) {
Object object = elements[i];
if (configFilter == null || configFilter.select(object))
filteredElements.add(object);
}
}
return filteredElements.toArray();
}
public Object getParent(Object element) {
return wrappedProvider.getParent(element);
}
public boolean hasChildren(Object element) {
return wrappedProvider.hasChildren(element);
}
public void setFilter(IFilter filter) {
this.filter = filter;
}
public void setConfigFilter(IFilter filter) {
this.configFilter = filter;
}
}
static class TemplateSDKFilter implements IFilter {
private ITemplate template;
public void setTemplate(ITemplate template) {
this.template = template;
}
public boolean select(Object toTest) {
if (template == null)
return true;
Check.checkArg(toTest instanceof BuildTargetTreeNode);
ISymbianSDK symbianSDK = ((BuildTargetTreeNode) toTest).getSymbianSDK();
return TemplateUtils.sdkMatchesTemplate(symbianSDK, template);
}
}
private Button filterCheckbox;
protected ContainerCheckedTreeViewer viewer;
private Label configLabel;
private boolean hideFilterCheckbox;
protected FilteringContentProviderWrapper filteringContentProviderWrapper;
private TemplateSDKFilter templateFilter;
private boolean inited;
private boolean useSBSv2Builder;
/**
* Default constructor
*/
public BuildTargetsPage() {
super(Messages.getString("BuildTargetsPage.BuildTargetsTitle")); //$NON-NLS-1$
setTitle(Messages.getString("BuildTargetsPage.SymbianSDKS")); //$NON-NLS-1$
setDescription(Messages.getString("BuildTargetsPage.BuildTargetsDescription")); //$NON-NLS-1$
templateFilter = new TemplateSDKFilter();
}
/**
* see {@link IDialogPage#createControl(Composite)}
*/
public void createControl(Composite parent) {
setPageComplete(false);
setErrorMessage(null);
setMessage(null);
initializeDialogUnits(parent);
Composite composite = new Composite(parent, SWT.NONE);
composite.setLayout(new GridLayout());
composite.setLayoutData(new GridData(GridData.FILL_BOTH));
createControls(composite);
setControl(composite);
getControl().setData(UID, "BuildTargetsPage"); //$NON-NLS-1$
getControl().setData("WizardPage", this); //$NON-NLS-1$
}
private void createControls(Composite parent) {
Font font = parent.getFont();
configLabel = new Label(parent, SWT.LEFT);
configLabel.setFont(font);
configLabel.setText(Messages.getString("BuildTargetsPage.BuildConfigsLabel")); //$NON-NLS-1$
configLabel.setToolTipText(Messages.getString("BuildTargetsPage.BuildConfigsToolTip")); //$NON-NLS-1$
drawSDKConfigView(parent);
filterCheckbox = new Button(parent, SWT.CHECK);
filterCheckbox.setText(Messages
.getString("BuildTargetsPage.FilterText")); //$NON-NLS-1$
filterCheckbox.setSelection(true); // default to checked
if (hideFilterCheckbox)
filterCheckbox.setVisible(false);
else
filteringContentProviderWrapper.setFilter(templateFilter);
filterCheckbox.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
TemplateSDKFilter filter = filterCheckbox.getSelection() ? templateFilter
: null;
filteringContentProviderWrapper.setFilter(filter);
viewer.refresh();
setPageComplete(validatePage());
}
});
filterCheckbox.setData(UID, "filterCheckbox"); //$NON-NLS-1$
addOtherControls(parent);
Link fLink = new Link(parent, SWT.WRAP);
fLink.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
fLink.setText(Messages.getString("BuildTargetsPage.Select_Filtering_Prefs_Link")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
fLink.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 3, 1));
fLink.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
// I don't see a way to open it to a specific tab, only the page
if (Window.OK == PreferencesUtil.createPreferenceDialogOn(getShell(), "com.nokia.carbide.cpp.sdk.ui.preferences.BuildPlatformFilterPage", null, null, 0).open()){ //$NON-NLS-1$
inited = false;
setVisible(true);
drawSDKConfigView(getControl().getParent());
TemplateSDKFilter filter = filterCheckbox.getSelection() ? templateFilter
: null;
filteringContentProviderWrapper.setFilter(filter);
viewer.getTree().clearAll(true);
viewer.refresh();
setPageComplete(validatePage());
}
}
});
setPageComplete(validatePage());
}
private void drawSDKConfigView(Composite parent) {
if (viewer == null){
viewer = new ContainerCheckedTreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
viewer.getTree().setLayoutData(new GridData(GridData.FILL_BOTH));
viewer.setLabelProvider(new LabelProvider());
}
TreeNodeContentProvider treeNodeContentProvider = new TreeNodeContentProvider();
filteringContentProviderWrapper =
new FilteringContentProviderWrapper(treeNodeContentProvider);
viewer.setContentProvider(filteringContentProviderWrapper);
viewer.addCheckStateListener(new ICheckStateListener() {
public void checkStateChanged(CheckStateChangedEvent event) {
setPageComplete(validatePage());
}
});
viewer.getControl().setData(UID, "buildConfigsTree"); //$NON-NLS-1$
viewer.getControl().setData("viewer", viewer); //$NON-NLS-1$
}
/**
* Add more controls after the tree and filter checkbox. Allows subclasses to add
* more controls.
* @since 1.4
*/
protected void addOtherControls(Composite parent) {
}
/**
* If using the template filter checkbox, this allows you to set the
* template to filter on.
* @param template the template to filter on
* @since 1.4
*/
public void setSelectedTemplate(ITemplate template) {
this.templateFilter.setTemplate(template);
// need to init again if they select another template
inited = false;
}
/**
* Hides the "Filter SDKs based on selected template" checkbox
*/
public void setHideFilterCheckbox() {
hideFilterCheckbox = true;
}
protected boolean validatePage() {
boolean isValid = false;
if (viewer.getTree().getItemCount() == 0) {
if (filterCheckbox.getSelection())
setErrorMessage(Messages.getString("BuildTargetsPage.NoMatchingSDKsError")); //$NON-NLS-1$
else
setErrorMessage(Messages.getString("BuildTargetsPage.NoSDKsError")); //$NON-NLS-1$
} else if ((viewer.getCheckedElements()).length > 1) {
setErrorMessage(null);
isValid = true;
} else {
setErrorMessage(Messages.getString("BuildTargetsPage.NoBuildConfigsSelectedError")); //$NON-NLS-1$
}
return isValid;
}
protected void checkPathWithSDKs(IPath path) {
setMessage(null);
for (ISymbianBuildContext context : getSelectedBuildConfigs()) {
Path sdkPath = new Path(context.getSDK().getEPOCROOT());
if (sdkPath.getDevice() != null) {
if (!useSBSv2Builder) {
if (!sdkPath.getDevice().equalsIgnoreCase(path.getDevice())) {
// there are no warnings so set the error message but return true so
// the user can continue if they choose to ignore our warning.
String warning = MessageFormat.format(
Messages.getString("BuildTargetsPage.DifferentDrivesError"), //$NON-NLS-1$
new Object[] { context.getSDK().getUniqueId() });
setMessage(warning, DialogPage.WARNING);
}
}
} else {
// else devices.xml 'epocroot' has no drive spec, so it will use the implicit epocroot
String warning = MessageFormat.format(
Messages.getString("BuildTargetsPage.NoDriveSpecWarning"), //$NON-NLS-1$
new Object[] { context.getSDK().getUniqueId() });
setMessage(warning, DialogPage.WARNING);
}
}
}
/**
* Returns the list of build configs selected in this page to template wizards.
* @return the map of values for this page -
* a singleton map containing the list of selected build configs mapped to the key "selectedBuildConfigs".
*/
public Map<String, Object> getPageValues() {
return Collections.singletonMap(SELECTED_BUILD_CONFIGS_VALUE_KEY, (Object)getSelectedBuildConfigs());
}
/**
* Gets the list of build configs selected in this page
* @return the list of build configs checked in the tree viewer
*/
public List<ISymbianBuildContext> getSelectedBuildConfigs() {
List<ISymbianBuildContext> selectedConfigs = new ArrayList<ISymbianBuildContext>();
Object[] items = viewer.getCheckedElements();
for (int i=0; i<items.length; i++) {
TreeNode node = (TreeNode)items[i];
if (node.getValue() instanceof ISymbianBuildContext) {
selectedConfigs.add((ISymbianBuildContext)node.getValue());
}
}
return selectedConfigs;
}
/**
* See {@link IDialogPage#setVisible(boolean)}
*/
@Override
public void setVisible(boolean visible) {
super.setVisible(visible);
if (visible) {
// set the viewer input when the page becomes visible, but only do it once
// unless the builder has changed.
boolean setInput = true;
Object value = getShell().getData(SBSV2BUILDER);
if (value != null && value instanceof Boolean) {
boolean sbsv2 = ((Boolean)value).booleanValue();
if (sbsv2 == useSBSv2Builder) {
if (inited) {
setInput = false;
}
} else {
useSBSv2Builder = sbsv2;
}
}
if (setInput) {
viewer.setInput(BuildTargetTreeNode.getTreeViewerInput(useSBSv2Builder));
}
if (!inited) {
inited = true;
TreeItem[] items = viewer.getTree().getItems();
if (items != null && items.length == 1) {
viewer.setChecked(items[0].getData(), true);
}
}
setPageComplete(validatePage());
}
}
@Override
public void performHelp() {
PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl().getShell(), SDKUIHelpIds.BUILD_TARGETS_PAGE);
}
}